From: Greg Kroah-Hartman Date: Wed, 14 Aug 2024 17:45:02 +0000 (+0200) Subject: 6.6-stable patches X-Git-Tag: v4.19.320~51 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=09df179e94a08148f692c87bb5b597690edece10;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: exec-fix-toctou-between-perm-check-and-set-uid-gid-usage.patch series --- diff --git a/queue-6.6/exec-fix-toctou-between-perm-check-and-set-uid-gid-usage.patch b/queue-6.6/exec-fix-toctou-between-perm-check-and-set-uid-gid-usage.patch new file mode 100644 index 00000000000..b1c6c0c7c16 --- /dev/null +++ b/queue-6.6/exec-fix-toctou-between-perm-check-and-set-uid-gid-usage.patch @@ -0,0 +1,95 @@ +From f50733b45d865f91db90919f8311e2127ce5a0cb Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Thu, 8 Aug 2024 11:39:08 -0700 +Subject: exec: Fix ToCToU between perm check and set-uid/gid usage + +From: Kees Cook + +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 +Tested-by: Marco Vanotti +Suggested-by: Linus Torvalds +Cc: stable@vger.kernel.org +Cc: Eric Biederman +Cc: Alexander Viro +Cc: Christian Brauner +Signed-off-by: Kees Cook +Signed-off-by: Greg Kroah-Hartman +--- + fs/exec.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1609,6 +1609,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; +@@ -1625,12 +1626,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.6/series b/queue-6.6/series new file mode 100644 index 00000000000..01bd35578b3 --- /dev/null +++ b/queue-6.6/series @@ -0,0 +1 @@ +exec-fix-toctou-between-perm-check-and-set-uid-gid-usage.patch