Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

execve: open the executable file before doing anything else

No point in allocating a new mm, counting arguments and environment
variables etc if we're just going to return ENOENT.

This patch does expose the fact that 'do_filp_open()' that execve() uses
is still unnecessarily expensive in the failure case, because it
allocates the 'struct file *' early, even if the path lookup (which is
heavily optimized) fails.

So that remains an unnecessary cost in the "no such executable" case,
but it's a separate issue. Regardless, I do not want to do _both_ a
filename_lookup() and a later do_filp_open() like the origin patch by
Josh Triplett did in [1].

Reported-by: Josh Triplett <josh@joshtriplett.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Mateusz Guzik <mjguzik@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Link: https://lore.kernel.org/lkml/5c7333ea4bec2fad1b47a8fa2db7c31e4ffc4f14.1663334978.git.josh@joshtriplett.org/ [1]
Link: https://lore.kernel.org/lkml/202209161637.9EDAF6B18@keescook/
Link: https://lore.kernel.org/lkml/CAHk-=wgznerM-xs+x+krDfE7eVBiy_HOam35rbsFMMOwvYuEKQ@mail.gmail.com/
Link: https://lore.kernel.org/lkml/CAHk-=whf9qLO8ipps4QhmS0BkM8mtWJhvnuDSdtw5gFjhzvKNA@mail.gmail.com/
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+35 -34
+35 -34
fs/exec.c
··· 1508 1508 kfree(bprm); 1509 1509 } 1510 1510 1511 - static struct linux_binprm *alloc_bprm(int fd, struct filename *filename) 1511 + static struct linux_binprm *alloc_bprm(int fd, struct filename *filename, int flags) 1512 1512 { 1513 - struct linux_binprm *bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); 1513 + struct linux_binprm *bprm; 1514 + struct file *file; 1514 1515 int retval = -ENOMEM; 1515 - if (!bprm) 1516 - goto out; 1516 + 1517 + file = do_open_execat(fd, filename, flags); 1518 + if (IS_ERR(file)) 1519 + return ERR_CAST(file); 1520 + 1521 + bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); 1522 + if (!bprm) { 1523 + allow_write_access(file); 1524 + fput(file); 1525 + return ERR_PTR(-ENOMEM); 1526 + } 1527 + 1528 + bprm->file = file; 1517 1529 1518 1530 if (fd == AT_FDCWD || filename->name[0] == '/') { 1519 1531 bprm->filename = filename->name; ··· 1538 1526 if (!bprm->fdpath) 1539 1527 goto out_free; 1540 1528 1529 + /* 1530 + * Record that a name derived from an O_CLOEXEC fd will be 1531 + * inaccessible after exec. This allows the code in exec to 1532 + * choose to fail when the executable is not mmaped into the 1533 + * interpreter and an open file descriptor is not passed to 1534 + * the interpreter. This makes for a better user experience 1535 + * than having the interpreter start and then immediately fail 1536 + * when it finds the executable is inaccessible. 1537 + */ 1538 + if (get_close_on_exec(fd)) 1539 + bprm->interp_flags |= BINPRM_FLAGS_PATH_INACCESSIBLE; 1540 + 1541 1541 bprm->filename = bprm->fdpath; 1542 1542 } 1543 1543 bprm->interp = bprm->filename; 1544 1544 1545 1545 retval = bprm_mm_init(bprm); 1546 - if (retval) 1547 - goto out_free; 1548 - return bprm; 1546 + if (!retval) 1547 + return bprm; 1549 1548 1550 1549 out_free: 1551 1550 free_bprm(bprm); 1552 - out: 1553 1551 return ERR_PTR(retval); 1554 1552 } 1555 1553 ··· 1829 1807 /* 1830 1808 * sys_execve() executes a new program. 1831 1809 */ 1832 - static int bprm_execve(struct linux_binprm *bprm, 1833 - int fd, struct filename *filename, int flags) 1810 + static int bprm_execve(struct linux_binprm *bprm) 1834 1811 { 1835 - struct file *file; 1836 1812 int retval; 1837 1813 1838 1814 retval = prepare_bprm_creds(bprm); ··· 1846 1826 current->in_execve = 1; 1847 1827 sched_mm_cid_before_execve(current); 1848 1828 1849 - file = do_open_execat(fd, filename, flags); 1850 - retval = PTR_ERR(file); 1851 - if (IS_ERR(file)) 1852 - goto out_unmark; 1853 - 1854 1829 sched_exec(); 1855 - 1856 - bprm->file = file; 1857 - /* 1858 - * Record that a name derived from an O_CLOEXEC fd will be 1859 - * inaccessible after exec. This allows the code in exec to 1860 - * choose to fail when the executable is not mmaped into the 1861 - * interpreter and an open file descriptor is not passed to 1862 - * the interpreter. This makes for a better user experience 1863 - * than having the interpreter start and then immediately fail 1864 - * when it finds the executable is inaccessible. 1865 - */ 1866 - if (bprm->fdpath && get_close_on_exec(fd)) 1867 - bprm->interp_flags |= BINPRM_FLAGS_PATH_INACCESSIBLE; 1868 1830 1869 1831 /* Set the unchanging part of bprm->cred */ 1870 1832 retval = security_bprm_creds_for_exec(bprm); ··· 1877 1875 if (bprm->point_of_no_return && !fatal_signal_pending(current)) 1878 1876 force_fatal_sig(SIGSEGV); 1879 1877 1880 - out_unmark: 1881 1878 sched_mm_cid_after_execve(current); 1882 1879 current->fs->in_exec = 0; 1883 1880 current->in_execve = 0; ··· 1911 1910 * further execve() calls fail. */ 1912 1911 current->flags &= ~PF_NPROC_EXCEEDED; 1913 1912 1914 - bprm = alloc_bprm(fd, filename); 1913 + bprm = alloc_bprm(fd, filename, flags); 1915 1914 if (IS_ERR(bprm)) { 1916 1915 retval = PTR_ERR(bprm); 1917 1916 goto out_ret; ··· 1960 1959 bprm->argc = 1; 1961 1960 } 1962 1961 1963 - retval = bprm_execve(bprm, fd, filename, flags); 1962 + retval = bprm_execve(bprm); 1964 1963 out_free: 1965 1964 free_bprm(bprm); 1966 1965 ··· 1985 1984 if (IS_ERR(filename)) 1986 1985 return PTR_ERR(filename); 1987 1986 1988 - bprm = alloc_bprm(fd, filename); 1987 + bprm = alloc_bprm(fd, filename, 0); 1989 1988 if (IS_ERR(bprm)) { 1990 1989 retval = PTR_ERR(bprm); 1991 1990 goto out_ret; ··· 2020 2019 if (retval < 0) 2021 2020 goto out_free; 2022 2021 2023 - retval = bprm_execve(bprm, fd, filename, 0); 2022 + retval = bprm_execve(bprm); 2024 2023 out_free: 2025 2024 free_bprm(bprm); 2026 2025 out_ret: