]> git.itanic.dy.fi Git - linux-stable/commitdiff
usb: misc: uss720: Fix two sleep-in-atomic-context bugs
authorJia-Ju Bai <baijiaju1990@gmail.com>
Sat, 1 Sep 2018 08:25:08 +0000 (16:25 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Sep 2018 06:35:08 +0000 (08:35 +0200)
commit bc8acc214d3f1cafebcbcd101a695bbac716595d upstream.

async_complete() in uss720.c is a completion handler function for the
USB driver. So it should not sleep, but it is can sleep according to the
function call paths (from bottom to top) in Linux-4.16.

[FUNC] set_1284_register(GFP_KERNEL)
drivers/usb/misc/uss720.c, 372:
  set_1284_register in parport_uss720_frob_control
drivers/parport/ieee1284.c, 560:
  [FUNC_PTR]parport_uss720_frob_control in parport_ieee1284_ack_data_avail
drivers/parport/ieee1284.c, 577:
  parport_ieee1284_ack_data_avail in parport_ieee1284_interrupt
./include/linux/parport.h, 474:
  parport_ieee1284_interrupt in parport_generic_irq
drivers/usb/misc/uss720.c, 116:
  parport_generic_irq in async_complete

[FUNC] get_1284_register(GFP_KERNEL)
drivers/usb/misc/uss720.c, 382:
  get_1284_register in parport_uss720_read_status
drivers/parport/ieee1284.c, 555:
  [FUNC_PTR]parport_uss720_read_status in parport_ieee1284_ack_data_avail
drivers/parport/ieee1284.c, 577:
  parport_ieee1284_ack_data_avail in parport_ieee1284_interrupt
./include/linux/parport.h, 474:
  parport_ieee1284_interrupt in parport_generic_irq
drivers/usb/misc/uss720.c, 116:
  parport_generic_irq in async_complete

Note that [FUNC_PTR] means a function pointer call is used.

To fix these bugs, GFP_KERNEL is replaced with GFP_ATOMIC.

These bugs are found by my static analysis tool DSAC.

Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/misc/uss720.c

index 442b6631162eb63b7f3adcac74da2924c0d0a207..3d750671b85a6b74300dfe3b8abaa9b18d8e63ac 100644 (file)
@@ -388,7 +388,7 @@ static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned ch
        mask &= 0x0f;
        val &= 0x0f;
        d = (priv->reg[1] & (~mask)) ^ val;
-       if (set_1284_register(pp, 2, d, GFP_KERNEL))
+       if (set_1284_register(pp, 2, d, GFP_ATOMIC))
                return 0;
        priv->reg[1] = d;
        return d & 0xf;
@@ -398,7 +398,7 @@ static unsigned char parport_uss720_read_status(struct parport *pp)
 {
        unsigned char ret;
 
-       if (get_1284_register(pp, 1, &ret, GFP_KERNEL))
+       if (get_1284_register(pp, 1, &ret, GFP_ATOMIC))
                return 0;
        return ret & 0xf8;
 }