[CHECKER] 2.4.5-ac4 security holes

Dawson Engler (engler@csl.Stanford.EDU)
Thu, 31 May 2001 21:49:14 -0700 (PDT)


Hi All,

Here's a few apparent security holes in 2.4.5-ac4. The biggest is in
fs/ioctl.c where it looks like a new option was added that seems to
write directly to the user pointer, essentially giving anyone complete
control over the machine.

4 | drivers/net/wan/cosa.c
2 | drivers/usb/bluetooth.c
1 | drivers/isdn/eicon/linchr.c
1 | drivers/sound/wavfront.c
1 | fs/ioctl.c

---------------------------------------------------------
[BUG] looks really broken.
/u2/engler/mc/oses/linux/2.4.5-ac4/fs/ioctl.c:108:sys_ioctl: ERROR:PARAM:70:108: Deref tainted var 'arg' (tainted from line 70)
case FIONCLEX:
set_close_on_exec(fd, 0);
break;

case FIONBIO:
Start --->
if ((error = get_user(on, (int *)arg)) != 0)

... DELETED 32 lines ...

case FIOQSIZE:
if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
S_ISREG(filp->f_dentry->d_inode->i_mode) ||
S_ISLNK(filp->f_dentry->d_inode->i_mode))
Error --->
*(loff_t *)arg = inode_get_bytes(filp->f_dentry->d_inode);
else
error = -ENOTTY;
break;

---------------------------------------------------------
[BUG] sure seems like it. In general, all 4 dereferences seem pretty bad.
/u2/engler/mc/oses/linux/2.4.5-ac4/drivers/net/wan/cosa.c:1049:cosa_download: ERROR:PARAM:1046:1049: Deref tainted var 'd' (tainted from line 1046)
return -EPERM;
}

if (get_user(addr, &(d->addr)) ||
__get_user(len, &(d->len)) ||
Start --->
__get_user(code, &(d->code)))
return -EFAULT;

Error --->
if (d->addr < 0 || d->addr > COSA_MAX_FIRMWARE_SIZE)
return -EINVAL;
if (d->len < 0 || d->len > COSA_MAX_FIRMWARE_SIZE)
return -EINVAL;
---------------------------------------------------------
[BUG] why copy it in then use the inital thing?
/u2/engler/mc/oses/linux/2.4.5-ac4/drivers/net/wan/cosa.c:1057:cosa_download: ERROR:PARAM:1046:1057: Deref tainted var 'd' (tainted from line 1046)
return -EPERM;
}

if (get_user(addr, &(d->addr)) ||
__get_user(len, &(d->len)) ||
Start --->
__get_user(code, &(d->code)))
return -EFAULT;

if (d->addr < 0 || d->addr > COSA_MAX_FIRMWARE_SIZE)
return -EINVAL;
if (d->len < 0 || d->len > COSA_MAX_FIRMWARE_SIZE)
return -EINVAL;

/* If something fails, force the user to reset the card */
cosa->firmware_status &= ~(COSA_FW_RESET|COSA_FW_DOWNLOAD);

Error --->
if ((i=download(cosa, d->code, len, addr)) < 0) {
printk(KERN_NOTICE "cosa%d: microcode download failed: %d\n",
cosa->num, i);
return -EIO;
---------------------------------------------------------
[BUG] seems retty clear
/u2/engler/mc/oses/linux/2.4.5-ac4/drivers/sound/wavfront.c:2049:wavefront_oss_ioctl: ERROR:PARAM:2072:2049: tainted var 'arg' (from line 2072) used as arg 0 to 'memcpy'
int err;

switch (cmd) {
case SNDCTL_SYNTH_INFO:
memcpy (&((char *) arg)[0], &wavefront_info,
Error --->
sizeof (wavefront_info));

... DELETED 17 lines ...

return dev.freemem;
}
break;

case SNDCTL_SYNTH_CONTROL:
Start --->
copy_from_user (&wc, arg, sizeof (wc));

if ((err = wavefront_synth_control (cmd, &wc)) == 0) {
copy_to_user (arg, &wc, sizeof (wc));
---------------------------------------------------------
[BUG] fixed in ac5, I believe.
/u2/engler/mc/oses/linux/2.4.5-ac4/drivers/usb/bluetooth.c:438:bluetooth_write: ERROR:PARAM:461:438: Deref tainted var 'buf' (tainted from line 461)
}

#ifdef DEBUG
printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", count);
for (i = 0; i < count; ++i) {
Error --->
printk ("%.2x ", buf[i]);

... DELETED 17 lines ...

err (__FUNCTION__ "- out of memory.");
return -ENOMEM;
}

if (from_user)
Start --->
copy_from_user (new_buffer, buf+1, count-1);
else
memcpy (new_buffer, buf+1, count-1);

---------------------------------------------------------
[BUG]
/u2/engler/mc/oses/linux/2.4.5-ac4/drivers/usb/bluetooth.c:431:bluetooth_write: ERROR:PARAM:461:431: Deref tainted var 'buf' (tainted from line 461)
if (count == 0) {
dbg(__FUNCTION__ " - write request of 0 bytes");
return 0;
}
if (count == 1) {
Error --->
dbg(__FUNCTION__ " - write request only included type %d", buf[0]);

... DELETED 24 lines ...

err (__FUNCTION__ "- out of memory.");
return -ENOMEM;
}

if (from_user)
Start --->
copy_from_user (new_buffer, buf+1, count-1);
else
memcpy (new_buffer, buf+1, count-1);

---------------------------------------------------------
[BUG] [RESURRECTED] Should be fixed in ac5, though.
/u2/engler/mc/oses/linux/2.4.5-ac4/drivers/isdn/eicon/linchr.c:128:do_ioctl: ERROR:PARAM:60:128: tainted var 'arg' (from line 60) used as arg 0 to 'DivasGetList'
mem_block_t mem_block;

switch (command)
{
case DIA_IOCTL_CONFIG:
Start --->
if (copy_from_user(&DivaConfig, (void *)arg, sizeof(dia_config_t)))

... DELETED 62 lines ...

case DIA_IOCTL_GET_LIST:
DPRINTF(("divas: DIA_IOCTL_GET_LIST"));

if (!verify_area(VERIFY_WRITE, (void *)arg, sizeof(dia_card_list_t)))
{
Error --->
DivasGetList((dia_card_list_t *)arg);
}
else
{

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/