Revert "fs: remove ksys_dup()"
This reverts commit8243186f0c
("fs: remove ksys_dup()") and the subsequent fix for it in commit2d3145f8d2
("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>
This commit is contained in:
Родитель
738d290277
Коммит
74f1a29910
|
@ -960,7 +960,7 @@ SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd)
|
||||||
return ksys_dup3(oldfd, newfd, 0);
|
return ksys_dup3(oldfd, newfd, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE1(dup, unsigned int, fildes)
|
int ksys_dup(unsigned int fildes)
|
||||||
{
|
{
|
||||||
int ret = -EBADF;
|
int ret = -EBADF;
|
||||||
struct file *file = fget_raw(fildes);
|
struct file *file = fget_raw(fildes);
|
||||||
|
@ -975,6 +975,11 @@ SYSCALL_DEFINE1(dup, unsigned int, fildes)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SYSCALL_DEFINE1(dup, unsigned int, fildes)
|
||||||
|
{
|
||||||
|
return ksys_dup(fildes);
|
||||||
|
}
|
||||||
|
|
||||||
int f_dupfd(unsigned int from, struct file *file, unsigned flags)
|
int f_dupfd(unsigned int from, struct file *file, unsigned flags)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
|
@ -1232,6 +1232,7 @@ asmlinkage long sys_ni_syscall(void);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ksys_umount(char __user *name, int flags);
|
int ksys_umount(char __user *name, int flags);
|
||||||
|
int ksys_dup(unsigned int fildes);
|
||||||
int ksys_chroot(const char __user *filename);
|
int ksys_chroot(const char __user *filename);
|
||||||
ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count);
|
ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count);
|
||||||
int ksys_chdir(const char __user *filename);
|
int ksys_chdir(const char __user *filename);
|
||||||
|
|
26
init/main.c
26
init/main.c
|
@ -93,7 +93,6 @@
|
||||||
#include <linux/rodata_test.h>
|
#include <linux/rodata_test.h>
|
||||||
#include <linux/jump_label.h>
|
#include <linux/jump_label.h>
|
||||||
#include <linux/mem_encrypt.h>
|
#include <linux/mem_encrypt.h>
|
||||||
#include <linux/file.h>
|
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/bugs.h>
|
#include <asm/bugs.h>
|
||||||
|
@ -1158,26 +1157,13 @@ static int __ref kernel_init(void *unused)
|
||||||
|
|
||||||
void console_on_rootfs(void)
|
void console_on_rootfs(void)
|
||||||
{
|
{
|
||||||
struct file *file;
|
/* Open the /dev/console as stdin, this should never fail */
|
||||||
unsigned int i;
|
if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
|
||||||
|
pr_err("Warning: unable to open an initial console.\n");
|
||||||
|
|
||||||
/* Open /dev/console in kernelspace, this should never fail */
|
/* create stdout/stderr */
|
||||||
file = filp_open("/dev/console", O_RDWR, 0);
|
(void) ksys_dup(0);
|
||||||
if (IS_ERR(file))
|
(void) ksys_dup(0);
|
||||||
goto err_out;
|
|
||||||
|
|
||||||
/* create stdin/stdout/stderr, this should never fail */
|
|
||||||
for (i = 0; i < 3; i++) {
|
|
||||||
if (f_dupfd(i, file, 0) != i)
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
err_out:
|
|
||||||
/* no panic -- this might not be fatal */
|
|
||||||
pr_err("Warning: unable to open an initial console.\n");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static noinline void __init kernel_init_freeable(void)
|
static noinline void __init kernel_init_freeable(void)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче