su problem with 4.4.93
steve houseman
steve at houseman.demon.co.uk
Fri Jan 31 09:17:05 UTC 2003
Nate Eldredge wrote (about the email from steve houseman) ...
>>
>> Hello,
>>
>> I thought I sent this once, I was sure I'd sent this the next time.
>> so here it is for the third time ... I've changed my devel list to
>> non-batch and with ack so I should know sooner if it doesnt arrive.
>>
>>
>> linux kernel 2.4.18
>>
>> In trying to recreate this problem in a simpler example, it seems
>> as though it is linked to tracing suid executables.... which
>> I assume is ok ?
>
>No. The reason is that tracing permits you to read and write the traced
>process's memory. So if an ordinary user could trace suid programs, you
>could trace su (or your favorite suid), and alter its code to immediately
>do exec("/bin/sh"). Which would be bad for security.
>
>So if a traced process tries to exec() a suid program, the kernel drops
>the suid part and runs the new program as the original user. Unless,
that
>is, the original process had the ability to do setuid(2) anyway (i.e. was
>root-owned) which would make this moot.
>
>This is in compute_creds, under if (!capable(CAP_SETUID)). It's entirely
>a kernel issue and AFAIK should have nothing to do with strace. If any
>system really allows you to strace a suid binary as non-root and lets it
>keep its root privileges, it has a glaring security hole and should not
be
>used.
>
Many apologies for wasting peoples time .... I was too involved with
this and assumed you all knew what I meant :-)
This was ONLY in the context of running strace as root.
Also I didnt say, but I (nearly) always run with the
-o/tmp/dbinxxx -f -F -v -tt flags .... sorry I didnt make that
clear.... I was trying to be brief (and failing badly :-( ).
My original post on "su problem with 4.4.93" did not even mention
that it was running as root, although it was obvious(?) from the
context.
I had assumed that running strace as root, should allow me to
su steve, then su back to root... but doing this fails, also
running my test suid exe (aa) shows it doesnt pick up the suid.
>>
>> I wrote a trivial exe (aa) which printed out its uid and euid
>> and set it owned by root and suid (to mimic su)
>>
>> strace -o/tmp/dbin -f -F -tt -v su steve -c aa
>> prints out euid=1000 ie steve , but a straight run as steve of .aa
>> shows euid=0 as expected.
>
>That's correct behavior.
>
>> This is the same for 4.4.2 and 4.4.93 ... unlike the original problem
>> (with wine install) that I reported which occured on 4.4.93 but
>> 4.4.2 was ok.
>>
>>
>> Investigating the suid problem with printk s in the kernel,
>> the problem area seems to be compute_creds and a chunk of code
>> that I dont understand what its purpose is ... but if
>> ptrace & PT_PTRACE_CAP were true then it wouldnt go that way ,
>
>But this is only true when you are already root.
>
>> ie must_not_trace_exec would return zero, and
>> it would work... ie the bprm euid wouldnt be reset.
>> I guess that in the
>> /usr/src/linux-2.4.18/arch/i386/kernel/ptrace.c
>>
>> asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
>> <snippety>
>> if (request == PTRACE_TRACEME) {
>> /* are we already being traced? */
>> if (current->ptrace & PT_PTRACED)
>> goto out;
>> /* set the ptrace bit in the process flags. */
>> current->ptrace |= PT_PTRACED;
>>
>>
>> if( current->uid == 0 || // <<<<< the 3 lines
>> current->euid == 0 )
>> current->ptrace |= PT_PTRACE_CAP ;
>> ret = 0;
>> goto out;
>> }
>>
>>
>> then this would be set when a traceme request was made as root,
>> and this capability (or something) ought to be propagated to
>> children (and I *think* it would be).
>
>Nope. current->ptrace is only propagated to children by clone(2) with
the
>CLONE_PTRACE flag, and not by normal fork(2). Which is correct: you
don't
>want fork() to randomly create traced processes which you weren't
>expecting to have to trace.
>
You may be right but a cursory look at do_fork shows
*p = *current; // ie everything is made the same
which would copy ptrace, and the only other use of ptrace in do_fork,
if the test to see if it is already being traced and diddles with
the p_pptr .
Also, I would not expect a coder to stick CLONE_PTRACE in a clone
call , it isnt something that a normal coder would think of, only
a security consious one who would want a CLONE_DONT_PTRACE flag
... unless I misunderstand this ... but I'm not getting into
any philosophical discussion about this :-) B.
>
>> The above seems to work , but I dont know enough to know whether
>> it is sensible or barmy ... and whether an attach (vs running
>> a prog) needs anything.
>
>To attach to a suid process you have to be root.
>
>> It seems to work in that an strace of su steve -c aa works
>
>Sure. When you strace su, su runs as you, without root privileges. But
>when it forks to run aa, the child is not traced and so is perfectly
>capable of execing a suid binary (aa) without interference.
>
>> and the wine install works .... why did this (wine install)
>> work under 4.4.2 and not 4.4.93 ... I have no idea.... maybe
>> there is another problem lurking .
>
my testing using printk in prepare_binprm and compute_creds to show
the path taken, the caps and the uid,euid for an strace as root,
of su steve -c ./aa , has strace running, fork, child calls traceme ,
child execs su , su sets uid/euid, immediately before calling bash.
prepare_binprm bash shows euid/uid = 1000 ,
compute_creds bash shows all caps = 0 (?) and leaves with caps=0,
euid=1000
bash execs aa ,
prepare_binprm aa -. euid.uid=1000 mode=(104711)
mode & S_ISUID i_uid(0) beuid(0)
prepare_binprm 2 pid(272)cuid(1000) ceuid(1000) beuid(0)
all as epected
compute_creds for aa shows caps = 0 , must_not_trace_exec is true
as PT_PTRACE_CAP is not set , and as all caps are zero
then it hits the !capable(CAP_SETUID) and wipes the
bprm->e_uid ... and loses the suid.
I dont know what the expected bits of that are but end result is a
non suid suid , when being traced as root.
I have attached the printk output below (not that it will make much sense)
and checking the euid or uid == 0 in sys_ptrace for PTRACE_TRACEME
and then setting PT_PTRACE_CAP does fix it ... whether that is the
right way or whether the path should have gone some other way ...
I dont know.
Cheers,
Steve Houseman
printk for strace etc as described above
ceuid = current->uid , cp,ci,ce = caps permitted,inheritable,effective
beuid = bprm->e-uid mode = mode in octal of inode
the following line is the end of strace printk's
compute_creds 2 pid(271) ceuid(0) cp(37777777377) ci(0) ce(37777777377)
exec su printk's
prepare_binprm 1 pid(272)cuid(0) ceuid(0) beuid(0) mode(104711)
mode & S_ISUID i_uid(0) beuid(0)
prepare_binprm 2 pid(272)cuid(0) ceuid(0) beuid(0)
compute_creds 0 pid(272) np(37777777377) wk(0)cp(37777777377) ci(0)
ce(377777773
77)
compute_creds 1 pid(272) cuid(0) ceuid(0) beuid(0)
compute_creds 2 pid(272) ceuid(0) cp(37777777377) ci(0) ce(37777777377)
exec bash printk's
prepare_binprm 1 pid(272)cuid(1000) ceuid(1000) beuid(1000) mode(100755)
mode & S_ISUID NOT true
prepare_binprm 2 pid(272)cuid(1000) ceuid(1000) beuid(1000)
compute_creds 0 pid(272) np(0) wk(0)cp(0) ci(0) ce(0)
compute_creds 1 pid(272) cuid(1000) ceuid(1000) beuid(1000)
compute_creds 2 pid(272) ceuid(1000) cp(0) ci(0) ce(0)
exec aa printk's
prepare_binprm 1 pid(272)cuid(1000) ceuid(1000) beuid(1000) mode(104711)
mode & S_ISUID i_uid(0) beuid(0)
prepare_binprm 2 pid(272)cuid(1000) ceuid(1000) beuid(0)
compute_creds 0 pid(272) np(37777777377) wk(0)cp(0) ci(0) ce(0)
compute_creds 0.5 pid(272) ptw : mnte(3) p->t(1) cfsc(1)cfc(1) csc(1)
compute_creds 7 pid(272)!capable(CAP_SETUID) <<<<<
compute_creds 1 pid(272) cuid(1000) ceuid(1000) beuid(1000)
compute_creds 2 pid(272) ceuid(1000) cp(0) ci(0) ce(0)
--
currently : | for strace, an annotator see -
steve at houseman demon co uk | http://www.houseman.demon.co.uk/
More information about the Strace-devel
mailing list