Bug 153303 - /proc files change ownership too soon with PTRACE_O_TRACEEXIT
/proc files change ownership too soon with PTRACE_O_TRACEEXIT
Status: CLOSED WONTFIX
Product: Red Hat Enterprise Linux 4
Classification: Red Hat
Component: kernel (Show other bugs)
4.0
i386 Linux
medium Severity medium
: ---
: ---
Assigned To: Alexander Viro
Brian Brock
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2005-04-04 12:53 EDT by Tom Horsley
Modified: 2012-06-20 12:13 EDT (History)
4 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2012-06-20 12:13:57 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
exitbug.c test program source (3.39 KB, text/plain)
2005-04-04 12:55 EDT, Tom Horsley
no flags Details
test run output from exitbug.c (1.92 KB, text/plain)
2005-04-04 12:56 EDT, Tom Horsley
no flags Details

  None (edit)
Description Tom Horsley 2005-04-04 12:53: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
bugzilla.


Version-Release number of selected component (if applicable):
lernel-2.6.9-5.0.3.EL

How reproducible:
Always

Steps to Reproduce:
1. gcc -o exitbug exitbug.c
2. ./exitbug

  

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.

Additional info:
Comment 1 Tom Horsley 2005-04-04 12:55:28 EDT
Created attachment 112664 [details]
exitbug.c test program source
Comment 2 Tom Horsley 2005-04-04 12:56:28 EDT
Created attachment 112665 [details]
test run output from exitbug.c
Comment 3 john.blackwood 2005-04-28 16:29:24 EDT
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:

[0]kdb> bt                                                                      
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                                          
           0xc01049c8 syscall_call+0x7

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().

Comment 4 john.blackwood 2005-05-25 08:31:45 EDT
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 @@
 		goto fail;
 	}
 	mm->dumpable = 0;
+	mm->coredumped = 1;
 	init_completion(&mm->core_done);
 	spin_lock_irq(&current->sighand->siglock);
 	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 @@
 	task_lock(task);
 	mm = task->mm;
 	if (mm)
-		dumpable = mm->dumpable;
+		dumpable = mm->dumpable | mm->coredumped;
 	task_unlock(task);
 	return dumpable;
 }
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[42]; /* for /proc/PID/auxv */
 
 	unsigned dumpable:1;
+	unsigned coredumped:1;
 	cpumask_t cpu_vm_mask;
 
 	/* Architecture-specific MM context */
Comment 5 Jiri Pallich 2012-06-20 12:13:57 EDT
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.

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