From: Dawson Engler <engler@csl.Stanford.EDU> To: linux-kernel@vger.kernel.org Subject: [CHECKER] 4 security holes in 2.4.4-ac8 Date: Tue, 29 May 2001 15:00:56 -0700 (PDT) Cc: mc@cs.Stanford.EDU 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/