Thread (22 messages) 22 messages, 4 authors, 2019-03-05

Re: [PATCH 2/2] LSM: SafeSetID: gate setgid transitions

From: "Serge E. Hallyn" <serge@hallyn.com>
Date: 2019-02-19 18:27:00

On Tue, Feb 19, 2019 at 09:04:10AM -0800, Micah Morton wrote:
On Sun, Feb 17, 2019 at 10:49 AM Serge E. Hallyn [off-list ref] wrote:
quoted
On Fri, Feb 15, 2019 at 02:22:28PM -0800, mortonm@chromium.org wrote:
quoted
From: Micah Morton <mortonm@chromium.org>

The SafeSetID LSM already gates setuid transitions for UIDs on the
system whose use of CAP_SETUID has been 'restricted'. This patch
implements the analogous functionality for setgid transitions, in order
to restrict the use of CAP_SETGID for certain UIDs on the system. One
notable consequence of this addition is that a process running under a
restricted UID (i.e. one that is only allowed to setgid to certain
approved GIDs) will not be allowed to call the setgroups() syscall to
set its supplementary group IDs. For now, we leave such support for
restricted setgroups() to future work, as it would require hooking the
logic in setgroups() and verifying that the array of GIDs passed in from
userspace only consists of approved GIDs.

Signed-off-by: Micah Morton <mortonm@chromium.org>
---
Tested with slight mod to test in tools/testing/selftests/safesetid for
testing setgid as well as setuid.

 security/safesetid/lsm.c        | 263 +++++++++++++++++++++++++++-----
 security/safesetid/lsm.h        |  11 +-
 security/safesetid/securityfs.c | 105 +++++++++----
 3 files changed, 307 insertions(+), 72 deletions(-)
diff --git a/security/safesetid/lsm.c b/security/safesetid/lsm.c
index cecd38e2ac80..5d9710b7bb04 100644
--- a/security/safesetid/lsm.c
+++ b/security/safesetid/lsm.c
@@ -26,27 +26,30 @@ int safesetid_initialized;

 #define NUM_BITS 8 /* 128 buckets in hash table */
...
quoted
+int add_safesetid_whitelist_uid_entry(kuid_t parent, kuid_t child)
 {
-     struct entry *new;
+     struct id_entry *new;

      /* Return if entry already exists */
      if (check_setuid_policy_hashtable_key_value(parent, child))
              return 0;

-     new = kzalloc(sizeof(struct entry), GFP_KERNEL);
+     new = kzalloc(sizeof(struct id_entry), GFP_KERNEL);
+     if (!new)
+             return -ENOMEM;
+     new->parent_kuid = __kuid_val(parent);
+     new->child_kid = __kuid_val(child);
+     spin_lock(&safesetid_whitelist_uid_hashtable_spinlock);
+     hash_add_rcu(safesetid_whitelist_uid_hashtable,
+                  &new->next,
+                  __kuid_val(parent));
Do you care at all about the possibility of duplicate entries?
Duplicate entries shouldn't be possible due to the invocation of
check_setuid_policy_hashtable_key_value() above where it says "Return
if entry already exists". Does this make sense?
I don't believe it does, because you do the check before you lock.  So
two tasks can race.

Obviously you can't do the malloc under the spinlock, but I think you
will need to check for an existing entry once, do the malloc, lock,
then check again for an existing entry, then free the alloced
'new' if found.
quoted
quoted
+     spin_unlock(&safesetid_whitelist_uid_hashtable_spinlock);
+     return 0;
+}
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help