Red Hat Bugzilla – Bug 153303
/proc files change ownership too soon with PTRACE_O_TRACEEXIT
Last modified: 2012-06-20 12:13:57 EDT
From Bugzilla Helper:
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; T312461)
Description of problem:
When using the PTRACE_SETOPTIONS feature of ptrace and turning on the
PTRACE_O_TRACEEXIT flag (none of which are documented anywhere other than
the kernel source - which might should be a separate bug :-), I find that
the /proc files for the debugged process have changed ownership to root
once the process stoped with the SIGTRAP for the exit event.
Though the lack of documentation makes it hard to know for sure, I
always got the impression that the exit option was intended to let
the user see what went wrong before the process completely vanishes.
Part of the useful information to poke around in is obtained from the
/proc files (maps for instance might be useful to verify if your
stack pointer is off in the weeds). If the ownership of the /proc files
has changed to root, it is hard to get useful information out of them :-).
I have a sample program and test run listing I will attach to this
Version-Release number of selected component (if applicable):
Steps to Reproduce:
1. gcc -o exitbug exitbug.c
Actual Results: The first ls -l shows the files owned by the user running the process.
The second ls -l shows the files owned by root.
Expected Results: I'm still debugging the process and it hasn't (completely) gone
away yet - the files should still be owned by the original user.
Created attachment 112664 [details]
exitbug.c test program source
Created attachment 112665 [details]
test run output from exitbug.c
I'm not sure what the 'solution' might be, but here's what is going on...
This exitbug.c test has the target ptraced process execute an "int $1"
instruction. This causes a do_general_protection() fault.
When the exitbug parent process passes on the signal to the target process
on the PTRACE_CONT call (the signal is SIGSEGV), the signal code then
will call do_coredump().
The do_coredump() code will clear the task->dumpable field in the target
tasks's task structure. At this point we're "hosed".
On the subsequent "ls" command to read the /pid/n files, the filesystem
code will call the /proc "pid_revalidate()" routine:
Stack traceback for pid 2273
0xf4f88d80 2273 2271 1 0 R 0xf4f89020 *ls
EBP EIP Function (args)
0xf3867e14 0xc019e6ee pid_revalidate+0x7e (0xf48cbb74, 0xf3867f10, 0xc19b8838, )
0xf3867e34 0xc017b4bc do_lookup+0x75 (0xf3867f10, 0xf3867ea4, 0xf3867e9c, 0xf38)
0xf3867ec0 0xc017be76 link_path_walk+0x993 (0xbfffe538, 0x1000, 0xf3aa0000, 0xf)
0xf3867edc 0xc017c669 path_lookup+0x185 (0xbfffe538, 0x805d217, 0x0, 0xf3867f68)
0xf3867efc 0xc017c80b __user_walk+0x32 (0x0, 0xc06568f0, 0x8db0000, 0xf3fdad6c,)
0xf3867f58 0xc0176cfc vfs_lstat+0x1e (0xbfffe538, 0xf3867f68, 0x296, 0x296, 0xf)
0xf3867fbc 0xc0177405 sys_lstat64+0x1b
pid_revalidate() calls task_dumpable(), and:
- if mm is gone,
- OR if mm->dumpable == 0,
then task_dumpable() returns 0.
When task_dumpable() returns 0, the pid_revalidate() routine clears the
uid and gid fields of the /proc file.
I guess that this code is trying to detect when a task/process is not
really 'viewable' anymore.
So it's not really where the PT_TRACE_EXIT check is located in the
kernel exit code, but rather the fact that this process has already called
do_coredump() and made itself 'un-dumpable'.
Note that when the ptraced target task exits normally (without having
to call do_coredump()), the /proc/nn files remain unchanged at the point
in time when we hit the PT_TRACE_EXIT code in do_exit().
I would like to submit a suggestion for a fixing this problem.
The diffs are below. Possibly these changes, or something
similar to them would provide a suitable fix.
The changes are:
- Add a new coredumped bit to the mm_struct.
- In do_coredump() when the mm->dumpable bit is cleared, set the
mm->coredumped bit. This is the only time that the mm->coredumped bit
is non-zero. Note that the mm->coredumped bit is set only if the
mm->dumpable bit was set at the time that do_coredump() was called.
- In the /proc task_dumpable() routine, return non-zero if either
mm->coredumped or mm->dumpable is set. The keeps the uid/gid indoe
fields of the /proc/[pid] files from getting set to 0 after a
do_coredump() has occurred and the process stopped in exit due to
the PTRACE_O_TRACEEXIT flag.
These changes preserve the validity of the existing places in the code
that examine the mm->dumpable bit for security access reasons, such as
setuid operations, etc.
Thank you for your considerations in this matter.
diff -ru old/fs/exec.c new/fs/exec.c
--- old/fs/exec.c 2005-05-25 08:09:11.481469350 -0400
+++ new/fs/exec.c 2005-05-25 08:10:08.643798039 -0400
@@ -1441,6 +1441,7 @@
mm->dumpable = 0;
+ mm->coredumped = 1;
current->signal->flags = SIGNAL_GROUP_EXIT;
diff -ru old/fs/proc/base.c new/fs/proc/base.c
--- old/fs/proc/base.c 2005-05-25 08:09:19.687368419 -0400
+++ new/fs/proc/base.c 2005-05-25 08:10:40.445531072 -0400
@@ -1029,7 +1029,7 @@
mm = task->mm;
- dumpable = mm->dumpable;
+ dumpable = mm->dumpable | mm->coredumped;
diff -ru old/include/linux/sched.h new/include/linux/sched.h
--- old/include/linux/sched.h 2005-05-25 08:09:01.564801555 -0400
+++ new/include/linux/sched.h 2005-05-25 08:11:23.955606630 -0400
@@ -235,6 +235,7 @@
unsigned long saved_auxv; /* for /proc/PID/auxv */
+ unsigned coredumped:1;
/* Architecture-specific MM context */
Thank you for submitting this issue for consideration in Red Hat Enterprise Linux. The release for which you requested us to review is now End of Life.
Please See https://access.redhat.com/support/policy/updates/errata/
If you would like Red Hat to re-consider your feature request for an active release, please re-open the request via appropriate support channels and provide additional supporting details about the importance of this issue.