返回列表 发帖

[转帖]Linux Kernel IOCTL处理器多个本地内存破坏漏洞

BUGTRAQ ID: 13651
CVE(CAN) ID: CAN-2005-1589
Linux Kernel是开放源码操作系统Linux所使用的内核。
Linux kernel的pktcdvd和rawdevice块设备组件中存在漏洞,本地攻击者可能利用此漏洞提升自己的权限。
起因是对Pktcdvd和rawdevice ioctl处理程序参数缺少检查,这样进程就可能摆脱对用户空间的限制,以Kernel权限级别执行任意代码。
有漏洞的代码位于Linux kernel源码树的drivers/block/pktcdvd.c中:
static int pkt_ioctl(struct inode *inode, struct file *file, unsigned
int cmd, unsigned long arg)
{
struct pktcdvd_device *pd = inode-??i_bdev-??bd_disk-??private_data;
VPRINTK(`pkt_ioctl: cmd %x, dev %d:%d `, cmd, imajor(inode),
iminor(inode));
BUG_ON(!pd);
switch (cmd) {
/*
* forward selected CDROM ioctls to CD-ROM, for UDF
*/
case CDROMMULTISESSION:
case CDROMREADTOCENTRY:
case CDROM_LAST_WRITTEN:
case CDROM_SEND_PACKET:
case SCSI_IOCTL_SEND_COMMAND:
  • return ioctl_by_bdev(pd-??bdev, cmd, arg);
    case CDROMEJECT:
    /*
    * The door gets locked when the device is opened, so we
    * have to unlock it or else the eject command fails.
    */
    pkt_lock_door(pd, 0);
  • return ioctl_by_bdev(pd-??bdev, cmd, arg);
    default:
  • 中可见没有检查提供给ioctl_by_bdev()函数的arg变量,这样用户就可以输入arg ?? TASK_SIZE值。
    fs/block_dev.c
    int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
    {
    int res;
    mm_segment_t old_fs = get_fs();
    [**] set_fs(KERNEL_DS);
    res = blkdev_ioctl(bdev-??bd_inode, NULL, cmd, arg);
    set_fs(old_fs);
    return res;
    }
    但是,为了支持kernel空间参数,ioctl_by_bdev()调用[**] set_fs(KERNEL_DS)访问kernel空间中的参数,因此如果ioctl_by_bdev()参数arg ?? TASK_SIZE,进程就可以摆脱用户空间的限制,覆盖kernel空间数据。
    Rawdevice漏洞与以上类似。
    drivers/char/raw.c
    static int
    raw_ioctl(struct inode *inode, struct file *filp,
    unsigned int command, unsigned long arg)
    {
    struct block_device *bdev = filp-??private_data;
  • return ioctl_by_bdev(bdev, command, arg);
    }
    *??
  • 返回列表 回复 发帖