diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 2f8223b2ffa454f5b5d5720e89799cc9687f75aa..ff87cb51747d811125d156d44d28a33156c268e3 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1027,9 +1027,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; @@ -1052,6 +1051,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; @@ -1061,9 +1065,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; } @@ -2306,6 +2314,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);