Bug 437712 - ptrace: PTRACE_SETREGS does not set RIP
Summary: ptrace: PTRACE_SETREGS does not set RIP
Status: CLOSED NOTABUG
Alias: None
Product: Red Hat Enterprise Linux 4
Classification: Red Hat
Component: kernel (Show other bugs)
(Show other bugs)
Version: 4.6
Hardware: x86_64 Linux
medium
medium
Target Milestone: rc
: ---
Assignee: Red Hat Kernel Manager
QA Contact: Martin Jenner
URL:
Whiteboard:
Keywords:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2008-03-16 22:13 UTC by Jan Kratochvil
Modified: 2008-03-17 14:09 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2008-03-17 14:09:04 UTC
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

Description Jan Kratochvil 2008-03-16 22:13:42 UTC
Description of problem:
PTRACE_SETREGS(rip=XYZ) followed by PTRACE_GETREGS returns the original RIP value.

Version-Release number of selected component (if applicable):
kernel-smp-2.6.9-68.10.EL.x86_64
(upstream 2.6.22-rc4-git7.x86_64 is OK)
(RHEL-5 kernel-2.6.18-53.1.13.el5.x86_64 is OK)

How reproducible:
Always.

Steps to Reproduce:
1. wget -O user-regs-peekpoke.c
'http://sources.redhat.com/cgi-bin/cvsweb.cgi/~checkout~/tests/ptrace-tests/tests/user-regs-peekpoke.c?cvsroot=systemtap'
2. gcc -o user-regs-peekpoke user-regs-peekpoke.c -Wall -ggdb2 -D_GNU_SOURCE
3. ./user-regs-peekpoke; echo $?

Actual results:
1

Expected results:
0

Additional info:
Register RIP remains unmodified.
wdiff:
$x = {r15 = 506097522914230528, r14 = 1084818905618843912, r13 =
1663540288323457296, r12 = 2242261671028070680,
  rbp = 2820983053732684064, rbx = 3399704436437297448, r11 =
3978425819141910832, r10 = 4557147201846524216,
  r9 = 5135868584551137600, r8 = 5714589967255750984, rax = 6293311349960364368,
rcx = 6872032732664977752,
  rdx = 7450754115369591136, rsi = 8029475498074204520, rdi =
8608196880778817904, orig_rax = 9186918263483431288,
  rip = [-9765639646188044672,-] {+248369046109,+} cs = 51, eflags = 514, rsp =
11501803794301884824, ss = 43, fs_base = 182894074624, gs_base = 0,
  ds = 0, es = 0, fs = 0, gs = 0}

It aborts at the source line 146 (of rev 1.2).

It breaks many other ptrace-testsuite testcases (step-jump-cont, erestart*).

Comment 3 Roland McGrath 2008-03-16 22:52:44 UTC
If I'm reading that wdiff fragment correctly, the old rip value was 0x39d3f2e25d
and you tried to set rip to 0x8786858483828180.  Is that correct?

User addresses on x86_64 cannot be above 0x7fffffffefff on recent kernels, or
above 0x7fbfffffff of RHEL4 kernels.

On most kernels, you can set any rip value you like via ptrace.  For any invalid
value (even the high ones that are permanently invalid), the thread will just
get the normal signal when it resumes at the bad rip.

On RHEL4, the fix for CAN-2005-1762 was kept conservative by making ptrace
disallow setting an rip value that is too high to ever be a valid user address
on that kernel.  On upstream kernels, the issue was fixed a different way that
was more invasive to deep kernel code, but did not affect the ptrace semantics
in this way.

If you try to set rip to the same value with PTRACE_POKEUSR, it will fail with
-EIO.  However, PTRACE_SETREGS just ignores all individual failures from setting
bad values (e.g. also nonzero segment register values with either of the low two
bits clear) and just sets what it can and returns success.

So AFAICT, the issue is trying to set bogus values for rip.  If the tests are
constrained to permissible values, they should work OK on all kernels.  Is that
a sufficient workaround?

Comment 4 Jan Kratochvil 2008-03-17 14:09:04 UTC
(In reply to comment #3)
> If I'm reading that wdiff fragment correctly, the old rip value was
> 0x39d3f2e25d and you tried to set rip to 0x8786858483828180.  Is that correct?

Yes.

> If you try to set rip to the same value with PTRACE_POKEUSR, it will fail with
> -EIO.  However, PTRACE_SETREGS just ignores all individual failures from
> setting bad values

Later I thought PTRACE_SETREGS should -EIO in such case but OK.

> So AFAICT, the issue is trying to set bogus values for rip.  If the tests are
> constrained to permissible values, they should work OK on all kernels.
> Is that a sufficient workaround?

Yes, implemented for `user-regs-peekpoke'.

Thanks for the explanation.



Note You need to log in before you can comment on or make changes to this bug.