ptrace shows esi mutation across pread64 and pwrite64 syscalls

Bug #1206746 reported by Chris Jones
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
linux (Ubuntu)
Expired
Low
Unassigned

Bug Description

NB: filing this kernel bug against Canonical because the 3.5.0 kernel isn't officially suported upstream [1].

== Steps to reproduce ==

 0. Follow these steps on an *x86* installation; *not* x86-64.
 1. Download the first attachment "Small test case ..." as pwrite64_testcase.c
 2. Download the second attachment "ptrace tracer ..." as regtrace.c
 3. Compile both files
    $ gcc -g -o pwrite64_testcase pwrite64_testcase.c
    $ gcc -g -o regtrace regtrace.c
 4. Verify the files were compiled correctly
    $ file regtrace
You should see output like
    regtrace: ELF 32-bit LSB executable, Intel 80386...
 5. Run the command
    $ ./regtrace ./pwrite64_testcase | grep -A1 181:

== Expected behavior ==

Step (5) above should print output that looks something like

    181: eax:0xffffffda ebx:0x3 ecx:0xff9cde0f edx:0x19
[-->]esi:0xa edi:0x0 ebp:0xff9cde48 eip:0x80486f5
    181: eax:0x19 ebx:0x3 ecx:0xff9cde0f edx:0x19
[-->]esi:0xa edi:0x0 ebp:0xff9cde48 eip:0x80486f5

Notice the "esi:..." values, marked with "[-->]", are both "0xa" in both the entry and exit trace line.

== Actual behavior ==

Step (5) produces output that looks like

    181: eax:0xffffffda ebx:0x4 ecx:0xbffff60a edx:0x19
[-->]esi:0xa edi:0x0 ebp:0xbffff658 eip:0x80488c5
    181: eax:0x19 ebx:0x4 ecx:0xbffff60a edx:0x19
[-->]esi:0x23 edi:0x0 ebp:0xbffff658 eip:0x80488c5

Notice that the "esi:..." values are *NOT* the same: in the entry trace line, esi is "0xa" (the correct value). But in the exit trace line, esi is "0x23" (INCORRECT).

== Brief description ==

The regtrace.c program dumps its tracee's registers at all syscall entry and exits. Per the kernel ABI, all register values *except* eax (return value) are preserved across syscall entry/exit. The pwrite64_testcase.c program uses the pwrite64 and pread64 syscalls in a very basic manner.

The symptom is that the regtrace program seems to show a violation of the kernel ABI, as described above: the esi value (as reported by ptrace) changes across syscall entry/exit. This could either be a ptrace bug, or a bug somewhere else in the kernel, but to userspace the symptom looks the same.

Three kernel builds were tested. Interestingly, the kernel only appears in an x86 kernel.

 * x86, 3.5.0-36: *SHOWS* the bug
 * x86-64, 3.5.0-36: does *NOT* show the bug
 * x86-64, 3.9.11: does *NOT* show the bug

If it helps clarify the nature of the bug, here's a patch that was landed to work around it

https://github.com/mozilla/rr/commit/0d585a0242d8771b7830621ff82abf75976b743b

== System and package information ==

$ lsb_release -rd
Description: Ubuntu 12.04.2 LTS
Release: 12.04
$ apt-cache policy linux-image-3.5.0-36-generic
linux-image-3.5.0-36-generic:
  Installed: 3.5.0-36.57~precise1
  Candidate: 3.5.0-36.57~precise1
  Version table:
 *** 3.5.0-36.57~precise1 0
        500 http://us.archive.ubuntu.com/ubuntu/ precise-updates/main i386 Packages
        100 /var/lib/dpkg/status
$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 42
model name : Intel(R) Core(TM) i7-2630QM CPU @ 2.00GHz

[1] https://www.kernel.org/

Revision history for this message
Chris Jones (jones-chris-g) wrote :
Revision history for this message
Chris Jones (jones-chris-g) wrote :

(The second program referred to above, because I can't provide multiple attachments with one comment.)

Revision history for this message
Chris Jones (jones-chris-g) wrote :

I should add one more but on information: the pwrite64_testcase.c includes three statements for executing the pwrite64 syscall

#if 0
 nr = pwrite(fd, content, sizeof(content), 10);
 nr = syscall(SYS_pwrite64, fd, content, sizeof(content), 10, 0);
#endif
 __asm__ __volatile__("int $0x80"
        : "=a"(nr)
        : "0"(SYS_pwrite64), "b"(fd), "c"(content),
          "d"(sizeof(content)), "S"(10), "D"(0));

The same result is seen with all three calls. The first two should end up using the |systenter| entry point in the VDSO. The third uses the old-fashioned entry point. So the bug manifests across both the systenter/int entry points.

Revision history for this message
penalvch (penalvch) wrote :

Chris Jones, thank you for reporting this bug to Ubuntu. linux-lts-quantal reached EOL on August 2014.
See the following documents for currently supported Ubuntu releases:
https://wiki.ubuntu.com/Releases
https://wiki.ubuntu.com/Kernel/LTSEnablementStack

If this is still reproducible in a supported release, please execute the following in a terminal:
apport-collect 1206746

Otherwise, please mark this as Invalid.

affects: linux-lts-quantal (Ubuntu) → linux (Ubuntu)
Changed in linux (Ubuntu):
importance: Undecided → Low
status: New → Incomplete
Revision history for this message
Launchpad Janitor (janitor) wrote :

[Expired for linux (Ubuntu) because there has been no activity for 60 days.]

Changed in linux (Ubuntu):
status: Incomplete → Expired
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.