security: Add LSM hook to setgroups() syscall
authorMicah Morton <mortonm@chromium.org>
Wed, 8 Jun 2022 20:57:11 +0000 (20:57 +0000)
committerMicah Morton <mortonm@chromium.org>
Fri, 15 Jul 2022 18:21:49 +0000 (18:21 +0000)
Give the LSM framework the ability to filter setgroups() syscalls. There
are already analagous hooks for the set*uid() and set*gid() syscalls.
The SafeSetID LSM will use this new hook to ensure setgroups() calls are
allowed by the installed security policy. Tested by putting print
statement in security_task_fix_setgroups() hook and confirming that it
gets hit when userspace does a setgroups() syscall.

Acked-by: Casey Schaufler <casey@schaufler-ca.com>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Micah Morton <mortonm@chromium.org>
include/linux/lsm_hook_defs.h
include/linux/lsm_hooks.h
include/linux/security.h
kernel/groups.c
security/security.c

index eafa1d2..8064481 100644 (file)
@@ -201,6 +201,7 @@ LSM_HOOK(int, 0, task_fix_setuid, struct cred *new, const struct cred *old,
         int flags)
 LSM_HOOK(int, 0, task_fix_setgid, struct cred *new, const struct cred * old,
         int flags)
+LSM_HOOK(int, 0, task_fix_setgroups, struct cred *new, const struct cred * old)
 LSM_HOOK(int, 0, task_setpgid, struct task_struct *p, pid_t pgid)
 LSM_HOOK(int, 0, task_getpgid, struct task_struct *p)
 LSM_HOOK(int, 0, task_getsid, struct task_struct *p)
index 91c8146..84a0d7e 100644 (file)
  *     @old is the set of credentials that are being replaced.
  *     @flags contains one of the LSM_SETID_* values.
  *     Return 0 on success.
+ * @task_fix_setgroups:
+ *     Update the module's state after setting the supplementary group
+ *     identity attributes of the current process.
+ *     @new is the set of credentials that will be installed.  Modifications
+ *     should be made to this rather than to @current->cred.
+ *     @old is the set of credentials that are being replaced.
+ *     Return 0 on success.
  * @task_setpgid:
  *     Check permission before setting the process group identifier of the
  *     process @p to @pgid.
index 7fc4e9f..1dfd32c 100644 (file)
@@ -415,6 +415,7 @@ int security_task_fix_setuid(struct cred *new, const struct cred *old,
                             int flags);
 int security_task_fix_setgid(struct cred *new, const struct cred *old,
                             int flags);
+int security_task_fix_setgroups(struct cred *new, const struct cred *old);
 int security_task_setpgid(struct task_struct *p, pid_t pgid);
 int security_task_getpgid(struct task_struct *p);
 int security_task_getsid(struct task_struct *p);
@@ -1098,6 +1099,12 @@ static inline int security_task_fix_setgid(struct cred *new,
        return 0;
 }
 
+static inline int security_task_fix_setgroups(struct cred *new,
+                                          const struct cred *old)
+{
+       return 0;
+}
+
 static inline int security_task_setpgid(struct task_struct *p, pid_t pgid)
 {
        return 0;
index 787b381..9aaed2a 100644 (file)
@@ -134,13 +134,26 @@ EXPORT_SYMBOL(set_groups);
 int set_current_groups(struct group_info *group_info)
 {
        struct cred *new;
+       const struct cred *old;
+       int retval;
 
        new = prepare_creds();
        if (!new)
                return -ENOMEM;
 
+       old = current_cred();
+
        set_groups(new, group_info);
+
+       retval = security_task_fix_setgroups(new, old);
+       if (retval < 0)
+               goto error;
+
        return commit_creds(new);
+
+error:
+       abort_creds(new);
+       return retval;
 }
 
 EXPORT_SYMBOL(set_current_groups);
index 188b8f7..15c6861 100644 (file)
@@ -1803,6 +1803,11 @@ int security_task_fix_setgid(struct cred *new, const struct cred *old,
        return call_int_hook(task_fix_setgid, 0, new, old, flags);
 }
 
+int security_task_fix_setgroups(struct cred *new, const struct cred *old)
+{
+       return call_int_hook(task_fix_setgroups, 0, new, old);
+}
+
 int security_task_setpgid(struct task_struct *p, pid_t pgid)
 {
        return call_int_hook(task_setpgid, 0, p, pgid);