diff options
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/n_tty.c | 7 | ||||
-rw-r--r-- | drivers/tty/tty_io.c | 27 |
2 files changed, 23 insertions, 11 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index e508c4672bcf..87ec15dbe10d 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2079,9 +2079,6 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty, return ldata->read_tail != canon_head; } -extern ssize_t redirected_tty_write(struct file *, const char __user *, - size_t, loff_t *); - /** * job_control - check job control * @tty: tty @@ -2103,7 +2100,7 @@ static int job_control(struct tty_struct *tty, struct file *file) /* NOTE: not yet done after every sleep pending a thorough check of the logic of this change. -- jlc */ /* don't stop on /dev/console */ - if (file->f_op->write == redirected_tty_write) + if (file->f_op->write_iter == redirected_tty_write) return 0; return __tty_check_change(tty, SIGTTIN); @@ -2330,7 +2327,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, ssize_t retval = 0; /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ - if (L_TOSTOP(tty) && file->f_op->write != redirected_tty_write) { + if (L_TOSTOP(tty) && file->f_op->write_iter != redirected_tty_write) { retval = tty_check_change(tty); if (retval) return retval; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index eb7bd80cd155..74733ec8f565 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -144,10 +144,8 @@ DEFINE_MUTEX(tty_mutex); static ssize_t tty_read(struct kiocb *, struct iov_iter *); static ssize_t tty_write(struct kiocb *, struct iov_iter *); -ssize_t redirected_tty_write(struct kiocb *, struct iov_iter *); static __poll_t tty_poll(struct file *, poll_table *); static int tty_open(struct inode *, struct file *); -long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg); #ifdef CONFIG_COMPAT static long tty_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); @@ -1047,11 +1045,14 @@ static inline ssize_t do_tty_write( if (ret <= 0) break; + written += ret; + if (ret > size) + break; + /* FIXME! Have Al check this! */ if (ret != size) iov_iter_revert(from, size-ret); - written += ret; count -= ret; if (!count) break; @@ -1111,9 +1112,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; @@ -1136,6 +1136,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; @@ -1145,9 +1150,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; } @@ -2413,6 +2422,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); |