]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 14 Aug 2024 17:45:18 +0000 (19:45 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 14 Aug 2024 17:45:18 +0000 (19:45 +0200)
added patches:
exec-fix-toctou-between-perm-check-and-set-uid-gid-usage.patch
series

queue-6.10/exec-fix-toctou-between-perm-check-and-set-uid-gid-usage.patch [new file with mode: 0644]
queue-6.10/series [new file with mode: 0644]

diff --git a/queue-6.10/exec-fix-toctou-between-perm-check-and-set-uid-gid-usage.patch b/queue-6.10/exec-fix-toctou-between-perm-check-and-set-uid-gid-usage.patch
new file mode 100644 (file)
index 0000000..d651e69
--- /dev/null
@@ -0,0 +1,95 @@
+From f50733b45d865f91db90919f8311e2127ce5a0cb Mon Sep 17 00:00:00 2001
+From: Kees Cook <kees@kernel.org>
+Date: Thu, 8 Aug 2024 11:39:08 -0700
+Subject: exec: Fix ToCToU between perm check and set-uid/gid usage
+
+From: Kees Cook <kees@kernel.org>
+
+commit f50733b45d865f91db90919f8311e2127ce5a0cb upstream.
+
+When opening a file for exec via do_filp_open(), permission checking is
+done against the file's metadata at that moment, and on success, a file
+pointer is passed back. Much later in the execve() code path, the file
+metadata (specifically mode, uid, and gid) is used to determine if/how
+to set the uid and gid. However, those values may have changed since the
+permissions check, meaning the execution may gain unintended privileges.
+
+For example, if a file could change permissions from executable and not
+set-id:
+
+---------x 1 root root 16048 Aug  7 13:16 target
+
+to set-id and non-executable:
+
+---S------ 1 root root 16048 Aug  7 13:16 target
+
+it is possible to gain root privileges when execution should have been
+disallowed.
+
+While this race condition is rare in real-world scenarios, it has been
+observed (and proven exploitable) when package managers are updating
+the setuid bits of installed programs. Such files start with being
+world-executable but then are adjusted to be group-exec with a set-uid
+bit. For example, "chmod o-x,u+s target" makes "target" executable only
+by uid "root" and gid "cdrom", while also becoming setuid-root:
+
+-rwxr-xr-x 1 root cdrom 16048 Aug  7 13:16 target
+
+becomes:
+
+-rwsr-xr-- 1 root cdrom 16048 Aug  7 13:16 target
+
+But racing the chmod means users without group "cdrom" membership can
+get the permission to execute "target" just before the chmod, and when
+the chmod finishes, the exec reaches brpm_fill_uid(), and performs the
+setuid to root, violating the expressed authorization of "only cdrom
+group members can setuid to root".
+
+Re-check that we still have execute permissions in case the metadata
+has changed. It would be better to keep a copy from the perm-check time,
+but until we can do that refactoring, the least-bad option is to do a
+full inode_permission() call (under inode lock). It is understood that
+this is safe against dead-locks, but hardly optimal.
+
+Reported-by: Marco Vanotti <mvanotti@google.com>
+Tested-by: Marco Vanotti <mvanotti@google.com>
+Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: stable@vger.kernel.org
+Cc: Eric Biederman <ebiederm@xmission.com>
+Cc: Alexander Viro <viro@zeniv.linux.org.uk>
+Cc: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Kees Cook <kees@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/exec.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -1668,6 +1668,7 @@ static void bprm_fill_uid(struct linux_b
+       unsigned int mode;
+       vfsuid_t vfsuid;
+       vfsgid_t vfsgid;
++      int err;
+       if (!mnt_may_suid(file->f_path.mnt))
+               return;
+@@ -1684,12 +1685,17 @@ static void bprm_fill_uid(struct linux_b
+       /* Be careful if suid/sgid is set */
+       inode_lock(inode);
+-      /* reload atomically mode/uid/gid now that lock held */
++      /* Atomically reload and check mode/uid/gid now that lock held. */
+       mode = inode->i_mode;
+       vfsuid = i_uid_into_vfsuid(idmap, inode);
+       vfsgid = i_gid_into_vfsgid(idmap, inode);
++      err = inode_permission(idmap, inode, MAY_EXEC);
+       inode_unlock(inode);
++      /* Did the exec bit vanish out from under us? Give up. */
++      if (err)
++              return;
++
+       /* We ignore suid/sgid if there are no mappings for them in the ns */
+       if (!vfsuid_has_mapping(bprm->cred->user_ns, vfsuid) ||
+           !vfsgid_has_mapping(bprm->cred->user_ns, vfsgid))
diff --git a/queue-6.10/series b/queue-6.10/series
new file mode 100644 (file)
index 0000000..01bd355
--- /dev/null
@@ -0,0 +1 @@
+exec-fix-toctou-between-perm-check-and-set-uid-gid-usage.patch