tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: [PATCH] fexecve



On Thu, Nov 15, 2012 at 04:57:24PM -0500, Thor Lancelot Simon wrote:
> On Thu, Nov 15, 2012 at 09:46:13PM +0000, David Holland wrote:
> > On Thu, Nov 15, 2012 at 11:03:15AM -0500, Thor Lancelot Simon wrote:
> >  > > Here is a patch that implements fexecve(2) for review:
> >  > > http://ftp.espci.fr/shadow/manu/fexecve.patch
> >  > 
> >  > This strikes me as profoundly dangerous.  Among other things, it
> >  > means you can't allow any program running in a chroot to receive
> >  > unix-domain messages any more since they might get passed a file
> >  > descriptor to code they should not be able to execute.
> > 
> > I have two immediate reactions to this: (1) being able to pass
> > executables to something untrusted in a controlled manner sounds
> > useful, not dangerous
> 
> Sorry to cherry-pick one more point for the moment:  Considered in a vacuum,
> I agree with your reaction #1 above.  The problem is that there is a great
> deal of existing code in the world which receives file descriptors and which
> is not designed with the possibility that they might then be used to exec.
> 
> With that history, I don't see a clear way to make this safe (for example
> by restricting which descriptors can be passed to chrooted processes) 
> without breaking code that assumes it can pass file descriptors without such
> restrictions.

Why restrict what descriptors can be passed?  It seems that you could
restrict what you can with the descriptors after they are passed.

It seems like something like the following can be made to work:

Label a file descriptor with the root that was in effect when it was created
by, say, open(2).  The effective root will never change over the
lifetime of that descriptor.

Call the root of a descriptor z, root(z).

Let fexecve(zfd, ...) compare the root of the kernel file descriptor
corresponding to zfd with the effective root and return EPERM if they're
unequal.

Say that process 1 with effective root pqr opens an executable,
fd = open("./setuidprog", ...). Call fd's corresponding kernel
descriptor z.  Now process 1 passes z to process 2, whose effective
root is stu != pqr.  Process 2 tries to fexecve() the descriptor, but
root(z) != stu so fexecve() returns EPERM.

Maybe we can weaken fexecve()'s requirement on the effective root of z
to "root(z) must be reachable from the effective root," but I think that
that might be much more complicated.

fexecve() isn't the only call on which you may want to enforce a
"root(descriptor) == effective root" restriction.  You may want to
enforce it on read(2) and write(2), too.

Also, enforcing access along "effective roots" lines may be inflexible
or unwieldy, maybe a more abstract notion of "process coalition" is
better.  Let each new root have a corresponding new coalition, but
perhaps we should be able to create a new coalition without changing
root, and change root without changing coalition.

Dave

-- 
David Young
dyoung%pobox.com@localhost    Urbana, IL    (217) 721-9981


Home | Main Index | Thread Index | Old Index