Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scsi: core: Fix legacy /proc parsing buffer overflow

(lightly modified commit message mostly by Linus Torvalds)

The parsing code for /proc/scsi/scsi is disgusting and broken. We should
have just used 'sscanf()' or something simple like that, but the logic may
actually predate our kernel sscanf library routine for all I know. It
certainly predates both git and BK histories.

And we can't change it to be something sane like that now, because the
string matching at the start is done case-insensitively, and the separator
parsing between numbers isn't done at all, so *any* separator will work,
including a possible terminating NUL character.

This interface is root-only, and entirely for legacy use, so there is
absolutely no point in trying to tighten up the parsing. Because any
separator has traditionally worked, it's entirely possible that people have
used random characters rather than the suggested space.

So don't bother to try to pretty it up, and let's just make a minimal patch
that can be back-ported and we can forget about this whole sorry thing for
another two decades.

Just make it at least not read past the end of the supplied data.

Link: https://lore.kernel.org/linux-scsi/b570f5fe-cb7c-863a-6ed9-f6774c219b88@cybernetics.com/
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Martin K Petersen <martin.petersen@oracle.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: stable@kernel.org
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Signed-off-by: Martin K Petersen <martin.petersen@oracle.com>

authored by

Tony Battersby and committed by
Martin K. Petersen
9426d3ce 8366d1f1

+17 -13
+17 -13
drivers/scsi/scsi_proc.c
··· 406 406 size_t length, loff_t *ppos) 407 407 { 408 408 int host, channel, id, lun; 409 - char *buffer, *p; 409 + char *buffer, *end, *p; 410 410 int err; 411 411 412 412 if (!buf || length > PAGE_SIZE) ··· 421 421 goto out; 422 422 423 423 err = -EINVAL; 424 - if (length < PAGE_SIZE) 425 - buffer[length] = '\0'; 426 - else if (buffer[PAGE_SIZE-1]) 427 - goto out; 424 + if (length < PAGE_SIZE) { 425 + end = buffer + length; 426 + *end = '\0'; 427 + } else { 428 + end = buffer + PAGE_SIZE - 1; 429 + if (*end) 430 + goto out; 431 + } 428 432 429 433 /* 430 434 * Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi ··· 437 433 if (!strncmp("scsi add-single-device", buffer, 22)) { 438 434 p = buffer + 23; 439 435 440 - host = simple_strtoul(p, &p, 0); 441 - channel = simple_strtoul(p + 1, &p, 0); 442 - id = simple_strtoul(p + 1, &p, 0); 443 - lun = simple_strtoul(p + 1, &p, 0); 436 + host = (p < end) ? simple_strtoul(p, &p, 0) : 0; 437 + channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; 438 + id = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; 439 + lun = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; 444 440 445 441 err = scsi_add_single_device(host, channel, id, lun); 446 442 ··· 451 447 } else if (!strncmp("scsi remove-single-device", buffer, 25)) { 452 448 p = buffer + 26; 453 449 454 - host = simple_strtoul(p, &p, 0); 455 - channel = simple_strtoul(p + 1, &p, 0); 456 - id = simple_strtoul(p + 1, &p, 0); 457 - lun = simple_strtoul(p + 1, &p, 0); 450 + host = (p < end) ? simple_strtoul(p, &p, 0) : 0; 451 + channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; 452 + id = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; 453 + lun = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; 458 454 459 455 err = scsi_remove_single_device(host, channel, id, lun); 460 456 }