Re: [PATCH PLACEHOLDER 1/3] fs/exec: "always_unprivileged" patch

From: Will Drewry
Date: Sun Jan 15 2012 - 21:04:21 EST


On Sun, Jan 15, 2012 at 4:07 PM, Andrew Lutomirski <luto@xxxxxxx> wrote:
> On Sun, Jan 15, 2012 at 1:32 PM, Casey Schaufler <casey@xxxxxxxxxxxxxxxx> wrote:
>> On 1/15/2012 12:59 PM, Andrew Lutomirski wrote:
>>>
>>> On Sun, Jan 15, 2012 at 12:16 PM, Casey Schaufler
>>> <casey@xxxxxxxxxxxxxxxx>  wrote:
>>>>
>>>> On 1/14/2012 12:22 PM, Linus Torvalds wrote:
>>>>>
>>>>> And yes, I really seriously do believe that is both safer and simpler
>>>>> than some model that says "you can drop stuff", and then you have to
>>>>> start making up rules for what "dropping" means.
>>>>>
>>>>> Does "dropping" mean allowing setuid(geteuid()) for example? That *is*
>>>>> dropping the uid in a _POSIX_SAVED_IDS environment. And I'm saying
>>>>> that no, we should not even allow that. It's simply all too "subtle".
>>>>
>>>>
>>>> I am casting my two cents worth behind Linus. Dropping
>>>> privilege can be every bit as dangerous as granting privilege
>>>> in the real world of atrocious user land code. Especially in
>>>> the case of security policy enforcing user land code.
>>>
>>> Can you think of *any* plausible attack that is possible with my patch
>>> (i.e. no_new_privs allows setuid, setresuid, and capset) that would be
>>> prevented or even mitigated if I blocked those syscalls?  I can't.
>>> (The sendmail-style attack is impossible with no_new_privs.)
>>
>>
>> I am notoriously bad at coming up with this sort of example.
>> I will try, I may not hit the mark, but it should be close.
>>
>> The application is running with saved uid != euid when
>> no-new-privs is set. It execs a new binary, which keeps
>> the saved and effective uids. The program calls setreuid,
>> which succeeds. It opens the saved userid's files.
>
> If you don't trust that binary, then why are you execing it with saved
> uid != euid in the first place?  If you are setting no_new_privs, then
> you are new code and should have at least some basic awareness of the
> semantics.  The exact same "exploit" is possible if you have
> CAP_DAC_OVERRIDE with either no_new_privs semantics -- if you have a
> privilege and you run untrusted code, then you had better remove that
> privilege somehow for the untrusted code.
>
> IOW, *drop privileges if you are a sandbox*.  Otherwise you're screwed
> with or without no_new_privs.

One consideration could be to add do_exit()s at known DAC transitions
(set*id, fcaps). I don't know if that'd be wise, but it would remove
some described ambiguity. The same could be done with exec when the
(e)uid/gid/fcaps change. However, none of that helps with the opaque
LSM data, so that'd have to be left up to the LSMs and the LSM_* flag
you've added.

This does seem subject to bitrot though, and your current approach
certainly suits the needs of the general
don't-do-something-stupid-on-exec that seccomp filter, unprivileged
chroot, unshare, etc all need (which is really nice).

> Another way of saying this is: no_new_privs is not a sandbox.  It's
> just a way to make it safe for sandboxes and other such weird things
> processes can do to themselves safe across execve.  If you want a
> sandbox, use seccomp mode 2, which will require you to set
> no_new_privs.

And even with system call filtering, you'll need to have appropriately
set up accessible files, file descriptors, memory maps, etc if you
want a proper sandbox. There's no single sandbox-equivalent kernel
feature. no_new_privs would be an excellent addition to the sandbox
toolkit. (I've tried to synthesize it in userspace with an empty
capability bounding set, SECURE_NOROOT, and MNT_NOSUID. Having this
in a future-proof task_struct bit form would be amazing.)

cheers!
will
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/