Bug 188691

Summary: Function sci_request_irq() returns an improper value when the call to kasprintf() fails
Product: Drivers Reporter: bianpan (bianpan2010)
Component: SerialAssignee: Russell King (rmk)
Status: RESOLVED CODE_FIX    
Severity: normal    
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: linux-4.9-rc6 Subsystem:
Regression: No Bisected commit-id:
Attachments: The patch fixes the bug

Description bianpan 2016-11-25 10:49:16 UTC
Function kasprintf() returns a NULL pointer if something goes wrong, e.g. no enough memory. In function sci_request_irq() defined in file drivers/tty/serial/sh-sci.c, variable ret takes the return value. Variable ret should takes a negative integer if error occurs. However, the value of ret is still 0 when the call to kasprintf() returns a NULL pointer. This will mislead its caller, and the freed memory (at line 1775) may be used/freed again. Maybe it is better to assign "-ENOMEM" to ret when the call to kasprintf() returns a NULL pointer. Codes related to this bug are summarised as follows.

sci_request_irq @@ drivers/tty/serial/sh-sci.c
1730 static int sci_request_irq(struct sci_port *port)
1731 {
1732     struct uart_port *up = &port->port;
1733     int i, j, ret = 0;
1734 
1735     for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) {
1736         const struct sci_irq_desc *desc;
1737         int irq;
             ...
1753         desc = sci_irq_desc + i;
1754         port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
1755                         dev_name(up->dev), desc->desc);
1756         if (!port->irqstr[j])
1757             goto out_nomem;   // insert "ret = -ENOMEM;" before this jump instruction?
1758 
1759         ret = request_irq(irq, desc->handler, up->irqflags,
1760                   port->irqstr[j], port);
1761         if (unlikely(ret)) {
1762             dev_err(up->dev, "Can't allocate %s IRQ\n", desc->desc);
1763             goto out_noirq;
1764         }
1765     }
1766
1767     return 0;
1768 
1769 out_noirq:
1770     while (--i >= 0)
1771         free_irq(port->irqs[i], port);
1772 
1773 out_nomem:
1774     while (--j >= 0)
1775         kfree(port->irqstr[j]);
1776 
1777     return ret;
1778 }

Thanks very much!
Comment 1 bianpan 2017-05-11 23:36:36 UTC
Created attachment 256405 [details]
The patch fixes the bug

The patch has been merged into the latest version of the Linux kernel. So I will close the bug.