diff options
author | salina@us.ibm.com <salina@us.ibm.com> | 2013-05-07 10:18:09 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-05-16 21:08:58 -0400 |
commit | 221ba151731133c8b0e1cdb9bfd2a45b3ba8764b (patch) | |
tree | ba6f1ff35fdc25a3e3a27ba8dc8aceabc8b7e11d | |
parent | a7b594b4905828b3bfc36be39d48b5e07a23c8e1 (diff) |
Char: lp, protect LPGETSTATUS with port_mutex
The patch fixes a problem in the lp driver that can cause oopses as
follows:
process A: calls lp_write, which in turn calls
parport_ieee1284_write_compat, and that invokes
parport_wait_peripheral
process B: meanwhile does an ioctl(LPGETSTATUS), which call
lp_release_parport when done. This function will set
physport->cad = NULL.
process A: parport_wait_peripheral tries to dereference
physport->cad and dies
So, protect that code with the port_mutex in order to protect against
simultaneous calls to lp_read/lp_write.
Similar protection is probably required for ioctl(LPRESET)...
This patch was done by IBM a while back and we (at suse) have that
since at least 2004 in our repos. Let's make it upstream.
Signed-off-by: okir@suse.de
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/char/lp.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/char/lp.c b/drivers/char/lp.c index dafd9ac6428f..0913d79424d3 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c | |||
@@ -622,9 +622,12 @@ static int lp_do_ioctl(unsigned int minor, unsigned int cmd, | |||
622 | return -EFAULT; | 622 | return -EFAULT; |
623 | break; | 623 | break; |
624 | case LPGETSTATUS: | 624 | case LPGETSTATUS: |
625 | if (mutex_lock_interruptible(&lp_table[minor].port_mutex)) | ||
626 | return -EINTR; | ||
625 | lp_claim_parport_or_block (&lp_table[minor]); | 627 | lp_claim_parport_or_block (&lp_table[minor]); |
626 | status = r_str(minor); | 628 | status = r_str(minor); |
627 | lp_release_parport (&lp_table[minor]); | 629 | lp_release_parport (&lp_table[minor]); |
630 | mutex_unlock(&lp_table[minor].port_mutex); | ||
628 | 631 | ||
629 | if (copy_to_user(argp, &status, sizeof(int))) | 632 | if (copy_to_user(argp, &status, sizeof(int))) |
630 | return -EFAULT; | 633 | return -EFAULT; |