summaryrefslogtreecommitdiff
path: root/drivers/tty/tty_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r--drivers/tty/tty_io.c133
1 files changed, 59 insertions, 74 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 407b0d87b7c1..e2d92cf70eb7 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -276,11 +276,10 @@ static void check_tty_count(struct tty_struct *tty, const char *routine)
struct list_head *p;
int count = 0, kopen_count = 0;
- spin_lock(&tty->files_lock);
- list_for_each(p, &tty->tty_files) {
- count++;
- }
- spin_unlock(&tty->files_lock);
+ scoped_guard(spinlock, &tty->files_lock)
+ list_for_each(p, &tty->tty_files)
+ count++;
+
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_SLAVE &&
tty->link && tty->link->count)
@@ -350,22 +349,19 @@ int tty_dev_name_to_number(const char *name, dev_t *number)
return ret;
prefix_length = str - name;
- mutex_lock(&tty_mutex);
+
+ guard(mutex)(&tty_mutex);
list_for_each_entry(p, &tty_drivers, tty_drivers)
if (prefix_length == strlen(p->name) && strncmp(name,
p->name, prefix_length) == 0) {
if (index < p->num) {
*number = MKDEV(p->major, p->minor_start + index);
- goto out;
+ return 0;
}
}
- /* if here then driver wasn't found */
- ret = -ENODEV;
-out:
- mutex_unlock(&tty_mutex);
- return ret;
+ return -ENODEV;
}
EXPORT_SYMBOL_GPL(tty_dev_name_to_number);
@@ -381,7 +377,7 @@ EXPORT_SYMBOL_GPL(tty_dev_name_to_number);
*/
struct tty_driver *tty_find_polling_driver(char *name, int *line)
{
- struct tty_driver *p, *res = NULL;
+ struct tty_driver *p;
int tty_line = 0;
int len;
char *str, *stp;
@@ -395,7 +391,8 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
len = str - name;
tty_line = simple_strtoul(str, &str, 10);
- mutex_lock(&tty_mutex);
+ guard(mutex)(&tty_mutex);
+
/* Search through the tty devices to look for a match */
list_for_each_entry(p, &tty_drivers, tty_drivers) {
if (!len || strncmp(name, p->name, len) != 0)
@@ -408,14 +405,12 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
if (tty_line >= 0 && tty_line < p->num && p->ops &&
p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) {
- res = tty_driver_kref_get(p);
*line = tty_line;
- break;
+ return tty_driver_kref_get(p);
}
}
- mutex_unlock(&tty_mutex);
- return res;
+ return NULL;
}
EXPORT_SYMBOL_GPL(tty_find_polling_driver);
#endif
@@ -462,7 +457,6 @@ static void tty_show_fdinfo(struct seq_file *m, struct file *file)
}
static const struct file_operations tty_fops = {
- .llseek = no_llseek,
.read_iter = tty_read,
.write_iter = tty_write,
.splice_read = copy_splice_read,
@@ -477,7 +471,6 @@ static const struct file_operations tty_fops = {
};
static const struct file_operations console_fops = {
- .llseek = no_llseek,
.read_iter = tty_read,
.write_iter = redirected_tty_write,
.splice_read = copy_splice_read,
@@ -491,7 +484,6 @@ static const struct file_operations console_fops = {
};
static const struct file_operations hung_up_tty_fops = {
- .llseek = no_llseek,
.read_iter = hung_up_tty_read,
.write_iter = hung_up_tty_write,
.poll = hung_up_tty_poll,
@@ -537,16 +529,15 @@ EXPORT_SYMBOL_GPL(tty_wakeup);
*/
static struct file *tty_release_redirect(struct tty_struct *tty)
{
- struct file *f = NULL;
+ guard(spinlock)(&redirect_lock);
- spin_lock(&redirect_lock);
if (redirect && file_tty(redirect) == tty) {
- f = redirect;
+ struct file *f = redirect;
redirect = NULL;
+ return f;
}
- spin_unlock(&redirect_lock);
- return f;
+ return NULL;
}
/**
@@ -771,11 +762,8 @@ void __stop_tty(struct tty_struct *tty)
*/
void stop_tty(struct tty_struct *tty)
{
- unsigned long flags;
-
- spin_lock_irqsave(&tty->flow.lock, flags);
+ guard(spinlock_irqsave)(&tty->flow.lock);
__stop_tty(tty);
- spin_unlock_irqrestore(&tty->flow.lock, flags);
}
EXPORT_SYMBOL(stop_tty);
@@ -802,11 +790,8 @@ void __start_tty(struct tty_struct *tty)
*/
void start_tty(struct tty_struct *tty)
{
- unsigned long flags;
-
- spin_lock_irqsave(&tty->flow.lock, flags);
+ guard(spinlock_irqsave)(&tty->flow.lock);
__start_tty(tty);
- spin_unlock_irqrestore(&tty->flow.lock, flags);
}
EXPORT_SYMBOL(start_tty);
@@ -815,7 +800,8 @@ static void tty_update_time(struct tty_struct *tty, bool mtime)
time64_t sec = ktime_get_real_seconds();
struct tty_file_private *priv;
- spin_lock(&tty->files_lock);
+ guard(spinlock)(&tty->files_lock);
+
list_for_each_entry(priv, &tty->tty_files, list) {
struct inode *inode = file_inode(priv->file);
struct timespec64 time = mtime ? inode_get_mtime(inode) : inode_get_atime(inode);
@@ -833,7 +819,6 @@ static void tty_update_time(struct tty_struct *tty, bool mtime)
inode_set_atime(inode, sec, 0);
}
}
- spin_unlock(&tty->files_lock);
}
/*
@@ -2225,6 +2210,12 @@ static int __tty_fasync(int fd, struct file *filp, int on)
if (tty_paranoia_check(tty, file_inode(filp), "tty_fasync"))
goto out;
+ if (on) {
+ retval = file_f_owner_allocate(filp);
+ if (retval)
+ goto out;
+ }
+
retval = fasync_helper(fd, filp, on, &tty->fasync);
if (retval <= 0)
goto out;
@@ -2314,13 +2305,12 @@ static int tiocsti(struct tty_struct *tty, u8 __user *p)
*/
static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
{
- int err;
+ guard(mutex)(&tty->winsize_mutex);
- mutex_lock(&tty->winsize_mutex);
- err = copy_to_user(arg, &tty->winsize, sizeof(*arg));
- mutex_unlock(&tty->winsize_mutex);
+ if (copy_to_user(arg, &tty->winsize, sizeof(*arg)))
+ return -EFAULT;
- return err ? -EFAULT : 0;
+ return 0;
}
/**
@@ -2335,10 +2325,10 @@ int tty_do_resize(struct tty_struct *tty, struct winsize *ws)
{
struct pid *pgrp;
- /* Lock the tty */
- mutex_lock(&tty->winsize_mutex);
+ guard(mutex)(&tty->winsize_mutex);
+
if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
- goto done;
+ return 0;
/* Signal the foreground process group */
pgrp = tty_get_pgrp(tty);
@@ -2347,8 +2337,7 @@ int tty_do_resize(struct tty_struct *tty, struct winsize *ws)
put_pid(pgrp);
tty->winsize = *ws;
-done:
- mutex_unlock(&tty->winsize_mutex);
+
return 0;
}
EXPORT_SYMBOL(tty_do_resize);
@@ -2409,13 +2398,14 @@ static int tioccons(struct file *file)
return -EBADF;
if (!(file->f_mode & FMODE_CAN_WRITE))
return -EINVAL;
- spin_lock(&redirect_lock);
- if (redirect) {
- spin_unlock(&redirect_lock);
+
+ guard(spinlock)(&redirect_lock);
+
+ if (redirect)
return -EBUSY;
- }
+
redirect = get_file(file);
- spin_unlock(&redirect_lock);
+
return 0;
}
@@ -2622,14 +2612,13 @@ static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
static int tty_set_serial(struct tty_struct *tty, struct serial_struct *ss)
{
- char comm[TASK_COMM_LEN];
int flags;
flags = ss->flags & ASYNC_DEPRECATED;
if (flags)
pr_warn_ratelimited("%s: '%s' is using deprecated serial flags (with no effect): %.8x\n",
- __func__, get_task_comm(comm, current), flags);
+ __func__, current->comm, flags);
if (!tty->ops->set_serial)
return -ENOTTY;
@@ -3029,11 +3018,9 @@ void __do_SAK(struct tty_struct *tty)
struct task_struct *g, *p;
struct pid *session;
int i;
- unsigned long flags;
- spin_lock_irqsave(&tty->ctrl.lock, flags);
- session = get_pid(tty->ctrl.session);
- spin_unlock_irqrestore(&tty->ctrl.lock, flags);
+ scoped_guard(spinlock_irqsave, &tty->ctrl.lock)
+ session = get_pid(tty->ctrl.session);
tty_ldisc_flush(tty);
@@ -3056,7 +3043,7 @@ void __do_SAK(struct tty_struct *tty)
PIDTYPE_SID);
continue;
}
- task_lock(p);
+ guard(task_lock)(p);
i = iterate_fd(p->files, 0, this_tty, tty);
if (i != 0) {
tty_notice(tty, "SAK: killed process %d (%s): by fd#%d\n",
@@ -3064,7 +3051,6 @@ void __do_SAK(struct tty_struct *tty)
group_send_sig_info(SIGKILL, SEND_SIG_PRIV, p,
PIDTYPE_SID);
}
- task_unlock(p);
}
read_unlock(&tasklist_lock);
put_pid(session);
@@ -3330,10 +3316,12 @@ EXPORT_SYMBOL(tty_unregister_device);
* __tty_alloc_driver - allocate tty driver
* @lines: count of lines this driver can handle at most
* @owner: module which is responsible for this driver
- * @flags: some of %TTY_DRIVER_ flags, will be set in driver->flags
+ * @flags: some of enum tty_driver_flag, will be set in driver->flags
+ *
+ * This should not be called directly, tty_alloc_driver() should be used
+ * instead.
*
- * This should not be called directly, some of the provided macros should be
- * used instead. Use IS_ERR() and friends on @retval.
+ * Returns: struct tty_driver or a PTR-encoded error (use IS_ERR() and friends).
*/
struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,
unsigned long flags)
@@ -3464,9 +3452,8 @@ int tty_register_driver(struct tty_driver *driver)
goto err_unreg_char;
}
- mutex_lock(&tty_mutex);
- list_add(&driver->tty_drivers, &tty_drivers);
- mutex_unlock(&tty_mutex);
+ scoped_guard(mutex, &tty_mutex)
+ list_add(&driver->tty_drivers, &tty_drivers);
if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
for (i = 0; i < driver->num; i++) {
@@ -3485,9 +3472,8 @@ err_unreg_devs:
for (i--; i >= 0; i--)
tty_unregister_device(driver, i);
- mutex_lock(&tty_mutex);
- list_del(&driver->tty_drivers);
- mutex_unlock(&tty_mutex);
+ scoped_guard(mutex, &tty_mutex)
+ list_del(&driver->tty_drivers);
err_unreg_char:
unregister_chrdev_region(dev, driver->num);
@@ -3506,9 +3492,8 @@ void tty_unregister_driver(struct tty_driver *driver)
{
unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
driver->num);
- mutex_lock(&tty_mutex);
- list_del(&driver->tty_drivers);
- mutex_unlock(&tty_mutex);
+ scoped_guard(mutex, &tty_mutex)
+ list_del(&driver->tty_drivers);
}
EXPORT_SYMBOL(tty_unregister_driver);
@@ -3567,7 +3552,7 @@ static ssize_t show_cons_active(struct device *dev,
for_each_console(c) {
if (!c->device)
continue;
- if (!c->write)
+ if (!(c->flags & CON_NBCON) && !c->write)
continue;
if ((c->flags & CON_ENABLED) == 0)
continue;
@@ -3618,7 +3603,7 @@ void console_sysfs_notify(void)
sysfs_notify(&consdev->kobj, NULL, "active");
}
-static struct ctl_table tty_table[] = {
+static const struct ctl_table tty_table[] = {
{
.procname = "legacy_tiocsti",
.data = &tty_legacy_tiocsti,
@@ -3631,7 +3616,7 @@ static struct ctl_table tty_table[] = {
.data = &tty_ldisc_autoload,
.maxlen = sizeof(tty_ldisc_autoload),
.mode = 0644,
- .proc_handler = proc_dointvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},