From: Oleg Nesterov <oleg@redhat.com>
To: Kees Cook <keescook@chromium.org>,
Andrew Morton <akpm@linux-foundation.org>
Cc: "security@kernel.org" <security@kernel.org>,
"Eric W. Biederman" <ebiederm@xmission.com>,
Vasily Kulikov <segoon@openwall.com>,
Petr Matousek <pmatouse@redhat.com>,
linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org,
Alex Kelly <alex.page.kelly@gmail.com>,
Josh Triplett <josh@joshtriplett.org>
Subject: [PATCH 1/3] set_dumpable: fix the theoretical race with itself
Date: Sat, 16 Nov 2013 20:01:21 +0100 [thread overview]
Message-ID: <20131116190121.GB22666@redhat.com> (raw)
In-Reply-To: <20131116190057.GA22666@redhat.com>
set_dumpable() updates MMF_DUMPABLE_MASK in a non-trivial way to
ensure that get_dumpable() can't observe the intermediate state,
but this all can't help if multiple threads call set_dumpable()
at the same time.
And in theory commit_creds()->set_dumpable(SUID_DUMP_ROOT) racing
with sys_prctl()->set_dumpable(SUID_DUMP_DISABLE) can result in
SUID_DUMP_USER.
Change this code to update both bits atomically via cmpxchg().
Note: this assumes that it is safe to mix bitops and cmpxchg. IOW,
if, say, an architecture implements cmpxchg() using the locking
(like arch/parisc/lib/bitops.c does), then it should use the same
locks for set_bit/etc.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
fs/exec.c | 49 +++++++++++++++----------------------------------
1 files changed, 15 insertions(+), 34 deletions(-)
diff --git a/fs/exec.c b/fs/exec.c
index bb8afc1..613c9dc 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1621,43 +1621,24 @@ EXPORT_SYMBOL(set_binfmt);
/*
* set_dumpable converts traditional three-value dumpable to two flags and
- * stores them into mm->flags. It modifies lower two bits of mm->flags, but
- * these bits are not changed atomically. So get_dumpable can observe the
- * intermediate state. To avoid doing unexpected behavior, get get_dumpable
- * return either old dumpable or new one by paying attention to the order of
- * modifying the bits.
- *
- * dumpable | mm->flags (binary)
- * old new | initial interim final
- * ---------+-----------------------
- * 0 1 | 00 01 01
- * 0 2 | 00 10(*) 11
- * 1 0 | 01 00 00
- * 1 2 | 01 11 11
- * 2 0 | 11 10(*) 00
- * 2 1 | 11 11 01
- *
- * (*) get_dumpable regards interim value of 10 as 11.
+ * stores them into mm->flags.
*/
void set_dumpable(struct mm_struct *mm, int value)
{
- switch (value) {
- case SUID_DUMP_DISABLE:
- clear_bit(MMF_DUMPABLE, &mm->flags);
- smp_wmb();
- clear_bit(MMF_DUMP_SECURELY, &mm->flags);
- break;
- case SUID_DUMP_USER:
- set_bit(MMF_DUMPABLE, &mm->flags);
- smp_wmb();
- clear_bit(MMF_DUMP_SECURELY, &mm->flags);
- break;
- case SUID_DUMP_ROOT:
- set_bit(MMF_DUMP_SECURELY, &mm->flags);
- smp_wmb();
- set_bit(MMF_DUMPABLE, &mm->flags);
- break;
- }
+ unsigned long old, new;
+
+ do {
+ old = ACCESS_ONCE(mm->flags);
+ new = old & ~MMF_DUMPABLE_MASK;
+
+ switch (value) {
+ case SUID_DUMP_ROOT:
+ new |= (1 << MMF_DUMP_SECURELY);
+ case SUID_DUMP_USER:
+ new |= (1<< MMF_DUMPABLE);
+ }
+
+ } while (cmpxchg(&mm->flags, old, new) != old);
}
int __get_dumpable(unsigned long mm_flags)
--
1.5.5.1
next prev parent reply other threads:[~2013-11-16 19:04 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20131101232521.GA23119@www.outflux.net>
[not found] ` <20131114170337.GA11068@redhat.com>
[not found] ` <CAGXu5jLXpLqjCAMFwKp7t7GpMq4+WBqNzSFC=up+CBvgGDuFCw@mail.gmail.com>
[not found] ` <20131115203652.GA13476@redhat.com>
[not found] ` <CAGXu5j+=LZYAczLVawGPAxd=9VX1FupWZq+2858GsrD1YprL3w@mail.gmail.com>
2013-11-16 19:00 ` [PATCH 0/3] get/set_dumpable() cleanups and theoretical fix Oleg Nesterov
2013-11-16 19:01 ` Oleg Nesterov [this message]
2013-11-18 16:36 ` [PATCH 1/3] set_dumpable: fix the theoretical race with itself Kees Cook
2013-11-16 19:01 ` [PATCH 2/3] kill MMF_DUMPABLE and MMF_DUMP_SECURELY Oleg Nesterov
2013-11-16 19:01 ` Oleg Nesterov
2013-11-18 18:38 ` Kees Cook
2013-11-18 19:16 ` Oleg Nesterov
2013-11-18 19:27 ` Kees Cook
2013-11-18 19:37 ` Oleg Nesterov
2013-11-16 19:02 ` [PATCH 3/3] make __get_dumpable/get_dumpable inline, kill fs/coredump.h Oleg Nesterov
2013-11-18 18:39 ` Kees Cook
2013-11-18 18:39 ` Kees Cook
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=20131116190121.GB22666@redhat.com \
--to=oleg@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=alex.page.kelly@gmail.com \
--cc=ebiederm@xmission.com \
--cc=josh@joshtriplett.org \
--cc=keescook@chromium.org \
--cc=linux-arch@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pmatouse@redhat.com \
--cc=security@kernel.org \
--cc=segoon@openwall.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).