]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
LSM: Signal to SafeSetID when setting group IDs
authorThomas Cedeno <thomascedeno@google.com>
Thu, 16 Jul 2020 19:13:57 +0000 (19:13 +0000)
committerMicah Morton <mortonm@chromium.org>
Tue, 13 Oct 2020 16:17:34 +0000 (09:17 -0700)
For SafeSetID to properly gate set*gid() calls, it needs to know whether
ns_capable() is being called from within a sys_set*gid() function or is
being called from elsewhere in the kernel. This allows SafeSetID to deny
CAP_SETGID to restricted groups when they are attempting to use the
capability for code paths other than updating GIDs (e.g. setting up
userns GID mappings). This is the identical approach to what is
currently done for CAP_SETUID.

NOTE: We also add signaling to SafeSetID from the setgroups() syscall,
as we have future plans to restrict a process' ability to set
supplementary groups in addition to what is added in this series for
restricting setting of the primary group.

Signed-off-by: Thomas Cedeno <thomascedeno@google.com>
Signed-off-by: Micah Morton <mortonm@chromium.org>
kernel/capability.c
kernel/groups.c
kernel/sys.c

index 7c59b096c98aee0a1867ee7c450c9efc99d4e345..de7eac903a2a5f6e6af42158b753f711dff9093c 100644 (file)
@@ -418,7 +418,7 @@ EXPORT_SYMBOL(ns_capable_noaudit);
 /**
  * ns_capable_setid - Determine if the current task has a superior capability
  * in effect, while signalling that this check is being done from within a
- * setid syscall.
+ * setid or setgroups syscall.
  * @ns:  The usernamespace we want the capability in
  * @cap: The capability to be tested for
  *
index 6ee6691f6839f64554aceeb1bbeca0785feda08d..fe7e6385530e679596009b2e125cb808397d870f 100644 (file)
@@ -178,7 +178,7 @@ bool may_setgroups(void)
 {
        struct user_namespace *user_ns = current_user_ns();
 
-       return ns_capable(user_ns, CAP_SETGID) &&
+       return ns_capable_setid(user_ns, CAP_SETGID) &&
                userns_may_setgroups(user_ns);
 }
 
index ab6c409b1159b1538437198d5a7745766f45e906..ad80f9767f27a66611a1363b027d93e13841729b 100644 (file)
@@ -373,7 +373,7 @@ long __sys_setregid(gid_t rgid, gid_t egid)
        if (rgid != (gid_t) -1) {
                if (gid_eq(old->gid, krgid) ||
                    gid_eq(old->egid, krgid) ||
-                   ns_capable(old->user_ns, CAP_SETGID))
+                   ns_capable_setid(old->user_ns, CAP_SETGID))
                        new->gid = krgid;
                else
                        goto error;
@@ -382,7 +382,7 @@ long __sys_setregid(gid_t rgid, gid_t egid)
                if (gid_eq(old->gid, kegid) ||
                    gid_eq(old->egid, kegid) ||
                    gid_eq(old->sgid, kegid) ||
-                   ns_capable(old->user_ns, CAP_SETGID))
+                   ns_capable_setid(old->user_ns, CAP_SETGID))
                        new->egid = kegid;
                else
                        goto error;
@@ -432,7 +432,7 @@ long __sys_setgid(gid_t gid)
        old = current_cred();
 
        retval = -EPERM;
-       if (ns_capable(old->user_ns, CAP_SETGID))
+       if (ns_capable_setid(old->user_ns, CAP_SETGID))
                new->gid = new->egid = new->sgid = new->fsgid = kgid;
        else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid))
                new->egid = new->fsgid = kgid;
@@ -744,7 +744,7 @@ long __sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
        old = current_cred();
 
        retval = -EPERM;
-       if (!ns_capable(old->user_ns, CAP_SETGID)) {
+       if (!ns_capable_setid(old->user_ns, CAP_SETGID)) {
                if (rgid != (gid_t) -1        && !gid_eq(krgid, old->gid) &&
                    !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid))
                        goto error;
@@ -871,7 +871,7 @@ long __sys_setfsgid(gid_t gid)
 
        if (gid_eq(kgid, old->gid)  || gid_eq(kgid, old->egid)  ||
            gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) ||
-           ns_capable(old->user_ns, CAP_SETGID)) {
+           ns_capable_setid(old->user_ns, CAP_SETGID)) {
                if (!gid_eq(kgid, old->fsgid)) {
                        new->fsgid = kgid;
                        if (security_task_fix_setgid(new,old,LSM_SETID_FS) == 0)