From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756832AbcAJFfl (ORCPT ); Sun, 10 Jan 2016 00:35:41 -0500 Received: from mail-pf0-f181.google.com ([209.85.192.181]:36500 "EHLO mail-pf0-f181.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755188AbcAJFfd (ORCPT ); Sun, 10 Jan 2016 00:35:33 -0500 From: Peter Hurley To: Greg Kroah-Hartman Cc: Jiri Slaby , linux-kernel@vger.kernel.org, Peter Hurley Subject: [PATCH v2 6/6] tty: Make tty_files_lock per-tty Date: Sat, 9 Jan 2016 21:35:23 -0800 Message-Id: <1452404123-9024-7-git-send-email-peter@hurleysoftware.com> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1452404123-9024-1-git-send-email-peter@hurleysoftware.com> References: <1448678317-9093-1-git-send-email-peter@hurleysoftware.com> <1452404123-9024-1-git-send-email-peter@hurleysoftware.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Access to tty->tty_files list is always per-tty, never for all ttys simultaneously. Replace global tty_files_lock spinlock with per-tty ->files_lock. Initialize when the ->tty_files list is inited, in alloc_tty_struct(). Signed-off-by: Peter Hurley --- drivers/tty/tty_io.c | 25 ++++++++++++------------- include/linux/tty.h | 2 +- security/selinux/hooks.c | 4 ++-- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index b89c0a5..48281a5 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -138,9 +138,6 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ /* Mutex to protect creating and releasing a tty */ DEFINE_MUTEX(tty_mutex); -/* Spinlock to protect the tty->tty_files list */ -DEFINE_SPINLOCK(tty_files_lock); - static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); ssize_t redirected_tty_write(struct file *, const char __user *, @@ -202,9 +199,9 @@ void tty_add_file(struct tty_struct *tty, struct file *file) priv->tty = tty; priv->file = file; - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_add(&priv->list, &tty->tty_files); - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); } /** @@ -225,10 +222,11 @@ void tty_free_file(struct file *file) static void tty_del_file(struct file *file) { struct tty_file_private *priv = file->private_data; + struct tty_struct *tty = priv->tty; - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_del(&priv->list); - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); tty_free_file(file); } @@ -286,11 +284,11 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) struct list_head *p; int count = 0; - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_for_each(p, &tty->tty_files) { count++; } - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); if (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_SLAVE && tty->link && tty->link->count) @@ -713,7 +711,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) workqueue with the lock held */ check_tty_count(tty, "tty_hangup"); - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); /* This breaks for file handles being sent over AF_UNIX sockets ? */ list_for_each_entry(priv, &tty->tty_files, list) { filp = priv->file; @@ -725,7 +723,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) __tty_fasync(-1, filp, 0); /* can't block */ filp->f_op = &hung_up_tty_fops; } - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); refs = tty_signal_session_leader(tty, exit_session); /* Account for the p->signal references we killed */ @@ -1637,9 +1635,9 @@ static void release_one_tty(struct work_struct *work) tty_driver_kref_put(driver); module_put(owner); - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_del_init(&tty->tty_files); - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); put_pid(tty->pgrp); put_pid(tty->session); @@ -3176,6 +3174,7 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) mutex_init(&tty->atomic_write_lock); spin_lock_init(&tty->ctrl_lock); spin_lock_init(&tty->flow_lock); + spin_lock_init(&tty->files_lock); INIT_LIST_HEAD(&tty->tty_files); INIT_WORK(&tty->SAK_work, do_SAK_work); diff --git a/include/linux/tty.h b/include/linux/tty.h index 8ed795d..dea7d54 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -302,6 +302,7 @@ struct tty_struct { struct work_struct hangup_work; void *disc_data; void *driver_data; + spinlock_t files_lock; /* protects tty_files list */ struct list_head tty_files; #define N_TTY_BUF_SIZE 4096 @@ -508,7 +509,6 @@ extern int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty); extern struct mutex tty_mutex; -extern spinlock_t tty_files_lock; #define tty_is_writelocked(tty) (mutex_is_locked(&tty->atomic_write_lock)) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d0cfaa9..ae6dbc75 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2352,7 +2352,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, tty = get_current_tty(); if (tty) { - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); if (!list_empty(&tty->tty_files)) { struct tty_file_private *file_priv; @@ -2367,7 +2367,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE)) drop_tty = 1; } - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); tty_kref_put(tty); } /* Reset controlling tty. */ -- 2.7.0