summaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorsalina@us.ibm.com <salina@us.ibm.com>2013-05-07 16:18:09 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-05-16 18:08:58 -0700
commit221ba151731133c8b0e1cdb9bfd2a45b3ba8764b (patch)
treeba6f1ff35fdc25a3e3a27ba8dc8aceabc8b7e11d /drivers/char
parenta7b594b4905828b3bfc36be39d48b5e07a23c8e1 (diff)
downloadlinux-221ba151731133c8b0e1cdb9bfd2a45b3ba8764b.tar.bz2
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>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/lp.c3
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,
return -EFAULT;
break;
case LPGETSTATUS:
+ if (mutex_lock_interruptible(&lp_table[minor].port_mutex))
+ return -EINTR;
lp_claim_parport_or_block (&lp_table[minor]);
status = r_str(minor);
lp_release_parport (&lp_table[minor]);
+ mutex_unlock(&lp_table[minor].port_mutex);
if (copy_to_user(argp, &status, sizeof(int)))
return -EFAULT;