[CHECKER] 4 security holes in 2.4.4-ac8

From: Dawson Engler (engler@csl.Stanford.EDU)
Date: Tue May 29 2001 - 17:00:56 EST


Hi All,

Enclosed are four bugs where 2.4.4-ac8 kernel code appears to directly
read/write user space pointers. The latter three were found after
forming equivalence classes by:
        (1) recording all routines assigned to the same function pointer
            field in a structure
        (2) if any member of the equiv class treated a parameter as a
            user-space pointer, checking that they all do.

Let me know if any of these are wrong. The first one seems pretty bad.

Dawson
-------------------------------------------------------------------------------
[BUG] raddr seems to be a user pointer, but is written at the end of
      the system call.

ipc/shm.c: ERROR: system call 'sys_shmat' derefs non-tainted param= 3

asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
{
        struct shmid_kernel *shp;

        ...
        *raddr = (unsigned long) user_addr;
        err = 0;
        if (IS_ERR(user_addr))
                err = PTR_ERR(user_addr);
        return err;

-----------------------------------------------------------------------------
[BUG] ./drivers/usb/bluetooth.c: dereference of 'buf' at the beginning of
      the switch, and then does a copyin.

        ERROR: equivalence class <struct tty_driver:write> contains
        2 functions that taint parameter <2>, and 1
        functions that dereference it raw.

        Tainting functions
                [ acm_tty_write:acm.c ]
                [ serial_write:usbserial.c ]
        Dereferencing functions
                [ bluetooth_write:bluetooth.c ]

        switch (*buf) {
                /* First byte indicates the type of packet */
                case CMD_PKT:
                        /* dbg(__FUNCTION__ "- Send cmd_pkt len:%d", count);*/

                        if (in_interrupt()){
                                printk("cmd_pkt from interrupt!\n");
                                return count;
                        }

                        new_buffer = kmalloc (count-1, GFP_KERNEL);

                        if (!new_buffer) {
                                err (__FUNCTION__ "- out of memory.");
                                return -ENOMEM;
                        }

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

-------------------------------------------------------
In the equivalence class for file_operations:write: 55 functions treat
their second parameter as tainted, but two functions use it raw.

[BUG]
/* drivers/char/sbc60xxwdt.c: buf is tainted */
static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos)
{
        /* We can't seek */
        if(ppos != &file->f_pos)
                return -ESPIPE;
        
        /* See if we got the magic character */
        if(count)
        {
                size_t ofs;
                
                /* note: just in case someone wrote the magic character
                 * five months ago... */
                wdt_expect_close = 0;
                
                /* now scan */
                for(ofs = 0; ofs != count; ofs++)
                        if(buf[ofs] == 'V')
                                wdt_expect_close = 1;
 
                /* Well, anyhow someone wrote to us, we should return that favour */
                next_heartbeat = jiffies + WDT_HEARTBEAT;
        }
        return 0;
}

[BUG]
/* drivers/usb/mdc800.c: buf is tainted */
static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t len, loff_t *pos)
{
        int i=0;
 
        spin_lock (&mdc800->io_lock);
        if (mdc800->state != READY)
        {
                spin_unlock (&mdc800->io_lock);
                return -EBUSY;
        }
        if (!mdc800->open )
        {
                spin_unlock (&mdc800->io_lock);
                return -EBUSY;
        }
 
        while (i<len)
        {
                if (signal_pending (current))
                {
                        spin_unlock (&mdc800->io_lock);
                        return -EINTR;
                }
        
                /* check for command start */
                if (buf [i] == (char) 0x55)
                {
                        mdc800->in_count=0;

Here's the equiv classes:

        Tainting functions
                [ ac_write:applicom.c ]
                [ affs_file_write:file.c ]
                [ block_write:ksyms.c ]
                [ camera_write:dc2xx.c ]
                [ cap_info_write:file_cap.c ]
                [ capi_write:capi.c ]
                [ capinc_raw_write:capi.c ]
                [ coda_file_write:file.c ]
                [ coda_psdev_write:psdev.c ]
                [ cs4281_midi_write:cs4281m.c ]
                [ cs4281_write:cs4281m.c ]
                [ dev_irnet_write:irnet_ppp.h ]
                [ dev_write:raw1394.c ]
                [ ds_write:ds.c ]
                [ dtlk_write:dtlk.c ]
                [ emu10k1_audio_write:audio.c ]
                [ emu10k1_midi_write:midi.c ]
                [ generic_file_write:ksyms.c ]
                [ hdr_write:file_hdr.c ]
                [ hfs_file_write:file.c ]
                [ hpfs_file_write:inode.c ]
                [ i2cdev_write:i2c-dev.c ]
                [ idetape_chrdev_write:ide-tape.c ]
                [ isapnp_info_entry_write:isapnp_proc.c ]
                [ isdn_write:isdn_common.c ]
                [ ixj_enhanced_write:ixj.c ]
                [ lp_write:lp.c ]
                [ mem_write:pcilynx.c ]
                [ microcode_write:microcode.c ]
                [ mtd_write:mtdchar.c ]
                [ mtrr_write:mtrr.c ]
                [ ncp_file_write:file.c ]
                [ nfs_file_write:file.c ]
                [ nvram_write:nvram.c ]
                [ osst_write:osst.c ]
                [ pg_write:pg.c ]
                [ pipe_write:pipe.c ]
                [ ppp_write:ppp_generic.c ]
                [ proc_bus_pci_write:proc.c ]
                [ proc_mpc_write:mpoa_proc.c ]
                [ qic02_tape_write:tpqic02.c ]
                [ sg_write:sg.c ]
                [ shmem_file_write:shmem.c ]
                [ smb_file_write:file.c ]
                [ st_write:st.c ]
                [ tun_chr_write:tun.c ]
                [ usb_audio_write:audio.c ]
                [ vcs_write:vc_screen.c ]
                [ write_kmem:mem.c ]
                [ write_mem:mem.c ]
                [ write_port:mem.c ]
                [ write_profile:proc_misc.c ]
                [ write_rio:rio500.c ]
                [ write_scanner:scanner.c ]
                [ zft_write:zftape-init.c ]
        Dereferencing functions
                [ fop_write:sbc60xxwdt.c ]
                [ mdc800_device_write:mdc800.c ]
-
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/



This archive was generated by hypermail 2b29 : Thu May 31 2001 - 21:00:41 EST