[Toybox] Corner Case Theatre.
Rob Landley
rob at landley.net
Fri Sep 11 17:25:33 PDT 2015
Today in "things nobody other than me will probably ever care about",
suid behavior, recursion, path logic, and the multiplexer.
So TOYBOX_SUID support lets you install the toybox binary suid root, and
then TOYFLAG_STAYROOT flag on commands tells it not to drop permissions
in toy_init(), and TOYFLAG_NEEDROOT says to exit if the command is
called WITHOUT root access.
However, if you call a command that calls _another_ command, the first
command can drop permissions and the second command can need them. When
toybox is recursively calling itself rather than doing a fresh exec() to
call commands from the $PATH, it can't regain suid root status.
To work around this, it checks when it _would_ need to regain suid
status and has toy_exec() fail, presumably so you fall through to
execlp() and call the command from the $PATH.
Note: getting the suid bit error message right was the subject of
commits bf1e70f3554c and dc11ed8d3bc9 and that's a hint it's nontrivial.
Note 2: this is why the toybox multiplexer command has TOYFLAG_STAYROOT
without TOYFLAG_NEEDROOT. So it doesn't drop permissions if it has them
(that's the job of the command it calls), but doesn't error out if it
_isn't_ called as root.
Speaking of the multiplexer, you can call it by hand. You can go "toybox
ls" from the command line, and one of the things about it is that it
will never fall back to calling stuff out of the $PATH, if it can't find
a builtin "ls" it will error_exit("Unknown command").
One reason for calling the multiplexer directly is so you can drop a
static toybox binary on the system and control which commands you call
without installing it.
Here's where it gets tricky: "echo hello | xargs toybox umount", where
xargs drops suid permissions, the toybox multiplexer doesn't have
NEEDROOT so doesn't force a re-exec to regain permissions, and umount
needs to re-exec but calling the multiplexer suppresses that behavior.
So umount fails when it otherwise wouldn't necessarily (fstab can have
"user" entries).
Now you can say this is pilot error, but the failure is nonobvious. How
do I indicate _what_ went wrong when you do this?
Hm. Two ways: 1) have the call to the multiplexer re-exec based on
STAYROOT, if it _can_ reacquire permissions it _should_. 2) let the
multiplexer re-exec in the specific case of needing to reacquire suid
permissions, but have it try to exec itself. (Which is a problem if you
called ../toybox and then did something that chdir or chroot before
shelling out to a child command.) 3) have a better error message
although it's not immediately obvious what that would be.
Rob
P.S. Yes there are least three other bugs needing fixing queued up, the
find -exec thing, and install getting the permissions wrong, the comma
parsing logic in cp, and so on. But I've been redoing the darn entry
plumbing for nommu support for a month now and I'd like to get that
finished, and my tree build breaks at the moment until I get this right...
More information about the Toybox
mailing list