Linux lp.c Out-of-Bounds Write via Kernel Command-line

2017-05-26T00:00:00
ID SSV:93143
Type seebug
Reporter Root
Modified 2017-05-26T00:00:00

Description

Vulnerable Versions

  • Linux 4.12-rc1 and below
  • Linux 3.x
  • Linux 2.6.x
  • Linux 2.4.x
  • Linux 2.2.x

Mitigation

Patch has been committed to the mainline tree, available in the 4.12-rc2 release. 3.18 / 4.4 stable releases with the patch are also avaialble (see timeline). Technical Details Due to a missing bounds check, and the fact that parport_ptr integer is static, a kernel command-line adversary (can happen due to bootloader vulnerabilities in Secure Boot environments, e.g. CVE-2016-10277) can overflow the parport_nr array in the following code, by appending many (>LP_NO) lp=none arguments to the command line. ``` static int parport_nr[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC }; static char *parport[LP_NO]; [...]

ifndef MODULE

static int __init lp_setup (char *str) { static int parport_ptr; [...] } else if (!strncmp(str, "parport", 7)) { int n = simple_strtoul(str+7, NULL, 10); if (parport_ptr < LP_NO) parport_nr[parport_ptr++] = n; else printk(KERN_INFO "lp: too many ports, %s ignored.\n", str); } else if (!strcmp(str, "auto")) { parport_nr[0] = LP_PARPORT_AUTO; } else if (!strcmp(str, "none")) { parport_nr[parport_ptr++] = LP_PARPORT_NONE; [...]

endif

[...] __setup("lp=", lp_setup); ```

Patch

As per our report, Willy Tarreau commited the following patch: diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 565e4cf..8249762 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -859,7 +859,11 @@ static int __init lp_setup (char *str) } else if (!strcmp(str, "auto")) { parport_nr[0] = LP_PARPORT_AUTO; } else if (!strcmp(str, "none")) { - parport_nr[parport_ptr++] = LP_PARPORT_NONE; + if (parport_ptr &lt; LP_NO) + parport_nr[parport_ptr++] = LP_PARPORT_NONE; + else + printk(KERN_INFO "lp: too many ports, %s ignored.\n", + str); } else if (!strcmp(str, "reset")) { reset = 1; }

Timeline