mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
tty: avoid using vfs_iocb_iter_write() for redirected console writes
It turns out that the vfs_iocb_iter_{read,write}() functions are entirely broken, and don't actually use the passed-in file pointer for IO - only for the preparatory work (permission checking and for the write_iter function lookup). That worked fine for overlayfs, which always builds the new iocb with the same file pointer that it passes in, but in the general case it ends up doing nonsensical things (and could cause an iterator call that doesn't even match the passed-in file pointer). This subtly broke the tty conversion to write_iter in commit9bb48c82ac
("tty: implement write_iter"), because the console redirection didn't actually end up redirecting anything, since the passed-in file pointer was basically ignored, and the actual write was done with the original non-redirected console tty after all. The main visible effect of this is that the console messages were no longer logged to /var/log/boot.log during graphical boot. Fix the issue by simply not using the vfs write "helper" function at all, and just redirecting the write entirely internally to the tty layer. Do the target writability permission checks when actually registering the target tty with TIOCCONS instead of at write time. Fixes:9bb48c82ac
("tty: implement write_iter") Reported-and-tested-by: Hans de Goede <hdegoede@redhat.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: stable@kernel.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
bec4c2968f
commit
a9cbbb80e3
@ -1026,9 +1026,8 @@ void tty_write_message(struct tty_struct *tty, char *msg)
|
||||
* write method will not be invoked in parallel for each device.
|
||||
*/
|
||||
|
||||
static ssize_t tty_write(struct kiocb *iocb, struct iov_iter *from)
|
||||
static ssize_t file_tty_write(struct file *file, struct kiocb *iocb, struct iov_iter *from)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct tty_struct *tty = file_tty(file);
|
||||
struct tty_ldisc *ld;
|
||||
ssize_t ret;
|
||||
@ -1051,6 +1050,11 @@ static ssize_t tty_write(struct kiocb *iocb, struct iov_iter *from)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t tty_write(struct kiocb *iocb, struct iov_iter *from)
|
||||
{
|
||||
return file_tty_write(iocb->ki_filp, iocb, from);
|
||||
}
|
||||
|
||||
ssize_t redirected_tty_write(struct kiocb *iocb, struct iov_iter *iter)
|
||||
{
|
||||
struct file *p = NULL;
|
||||
@ -1060,9 +1064,13 @@ ssize_t redirected_tty_write(struct kiocb *iocb, struct iov_iter *iter)
|
||||
p = get_file(redirect);
|
||||
spin_unlock(&redirect_lock);
|
||||
|
||||
/*
|
||||
* We know the redirected tty is just another tty, we can can
|
||||
* call file_tty_write() directly with that file pointer.
|
||||
*/
|
||||
if (p) {
|
||||
ssize_t res;
|
||||
res = vfs_iocb_iter_write(p, iocb, iter);
|
||||
res = file_tty_write(p, iocb, iter);
|
||||
fput(p);
|
||||
return res;
|
||||
}
|
||||
@ -2308,6 +2316,12 @@ static int tioccons(struct file *file)
|
||||
fput(f);
|
||||
return 0;
|
||||
}
|
||||
if (file->f_op->write_iter != tty_write)
|
||||
return -ENOTTY;
|
||||
if (!(file->f_mode & FMODE_WRITE))
|
||||
return -EBADF;
|
||||
if (!(file->f_mode & FMODE_CAN_WRITE))
|
||||
return -EINVAL;
|
||||
spin_lock(&redirect_lock);
|
||||
if (redirect) {
|
||||
spin_unlock(&redirect_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user