tech-kern archive

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

Re: [PATCH] fexecve



On Fri, Nov 16, 2012 at 09:14:14AM +0000, David Holland wrote:
> On Thu, Nov 15, 2012 at 11:58:59PM -0500, Thor Lancelot Simon wrote:
> 
> Well, no. You have to first receive a new file descriptor from
> somewhere, either on an existing socket (requires owning the other
> end) or by opening a new one (not much use in a chroot). Only then you
> can overwrite those ints with the number of the new fd and trigger
> fexecve(); otherwise you'll get EBADF, because presumably in a
> construction like this random file handles that have already been
> passed around won't have been opened for execution; nor would
> executing one of them be likely to do anything useful anyway.

What is this "opened for execution"?  I don't see it in the open(2)
manual page (one can imagine a history of Unix in which there were always
such a thing, and fexecve() were the only way to exec.  that actually
seems elegant and cool, in a way, but the problem is that there is a
long history of Unix *not* doing it that way, and bolting it on now
as an additional way to exec raises issues).

The way I read the standard, if you can open it for read, you can pass
it to me, and if I can receive it, its permissions with regard to me
are evaluated then, according to the ownership and modes of the object
attached to the fd -- not later.

> Meanwhile, if you can own the other end to the point where you can
> open an executable file containing code you supplied and pass it down
> an existing socket connection, you've already done arbitrary code
> execution. If the other end is a W^X chroot, that's not supposed to be
> possible; if the other end isn't chrooted you've probably already won.

Again, the question is "arbitrary code execution as who?"  I don't see
why the assumption is that all chrooted executables should run in identical
chroot environments, with access to the same executables, is warranted.  And
a bug in one should not necessarily make compromise of another so much
easier.

In any event, as we both realize, not a lot of programs receive file
descriptors.

Unfortunately, for any program that does, the existence of fexecfd()
makes shellcode injection trivial.  It turns any attack that can
overwrite a few chosen bytes of RAM into an attack that runs an
arbitrary executable.  I don't think it is a good idea to add new
functionality that empowers attackers in such a way, even if, had
that functionality been designed in from the beginning, it would
have been useful and cool.

The target program, by the way, doesn't _have to_ be in a chroot for
fexecfd to make code injection easier.  It just has to receive file
descriptors at all.

I have been wondering if we could make " can receive executable fds" a
property of the socket, and disable it by default.  Then we would have
to have a way to tag all fds as potentially executable or not, though.
But if we could do something like this, programs receiving fds would
not automaticaly open themselves up to this attack, which would be a
good thing.

The setuid question needs more attention, too.

Thor


Home | Main Index | Thread Index | Old Index