mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-13 08:07:32 -04:00
tty: hvc: Fix data abort due to race in hvc_open
[ Upstream commit e2bd1dcbe1aa34ff5570b3427c530e4332ecf0fe ] Potentially, hvc_open() can be called in parallel when two tasks calls open() on /dev/hvcX. In such a scenario, if the hp->ops->notifier_add() callback in the function fails, where it sets the tty->driver_data to NULL, the parallel hvc_open() can see this NULL and cause a memory abort. Hence, serialize hvc_open and check if tty->private_data is NULL before proceeding ahead. The issue can be easily reproduced by launching two tasks simultaneously that does nothing but open() and close() on /dev/hvcX. For example: $ ./simple_open_close /dev/hvc0 & ./simple_open_close /dev/hvc0 & Signed-off-by: Raghavendra Rao Ananta <rananta@codeaurora.org> Link: https://lore.kernel.org/r/20200428032601.22127-1-rananta@codeaurora.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
eb3e85b337
commit
793e15fb66
1 changed files with 14 additions and 2 deletions
|
|
@ -75,6 +75,8 @@ static LIST_HEAD(hvc_structs);
|
|||
*/
|
||||
static DEFINE_MUTEX(hvc_structs_mutex);
|
||||
|
||||
/* Mutex to serialize hvc_open */
|
||||
static DEFINE_MUTEX(hvc_open_mutex);
|
||||
/*
|
||||
* This value is used to assign a tty->index value to a hvc_struct based
|
||||
* upon order of exposure via hvc_probe(), when we can not match it to
|
||||
|
|
@ -346,16 +348,24 @@ static int hvc_install(struct tty_driver *driver, struct tty_struct *tty)
|
|||
*/
|
||||
static int hvc_open(struct tty_struct *tty, struct file * filp)
|
||||
{
|
||||
struct hvc_struct *hp = tty->driver_data;
|
||||
struct hvc_struct *hp;
|
||||
unsigned long flags;
|
||||
int rc = 0;
|
||||
|
||||
mutex_lock(&hvc_open_mutex);
|
||||
|
||||
hp = tty->driver_data;
|
||||
if (!hp) {
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&hp->port.lock, flags);
|
||||
/* Check and then increment for fast path open. */
|
||||
if (hp->port.count++ > 0) {
|
||||
spin_unlock_irqrestore(&hp->port.lock, flags);
|
||||
hvc_kick();
|
||||
return 0;
|
||||
goto out;
|
||||
} /* else count == 0 */
|
||||
spin_unlock_irqrestore(&hp->port.lock, flags);
|
||||
|
||||
|
|
@ -383,6 +393,8 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
|
|||
/* Force wakeup of the polling thread */
|
||||
hvc_kick();
|
||||
|
||||
out:
|
||||
mutex_unlock(&hvc_open_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue