[CFT][PATCH 2/7] userns: Don't allow setgroups until a gid mapping has been setablished

Eric W. Biederman ebiederm at xmission.com
Mon Dec 8 22:26:54 UTC 2014


Andy Lutomirski <luto at amacapital.net> writes:

> On Mon, Dec 8, 2014 at 2:07 PM, Eric W. Biederman <ebiederm at xmission.com> wrote:
>>
>> setgroups is unique in not needing a valid mapping before it can be called,
>> in the case of setgroups(0, NULL) which drops all supplemental groups.
>>
>> The design of the user namespace assumes that CAP_SETGID can not actually
>> be used until a gid mapping is established.  Therefore add a helper function
>> to see if the user namespace gid mapping has been established and call
>> that function in the setgroups permission check.
>>
>> This is part of the fix for CVE-2014-8989, being able to drop groups
>> without privilege using user namespaces.
>>
>> Cc: stable at vger.kernel.org
>> Signed-off-by: "Eric W. Biederman" <ebiederm at xmission.com>
>> ---
>>  include/linux/user_namespace.h | 9 +++++++++
>>  kernel/groups.c                | 7 ++++++-
>>  2 files changed, 15 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
>> index e95372654f09..41cc26e5a350 100644
>> --- a/include/linux/user_namespace.h
>> +++ b/include/linux/user_namespace.h
>> @@ -37,6 +37,15 @@ struct user_namespace {
>>
>>  extern struct user_namespace init_user_ns;
>>
>> +static inline bool userns_gid_mappings_established(const struct user_namespace *ns)
>> +{
>> +       bool established;
>> +       smp_mb__before_atomic();
>> +       established = ACCESS_ONCE(ns->gid_map.nr_extents) != 0;
>> +       smp_mb__after_atomic();
>> +       return established;
>> +}
>
> I don't think this works on all platforms.  ACCESS_ONCE is not atomic
> in the smp_mb__before_atomic sense.

Documentation/atomic_ops.txt documents ACCESS_ONCE as being equivalent
to atomic_read() and atomic_set().  smp_mb__before_atomic and
smp_mb__after_atomic() are Documented as working with atomic_read and
atomic_set.  Maybe it is a stretch to use them but it doesn't seem like
much of a stretch.

Further at this point I don't know that any barriers are strictly
needed, beyond the ACCESS_ONCE.  However since x86 does all of the
ordering in hardware that I need I am not going to find any bugs that
don't require a barrier.

All I really want is the same level of barriers I would get if I used a
spin-lock protected data structure so I don't need to worry about
crazy smp issues that happen when the hardware decides it is safe to
reorder things.

Eric


>> +
>>  #ifdef CONFIG_USER_NS
>>
>>  static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
>> diff --git a/kernel/groups.c b/kernel/groups.c
>> index 02d8a251c476..e0335e44f76a 100644
>> --- a/kernel/groups.c
>> +++ b/kernel/groups.c
>> @@ -6,6 +6,7 @@
>>  #include <linux/slab.h>
>>  #include <linux/security.h>
>>  #include <linux/syscalls.h>
>> +#include <linux/user_namespace.h>
>>  #include <asm/uaccess.h>
>>
>>  /* init to 2 - one for init_task, one to ensure it is never freed */
>> @@ -217,7 +218,11 @@ bool may_setgroups(void)
>>  {
>>         struct user_namespace *user_ns = current_user_ns();
>>
>> -       return ns_capable(user_ns, CAP_SETGID);
>> +       /* It is not safe to use setgroups until a gid mapping in
>> +        * the user namespace has been established.
>> +        */
>> +       return userns_gid_mappings_established(user_ns) &&
>> +               ns_capable(user_ns, CAP_SETGID);
>>  }
>>
>>  /*
>> --
>> 1.9.1
>>
>
> --Andy


More information about the Containers mailing list