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.

Revert "fs: remove ksys_dup()"

This reverts commit 8243186f0cc7 ("fs: remove ksys_dup()") and the
subsequent fix for it in commit 2d3145f8d280 ("early init: fix error
handling when opening /dev/console").

Trying to use filp_open() and f_dupfd() instead of pseudo-syscalls
caused more trouble than what is worth it: it requires accessing vfs
internals and it turns out there were other bugs in it too.

In particular, the file reference counting was wrong - because unlike
the original "open+2*dup" sequence it used "filp_open+3*f_dupfd" and
thus had an extra leaked file reference.

That in turn then caused odd problems with Androidx86 long after boot
becaue of how the extra reference to the console kept the session active
even after all file descriptors had been closed.

Reported-by: youling 257 <youling257@gmail.com>
Cc: Arvind Sankar <nivedita@alum.mit.edu>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Dominik Brodowski and committed by
Linus Torvalds
74f1a299 738d2902

+13 -21
+6 -1
fs/file.c
··· 960 960 return ksys_dup3(oldfd, newfd, 0); 961 961 } 962 962 963 - SYSCALL_DEFINE1(dup, unsigned int, fildes) 963 + int ksys_dup(unsigned int fildes) 964 964 { 965 965 int ret = -EBADF; 966 966 struct file *file = fget_raw(fildes); ··· 973 973 fput(file); 974 974 } 975 975 return ret; 976 + } 977 + 978 + SYSCALL_DEFINE1(dup, unsigned int, fildes) 979 + { 980 + return ksys_dup(fildes); 976 981 } 977 982 978 983 int f_dupfd(unsigned int from, struct file *file, unsigned flags)
+1
include/linux/syscalls.h
··· 1232 1232 */ 1233 1233 1234 1234 int ksys_umount(char __user *name, int flags); 1235 + int ksys_dup(unsigned int fildes); 1235 1236 int ksys_chroot(const char __user *filename); 1236 1237 ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count); 1237 1238 int ksys_chdir(const char __user *filename);
+6 -20
init/main.c
··· 93 93 #include <linux/rodata_test.h> 94 94 #include <linux/jump_label.h> 95 95 #include <linux/mem_encrypt.h> 96 - #include <linux/file.h> 97 96 98 97 #include <asm/io.h> 99 98 #include <asm/bugs.h> ··· 1157 1158 1158 1159 void console_on_rootfs(void) 1159 1160 { 1160 - struct file *file; 1161 - unsigned int i; 1161 + /* Open the /dev/console as stdin, this should never fail */ 1162 + if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) 1163 + pr_err("Warning: unable to open an initial console.\n"); 1162 1164 1163 - /* Open /dev/console in kernelspace, this should never fail */ 1164 - file = filp_open("/dev/console", O_RDWR, 0); 1165 - if (IS_ERR(file)) 1166 - goto err_out; 1167 - 1168 - /* create stdin/stdout/stderr, this should never fail */ 1169 - for (i = 0; i < 3; i++) { 1170 - if (f_dupfd(i, file, 0) != i) 1171 - goto err_out; 1172 - } 1173 - 1174 - return; 1175 - 1176 - err_out: 1177 - /* no panic -- this might not be fatal */ 1178 - pr_err("Warning: unable to open an initial console.\n"); 1179 - return; 1165 + /* create stdout/stderr */ 1166 + (void) ksys_dup(0); 1167 + (void) ksys_dup(0); 1180 1168 } 1181 1169 1182 1170 static noinline void __init kernel_init_freeable(void)