From: Solar Designer <solar@openwall.com>
To: NeilBrown <neilb@suse.de>
Cc: Stephen Smalley <sds@tycho.nsa.gov>,
Vasiliy Kulikov <segoon@openwall.com>,
kernel-hardening@lists.openwall.com,
James Morris <jmorris@namei.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
linux-kernel@vger.kernel.org, Greg Kroah-Hartman <gregkh@suse.de>,
Andrew Morton <akpm@linux-foundation.org>,
"David S. Miller" <davem@davemloft.net>,
Jiri Slaby <jslaby@suse.cz>,
Alexander Viro <viro@zeniv.linux.org.uk>,
linux-fsdevel@vger.kernel.org,
KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>,
Eric Paris <eparis@redhat.com>, Willy Tarreau <w@1wt.eu>,
Sebastian Krahmer <krahmer@suse.de>
Subject: Re: [kernel-hardening] Re: [PATCH] move RLIMIT_NPROC check from set_user() to do_execve_common()
Date: Thu, 21 Jul 2011 16:48:30 +0400 [thread overview]
Message-ID: <20110721124830.GA1325@openwall.com> (raw)
In-Reply-To: <20110721140936.632d2c8b@notabene.brown>
On Thu, Jul 21, 2011 at 02:09:36PM +1000, NeilBrown wrote:
> On Fri, 15 Jul 2011 15:54:43 -0400 Stephen Smalley <sds@tycho.nsa.gov> wrote:
> > On Fri, 2011-07-15 at 19:26 +0400, Vasiliy Kulikov wrote:
> > > On Fri, Jul 15, 2011 at 09:58 -0400, Stephen Smalley wrote:
> > > > Does this have implications for Android's zygote model? There you have
> > > > a long running uid 0 / all caps process (the zygote), which forks itself
> > > > upon receiving a request to spawn an app and then calls
> > >
> > > > setgroups();
> > > > setrlimit(); setgid(); setuid();
> > >
> > > Is RLIMIT_NPROC forced in your model and setuid() is expected to fail
> > > because of NPROC exceeding? If no, then it is not touched at all.
> >
> > I don't know what their intent is. But it is an example of a case where
> > moving the enforcement from setuid() to a subsequent execve() causes the
> > check to never get applied. As to whether or not they care, I don't
> > know. An app that calls fork() repeatedly will still be stopped, but an
> > app that repeatedly connects to the zygote and asks to spawn another
> > instance of itself would be unlimited.
> >
> > OTOH, the current RLIMIT_NPROC check and lack of setuid() error checking
> > has been a repeated issue for Android.
>
> So where does this leave us? Between a rock and a hard place?
Maybe. I just took a look at Android's Zygote code, as found via Google
Code Search. This appears to be the relevant place:
http://www.google.com/codesearch#atE6BTe41-M/vm/native/dalvik_system_Zygote.c&q=forkAndSpecialize&type=cs&l=439
As we can see, Stephen's description of the sequence of calls is indeed
correct. Also, the return value from setuid() is checked here. :-)
As to which rlimits are actually set, I don't know. This appears to be
configured at a much higher level:
http://www.google.com/codesearch#uX1GffpyOZk/core/java/com/android/internal/os/ZygoteConnection.java&q=ZygoteConnection.java&type=cs&l=247
--rlimit=r,c,m tuple of values for setrlimit() call.
I have no idea whether this --rlimit argument is ever supplied and with
what settings. The intent of supporting it could well be other than
making use of RLIMIT_NPROC specifically.
> It says to me that moving the check from set_user to execve is simply
> Wrong(TM). It may be convenient and do TheRightThing in certain common
> cases, but it also can do the Wrong thing in other cases and I don't think
> that is an acceptable trade off.
I disagree. There's nothing wrong in having the check on execve(),
especially not if we combine it with a check of your proposed flag set
on setuid() (only fail execve() when the flag is set and RLIMIT_NPROC is
still or again exceeded).
> Having setuid succeed when it should fail is simply incorrect.
As far as I'm aware, no standard says that setuid() should fail if it
would exceed RLIMIT_NPROC for the target user. There's a notion of
"appropriate privileges", but what these are is implementation-defined
and it was hardly meant to include rlimits.
> The problem - as we all know - is that user space doesn't always check error
> status properly. If we were to look for precedent I would point to SIGPIPE.
> The only reason for that to exist is because programs don't always check that
> a "write" succeeds so we have a mechanism to kill off processes that don't
> check the error status and keep sending.
>
> I would really like to apply that to this problem ... but that has already
> been suggested (years ago) and found wanting. Maybe we can revisit it?
>
> The value of the SIGPIPE approach (whether it is SIGPIPE or SIGXCPU or
> SIGVEC ... if only there were a SIGXNPROC) is that the program remains in
> complete control. It can find out if the NPROC limit has been exceeded at
> the "right" time.
I don't mind having setuid() signal (and by default actually kill) a
process if it would exceed RLIMIT_NPROC. However, I doubt that others
will agree. BTW, as I told Vasiliy on the kernel-hardening list, I
think we should revisit the "can't happen" memory allocation failure in
set_user() _after_ we have dealt with the RLIMIT_NPROC issue. I would
support the killing of process with SIGKILL or SIGSEGV (as opposed to
return -EAGAIN) on that "can't happen" condition (which might become
possible in a further revision of the code, so better safe than sorry).
Let's actually revisit this later, after having the most important fix
applied.
> The only other solution that I can think of which isn't "Wrong(TM)" is my
> first patch which introduced PF_SETUSER_FAILED.
> With this patch setuid() still fails if it should, so the calling process
> still remains in control. But if it fails to exercise that control, the
> kernel steps in.
>
> Vasiliy didn't like that because it allows a process to ignore the setuid
> failure, perform some in-process activity as root when expecting it to be as
> some-other-user, and only fails when execve is attempted - possibly too late.
I am with Vasiliy on this.
> Against this I ask: what exactly is our goal here?
> Is it to stop all possible abuses? I think not. That is impossible.
> Is it to stop certain known and commonly repeated errors? I think so. That
> is clearly valuable.
Not checking the return value from setuid() and proceeding to do other
work is a known and commonly repeated error. As to whether it is also
common for that other work to involve risky syscalls other than execve(),
I expect that it is, although I did not research this.
> We know (Thanks to Solar Designer's list) that unchecked setuid followed by
> execve is a commonly repeated error, so trapping that can be justified.
> Do we know that accessing the filesystem first is a commonly repeated error?
> If not, there is no clear motive to deal with that problem.
> If, however, it is then maybe a check for PF_SETUSER_FAILED in
> inode_permission() would be the right thing.
>
> Or maybe we just set PF_SETUSER_FAILED and leave it up to some security
> module to decide what to disable or report when that is set?
I feel that we'd be inventing something more complicated yet worse than
simply moving the check would be.
Here's my current proposal:
1. Apply Vasiliy's patch to move the RLIMIT_NPROC check from setuid() to
execve(), optionally enhanced with setting PF_SETUSER_FAILED on
would-be-failed setuid() and checking this flag in execve() (in addition
to repeating the RLIMIT_NPROC check).
2. With a separate patch, add a prctl() to read the PF_SETUSER_FAILED flag.
Android will be able to use this if it wants to.
Yes, this might break RLIMIT_NPROC for Android (I wrote "might" because
I have no idea if it actually sets that specific limit or not) until it
learns to use the new prctl(). But I think that's fine, and it is not a
reason for us to introduce more complexity into the kernel, yet make our
security hardening change more limited. There was never a guarantee (in
any standard or piece of documentation) that setuid() would fail on
exceeding RLIMIT_NPROC, and the Android/Zygote code might not actually
rely on that anyway (there's no clear indication that it does;
RLIMIT_NPROC is not in the code, nor is it mentioned in any comment).
> In short: I don't think there can be a solution that is both completely
> correct and completely safe. I would go for "as correct as possible" with
> "closes common vulnerabilities".
Maybe, and if so I think that one I proposed above falls in this
category as well, but it closes more vulnerabilities (and/or does so
more fully).
Thanks,
Alexander
next prev parent reply other threads:[~2011-07-21 12:48 UTC|newest]
Thread overview: 76+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-12 13:09 [kernel-hardening] RLIMIT_NPROC check in set_user() Vasiliy Kulikov
2011-06-12 13:09 ` Vasiliy Kulikov
2011-07-06 17:36 ` [kernel-hardening] " Vasiliy Kulikov
2011-07-06 17:36 ` Vasiliy Kulikov
2011-07-06 18:01 ` [kernel-hardening] " Linus Torvalds
2011-07-06 18:01 ` Linus Torvalds
2011-07-06 18:59 ` [kernel-hardening] " Vasiliy Kulikov
2011-07-07 7:56 ` Vasiliy Kulikov
2011-07-07 8:19 ` Vasiliy Kulikov
2011-07-12 13:27 ` [kernel-hardening] [PATCH] move RLIMIT_NPROC check from set_user() to do_execve_common() Vasiliy Kulikov
2011-07-12 13:27 ` Vasiliy Kulikov
2011-07-12 21:16 ` [kernel-hardening] " Linus Torvalds
2011-07-12 21:16 ` Linus Torvalds
2011-07-12 23:14 ` [kernel-hardening] " NeilBrown
2011-07-12 23:14 ` NeilBrown
2011-07-13 6:31 ` [kernel-hardening] " Solar Designer
2011-07-13 6:31 ` Solar Designer
2011-07-13 7:06 ` [kernel-hardening] " NeilBrown
2011-07-13 7:06 ` NeilBrown
2011-07-13 20:46 ` [kernel-hardening] " Linus Torvalds
2011-07-13 20:46 ` Linus Torvalds
2011-07-14 0:11 ` [kernel-hardening] " James Morris
2011-07-14 0:11 ` James Morris
2011-07-14 1:27 ` [kernel-hardening] " NeilBrown
2011-07-14 1:27 ` NeilBrown
2011-07-14 15:06 ` [kernel-hardening] " Solar Designer
2011-07-14 15:06 ` Solar Designer
2011-07-15 3:30 ` [kernel-hardening] " NeilBrown
2011-07-15 3:30 ` NeilBrown
2011-07-15 5:35 ` [kernel-hardening] " Willy Tarreau
2011-07-15 5:35 ` Willy Tarreau
2011-07-15 6:31 ` [kernel-hardening] " Vasiliy Kulikov
2011-07-15 7:06 ` NeilBrown
2011-07-15 7:06 ` NeilBrown
2011-07-15 7:38 ` Vasiliy Kulikov
2011-07-15 13:04 ` Solar Designer
2011-07-15 13:04 ` Solar Designer
2011-07-15 13:58 ` [kernel-hardening] " Stephen Smalley
2011-07-15 15:26 ` Vasiliy Kulikov
2011-07-15 19:54 ` Stephen Smalley
2011-07-21 4:09 ` NeilBrown
2011-07-21 12:48 ` Solar Designer [this message]
2011-07-21 18:21 ` Linus Torvalds
2011-07-21 19:39 ` [kernel-hardening] " Solar Designer
2011-07-25 17:14 ` Vasiliy Kulikov
2011-07-25 17:14 ` Vasiliy Kulikov
2011-07-25 23:40 ` [kernel-hardening] " Solar Designer
2011-07-26 0:47 ` NeilBrown
2011-07-26 1:16 ` Solar Designer
2011-07-26 4:11 ` NeilBrown
2011-07-26 14:48 ` [kernel-hardening] [patch v2] " Vasiliy Kulikov
2011-07-26 14:48 ` Vasiliy Kulikov
2011-07-27 2:15 ` [kernel-hardening] " NeilBrown
2011-07-27 2:15 ` NeilBrown
2011-07-29 7:07 ` [kernel-hardening] " Vasiliy Kulikov
2011-07-29 8:06 ` Vasiliy Kulikov
2011-07-29 8:06 ` Vasiliy Kulikov
2011-07-29 8:11 ` [kernel-hardening] [patch v3] " Vasiliy Kulikov
2011-07-29 8:11 ` Vasiliy Kulikov
2011-07-29 8:17 ` [kernel-hardening] " James Morris
2011-07-29 8:17 ` James Morris
2011-07-24 14:32 ` [kernel-hardening] [PATCH] " Solar Designer
2011-07-24 18:02 ` Vasiliy Kulikov
2011-07-14 1:30 ` [kernel-hardening] " KOSAKI Motohiro
2011-07-14 1:30 ` KOSAKI Motohiro
2011-07-13 5:36 ` [kernel-hardening] " KOSAKI Motohiro
2011-07-13 5:36 ` KOSAKI Motohiro
2011-07-14 15:22 ` [kernel-hardening] " Solar Designer
2011-07-14 15:55 ` Vasiliy Kulikov
2011-07-11 16:59 ` [kernel-hardening] RLIMIT_NPROC check in set_user() Solar Designer
2011-07-11 18:56 ` Vasiliy Kulikov
2011-07-13 9:48 ` Solar Designer
2011-07-14 14:15 ` Solar Designer
2011-07-14 14:27 ` Vasiliy Kulikov
2011-07-14 15:14 ` Solar Designer
2011-07-14 16:31 ` [kernel-hardening] compile time warnings in libc for setuid() unused result (was: RLIMIT_NPROC check in set_user()) Vasiliy Kulikov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110721124830.GA1325@openwall.com \
--to=solar@openwall.com \
--cc=akpm@linux-foundation.org \
--cc=davem@davemloft.net \
--cc=eparis@redhat.com \
--cc=gregkh@suse.de \
--cc=jmorris@namei.org \
--cc=jslaby@suse.cz \
--cc=kernel-hardening@lists.openwall.com \
--cc=kosaki.motohiro@jp.fujitsu.com \
--cc=krahmer@suse.de \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=neilb@suse.de \
--cc=sds@tycho.nsa.gov \
--cc=segoon@openwall.com \
--cc=torvalds@linux-foundation.org \
--cc=viro@zeniv.linux.org.uk \
--cc=w@1wt.eu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.