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

exec: Remove do_execve_file

Now that the last callser has been removed remove this code from exec.

For anyone thinking of resurrecing do_execve_file please note that
the code was buggy in several fundamental ways.

- It did not ensure the file it was passed was read-only and that
deny_write_access had been called on it. Which subtlely breaks
invaniants in exec.

- The caller of do_execve_file was expected to hold and put a
reference to the file, but an extra reference for use by exec was
not taken so that when exec put it's reference to the file an
underflow occured on the file reference count.

- The point of the interface was so that a pathname did not need to
exist. Which breaks pathname based LSMs.

Tetsuo Handa originally reported these issues[1]. While it was clear
that deny_write_access was missing the fundamental incompatibility
with the passed in O_RDWR filehandle was not immediately recognized.

All of these issues were fixed by modifying the usermode driver code
to have a path, so it did not need this hack.

Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
[1] https://lore.kernel.org/linux-fsdevel/2a8775b4-1dd5-9d5c-aa42-9872445e0942@i-love.sakura.ne.jp/
v1: https://lkml.kernel.org/r/871rm2f0hi.fsf_-_@x220.int.ebiederm.org
v2: https://lkml.kernel.org/r/87lfk54p0m.fsf_-_@x220.int.ebiederm.org
Link: https://lkml.kernel.org/r/20200702164140.4468-10-ebiederm@xmission.com
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

+9 -30
+9 -29
fs/exec.c
··· 1818 1818 /* 1819 1819 * sys_execve() executes a new program. 1820 1820 */ 1821 - static int __do_execve_file(int fd, struct filename *filename, 1822 - struct user_arg_ptr argv, 1823 - struct user_arg_ptr envp, 1824 - int flags, struct file *file) 1821 + static int do_execveat_common(int fd, struct filename *filename, 1822 + struct user_arg_ptr argv, 1823 + struct user_arg_ptr envp, 1824 + int flags) 1825 1825 { 1826 1826 char *pathbuf = NULL; 1827 1827 struct linux_binprm *bprm; 1828 + struct file *file; 1828 1829 struct files_struct *displaced; 1829 1830 int retval; 1830 1831 ··· 1864 1863 check_unsafe_exec(bprm); 1865 1864 current->in_execve = 1; 1866 1865 1867 - if (!file) 1868 - file = do_open_execat(fd, filename, flags); 1866 + file = do_open_execat(fd, filename, flags); 1869 1867 retval = PTR_ERR(file); 1870 1868 if (IS_ERR(file)) 1871 1869 goto out_unmark; ··· 1872 1872 sched_exec(); 1873 1873 1874 1874 bprm->file = file; 1875 - if (!filename) { 1876 - bprm->filename = "none"; 1877 - } else if (fd == AT_FDCWD || filename->name[0] == '/') { 1875 + if (fd == AT_FDCWD || filename->name[0] == '/') { 1878 1876 bprm->filename = filename->name; 1879 1877 } else { 1880 1878 if (filename->name[0] == '\0') ··· 1933 1935 task_numa_free(current, false); 1934 1936 free_bprm(bprm); 1935 1937 kfree(pathbuf); 1936 - if (filename) 1937 - putname(filename); 1938 + putname(filename); 1938 1939 if (displaced) 1939 1940 put_files_struct(displaced); 1940 1941 return retval; ··· 1964 1967 if (displaced) 1965 1968 reset_files_struct(displaced); 1966 1969 out_ret: 1967 - if (filename) 1968 - putname(filename); 1970 + putname(filename); 1969 1971 return retval; 1970 - } 1971 - 1972 - static int do_execveat_common(int fd, struct filename *filename, 1973 - struct user_arg_ptr argv, 1974 - struct user_arg_ptr envp, 1975 - int flags) 1976 - { 1977 - return __do_execve_file(fd, filename, argv, envp, flags, NULL); 1978 - } 1979 - 1980 - int do_execve_file(struct file *file, void *__argv, void *__envp) 1981 - { 1982 - struct user_arg_ptr argv = { .ptr.native = __argv }; 1983 - struct user_arg_ptr envp = { .ptr.native = __envp }; 1984 - 1985 - return __do_execve_file(AT_FDCWD, NULL, argv, envp, 0, file); 1986 1972 } 1987 1973 1988 1974 int do_execve(struct filename *filename,
-1
include/linux/binfmts.h
··· 141 141 const char __user * const __user *, 142 142 const char __user * const __user *, 143 143 int); 144 - int do_execve_file(struct file *file, void *__argv, void *__envp); 145 144 146 145 #endif /* _LINUX_BINFMTS_H */