execve fixes for v6.11-rc4

- binfmt_flat: Fix corruption when not offsetting data start
 
 - exec: Fix ToCToU between perm check and set-uid/gid usage
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRSPkdeREjth1dHnSE2KwveOeQkuwUCZrvBmwAKCRA2KwveOeQk
 u9Z2AQDgtypF4Kficiwn9BwZL5OxCxr9XnFuCYUue8Ufzm2WdQEAwhl1tcbs+Auf
 VAqpr6gZTRlpBjbl55LHeyMdxIbwhg4=
 =L28M
 -----END PGP SIGNATURE-----

Merge tag 'execve-v6.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull execve fixes from Kees Cook:

 - binfmt_flat: Fix corruption when not offsetting data start

 - exec: Fix ToCToU between perm check and set-uid/gid usage

* tag 'execve-v6.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  exec: Fix ToCToU between perm check and set-uid/gid usage
  binfmt_flat: Fix corruption when not offsetting data start
This commit is contained in:
Linus Torvalds 2024-08-13 16:10:32 -07:00
commit 6b0f8db921
2 changed files with 10 additions and 2 deletions

View File

@ -72,8 +72,10 @@
#ifdef CONFIG_BINFMT_FLAT_NO_DATA_START_OFFSET #ifdef CONFIG_BINFMT_FLAT_NO_DATA_START_OFFSET
#define DATA_START_OFFSET_WORDS (0) #define DATA_START_OFFSET_WORDS (0)
#define MAX_SHARED_LIBS_UPDATE (0)
#else #else
#define DATA_START_OFFSET_WORDS (MAX_SHARED_LIBS) #define DATA_START_OFFSET_WORDS (MAX_SHARED_LIBS)
#define MAX_SHARED_LIBS_UPDATE (MAX_SHARED_LIBS)
#endif #endif
struct lib_info { struct lib_info {
@ -880,7 +882,7 @@ static int load_flat_binary(struct linux_binprm *bprm)
return res; return res;
/* Update data segment pointers for all libraries */ /* Update data segment pointers for all libraries */
for (i = 0; i < MAX_SHARED_LIBS; i++) { for (i = 0; i < MAX_SHARED_LIBS_UPDATE; i++) {
if (!libinfo.lib_list[i].loaded) if (!libinfo.lib_list[i].loaded)
continue; continue;
for (j = 0; j < MAX_SHARED_LIBS; j++) { for (j = 0; j < MAX_SHARED_LIBS; j++) {

View File

@ -1692,6 +1692,7 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)
unsigned int mode; unsigned int mode;
vfsuid_t vfsuid; vfsuid_t vfsuid;
vfsgid_t vfsgid; vfsgid_t vfsgid;
int err;
if (!mnt_may_suid(file->f_path.mnt)) if (!mnt_may_suid(file->f_path.mnt))
return; return;
@ -1708,12 +1709,17 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)
/* Be careful if suid/sgid is set */ /* Be careful if suid/sgid is set */
inode_lock(inode); 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; mode = inode->i_mode;
vfsuid = i_uid_into_vfsuid(idmap, inode); vfsuid = i_uid_into_vfsuid(idmap, inode);
vfsgid = i_gid_into_vfsgid(idmap, inode); vfsgid = i_gid_into_vfsgid(idmap, inode);
err = inode_permission(idmap, inode, MAY_EXEC);
inode_unlock(inode); 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 */ /* We ignore suid/sgid if there are no mappings for them in the ns */
if (!vfsuid_has_mapping(bprm->cred->user_ns, vfsuid) || if (!vfsuid_has_mapping(bprm->cred->user_ns, vfsuid) ||
!vfsgid_has_mapping(bprm->cred->user_ns, vfsgid)) !vfsgid_has_mapping(bprm->cred->user_ns, vfsgid))