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: 10+ 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-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
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 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.