Re: [CHECKER] potential dereference of user pointer errors

From: Junfeng Yang (yjf@stanford.edu)
Date: Sun Mar 23 2003 - 18:10:06 EST


Hi,

Here are more bugs on derefences of user pointers.

Where the bugs occur:

      fs/intermezzo/vfs.c
      drivers/media/video/zoran_procfs.c
      drivers/media/video/zr36120.c
      drivers/video/sis/sis_main.c
      drivers/char/specialix.c
      drivers/pnp/pnpbios/proc.c
      drivers/media/dvb/av7110/av7110_ir.c
      drivers/usb/serial/ipaq.c
      drivers/char/vt.c
      drivers/isdn/hardware/eicon/divasproc.c
      drivers/media/radio/radio-cadet.c
      drivers/media/video/bw-qcam.c
      sound/pci/es1938.c
      sound/oss/awe_wave.c
      sound/isa/sb/sb16_csp.c
      sound/oss/cmpci.c

Main sources of bugs: proc_write functions and ioctl functions

Thanks a lot for Chris and other people's replies on my previous error
reports.

Junfeng

---------------------------------------------------------
[BUG] write_proc
/home/junfeng/linux-2.5.63/drivers/media/video/zoran_procfs.c:122:zoran_write_proc:
ERROR:tainted:122:122: passing buffer into deref cal __constant_memcpy
[dist=1][thru proc_dir_entry:write_proc
/home/junfeng/linux-2.5.63/drivers/media/video/cpia.c:cpia_write_proc:parm1
copy_from_user:parm1][START: buffer, unknown->tainted,
/home/junfeng/linux-2.5.63/drivers/media/video/zoran_procfs.c,
zoran_write_proc, 122]

        string = sp = vmalloc(count + 1);
        if (!string) {
                printk(KERN_ERR "%s: write_proc: can not allocate
memory\n", zr->name);
                return -ENOMEM;
        }

Error --->
        memcpy(string, buffer, count);
        string[count] = 0;
        DEBUG2(printk(KERN_INFO "%s: write_proc: name=%s count=%lu
data=%x\n", zr->name, file->f_dentry->d_name.name, count, (int) data));
        ldelim = " \t\n";
---------------------------------------------------------
[BUG] buf is passed into access_ok.
/home/junfeng/linux-2.5.63/drivers/char/specialix.c:1654:sx_write:
ERROR:tainted:1654:1654: passing buf into deref cal __constant_memcpy
[dist=1][thru tty_driver:write
/home/junfeng/linux-2.5.63/drivers/char/epca.c:pc_write:parm2
copy_from_user:parm1][START: buf, unknown->tainted,
/home/junfeng/linux-2.5.63/drivers/char/specialix.c, sx_write, 1654]

                                           SERIAL_XMIT_SIZE -
port->xmit_head));
                        if (c <= 0) {
                                restore_flags(flags);
                                break;
                        }

Error --->
                        memcpy(port->xmit_buf + port->xmit_head, buf, c);
                        port->xmit_head = (port->xmit_head + c) &
(SERIAL_XMIT_SIZE-1);
                        port->xmit_cnt += c;
                        restore_flags(flags);
---------------------------------------------------------
[BUG] buf is passed into access_ok, which implies it is tainted.
/home/junfeng/linux-2.5.63/drivers/media/video/zr36120.c:1698:vbi_read:
ERROR:tainted:1698:1698:deferencing optr++ tainted by [dist=-1][(null)]

                {
                        /* copy to doubled data to userland */
                        for (x=0; optr+1<eptr && x<-done->w; x++)
                        {
                                unsigned char a = iptr[x*2];

Error --->
                                *optr++ = a;
                                *optr++ = a;
                        }
                        /* and clear the rest of the line */
---------------------------------------------------------
[BUG]
/home/junfeng/linux-2.5.63/drivers/video/sis/sis_main.c:1817:sis_malloc:
ERROR:tainted:1817:1817:deferencing req tainted by [dist=2][ called by
sisfb_ioctl:parm3 thru fb_ops:fb_ioctl
/home/junfeng/linux-2.5.63/drivers/video/matrox/matroxfb_crtc2.c:matroxfb_dh_ioctl:parm3
copy_to_user:parm0][START: req, unknown->tainted,
/home/junfeng/linux-2.5.63/drivers/video/sis/sis_main.c, sis_malloc, 1817]

void sis_malloc(struct sis_memreq *req)
{
        SIS_OH *poh;

Error --->
        poh = sisfb_poh_allocate(req->size);

        if (poh == NULL) {
                req->offset = 0;
---------------------------------------------------------
[BUG] proc_write
/home/junfeng/linux-2.5.63/drivers/pnp/pnpbios/proc.c:190:proc_write_node:
ERROR:tainted:190:190: passing buf into deref cal __constant_memcpy
[dist=1][thru proc_dir_entry:write_proc
/home/junfeng/linux-2.5.63/drivers/media/video/cpia.c:cpia_write_proc:parm1
copy_from_user:parm1][START: buf, unknown->tainted,
/home/junfeng/linux-2.5.63/drivers/pnp/pnpbios/proc.c, proc_write_node,
190]

        if (!node) return -ENOMEM;
        if ( pnp_bios_get_dev_node(&nodenum, boot, node) )
                return -EIO;
        if (count != node->size - sizeof(struct pnp_bios_node))
                return -EINVAL;

Error --->
        memcpy(node->data, buf, count);
        if (pnp_bios_set_dev_node(node->handle, boot, node) != 0)
            return -EINVAL;
        kfree(node);
---------------------------------------------------------
[BUG] bug is in lento_symlink. oldname is passed into getname, which
implies it is tainted. Then it is passed to presto_do_symlink. should pass
in "from" not "oldname".
/home/junfeng/linux-2.5.63/fs/namei.c:2190:page_symlink:
ERROR:tainted:2190:2190: passing symname into deref cal __constant_memcpy
[dist=6][ called by
/home/junfeng/linux-2.5.63/fs/ramfs/inode.c:ramfs_symlink:parm2 thru
inode_operations:symlink
/home/junfeng/linux-2.5.63/fs/intermezzo/dir.c:presto_symlink:parm2
calling
/home/junfeng/linux-2.5.63/fs/intermezzo/vfs.c:presto_do_symlink:parm3
called by lento_symlink calling
/home/junfeng/linux-2.5.63/fs/namei.c:getname called by
/home/junfeng/linux-2.5.63/fs/open.c:sys_open sys_open:parm0][START:
symname, unknown->tainted, /home/junfeng/linux-2.5.63/fs/namei.c,
page_symlink, 2190]

                goto fail;
        err = mapping->a_ops->prepare_write(NULL, page, 0, len-1);
        if (err)
                goto fail_map;
        kaddr = kmap_atomic(page, KM_USER0);

Error --->
        memcpy(kaddr, symname, len-1);
        kunmap_atomic(kaddr, KM_USER0);
        mapping->a_ops->commit_write(NULL, page, 0, len-1);
        /*
---------------------------------------------------------
[BUG] buf is passed to access_ok
/home/junfeng/linux-2.5.63/drivers/media/video/zr36120.c:1703:vbi_read:
ERROR:tainted:1703:1703:deferencing optr++ tainted by [dist=-1][(null)]

                                *optr++ = a;
                                *optr++ = a;
                        }
                        /* and clear the rest of the line */
                        for (x*=2; optr<eptr && x<done->bpl; x++)

Error --->
                                *optr++ = 0;
                        /* next line */
                        iptr += done->bpl;
                }
---------------------------------------------------------
[BUG] in the caller cm_write, buff is passed into access_ok
/home/junfeng/linux-2.5.63/sound/oss/cmpci.c:593:trans_ac3:
ERROR:tainted:593:593:deferencing src++ tainted by [dist=-1][(null)]

        unsigned long data;
        unsigned long *dst = (unsigned long *) dest;
        unsigned short *src = (unsigned short *)source;

        do {

Error --->
                data = (unsigned long) *src++;
                data <<= 12; // ok for 16-bit data
                if (s->spdif_counter == 2 || s->spdif_counter == 3)
                        data |= 0x40000000; // indicate AC-3 raw data
---------------------------------------------------------
[BUG]
/home/junfeng/linux-2.5.63/sound/oss/cmpci.c:1673:cm_write:
ERROR:tainted:1673:1673:deferencing src++ tainted by [dist=-1][(null)]

                        src = (unsigned long *) buffer;
                        dst0 = (unsigned long *) (s->dma_dac.rawbuf +
swptr);
                        dst1 = (unsigned long *) (s->dma_adc.rawbuf +
swptr);
                        // copy left/right sample at one time
                        for (i = 0; i <= cnt / 4; i++) {

Error --->
                                *dst0++ = *src++;
                                *dst1++ = *src++;
                        }
                        swptr = (swptr + cnt) % s->dma_dac.dmasize;
---------------------------------------------------------
[BUG] Bug is in ipaq_write. if debug is on, can print out kernel data
/home/junfeng/linux-2.5.63/drivers/usb/serial/usb-serial.h:363:usb_serial_debug_data:
ERROR:tainted:363:363:deferencing data tainted by [dist=2][ called by
/home/junfeng/linux-2.5.63/drivers/usb/serial/ipaq.c:ipaq_write:parm2 thru
usb_serial_device_type:write
/home/junfeng/linux-2.5.63/drivers/usb/serial/keyspan_pda.c:keyspan_pda_write:parm2
copy_from_user:parm1][START: data, unknown->tainted,
/home/junfeng/linux-2.5.63/drivers/usb/serial/usb-serial.h,
usb_serial_debug_data, 363]

        if (!debug)
                return;

        printk (KERN_DEBUG "%s: %s - length = %d, data = ", file,
function, size);
        for (i = 0; i < size; ++i) {

Error --->
                printk ("%.2x ", data[i]);
        }
        printk ("\n");
}
---------------------------------------------------------
[BUG] write_proc
/home/junfeng/linux-2.5.63/drivers/media/dvb/av7110/av7110_ir.c:116:av7110_ir_write_proc:
ERROR:tainted:116:116: passing buffer into deref cal __constant_memcpy
[dist=1][thru proc_dir_entry:write_proc
/home/junfeng/linux-2.5.63/drivers/media/video/cpia.c:cpia_write_proc:parm1
copy_from_user:parm1][START: buffer, unknown->tainted,
/home/junfeng/linux-2.5.63/drivers/media/dvb/av7110/av7110_ir.c,
av7110_ir_write_proc, 116]

        u32 ir_config;

        if (count < 4 + 256 * sizeof(u16))
                return -EINVAL;

Error --->
        memcpy (&ir_config, buffer, 4);
        memcpy (&key_map, buffer + 4, 256 * sizeof(u16));

        av7110_setup_irc_config (NULL, ir_config);
---------------------------------------------------------
[BUG]
/home/junfeng/linux-2.5.63/drivers/video/sis/sis_main.c:276:sis_dispinfo:
ERROR:tainted:276:276:deferencing rec tainted by [dist=2][ called by
sisfb_ioctl:parm3 thru fb_ops:fb_ioctl
/home/junfeng/linux-2.5.63/drivers/video/matrox/matroxfb_crtc2.c:matroxfb_dh_ioctl:parm3
copy_to_user:parm0][START: rec, unknown->tainted,
/home/junfeng/linux-2.5.63/drivers/video/sis/sis_main.c, sis_dispinfo,
276]

        gly->ngmask = size;
}

void sis_dispinfo(struct ap_data *rec)
{

Error --->
        rec->minfo.bpp = ivideo.video_bpp;
        rec->minfo.xres = ivideo.video_width;
        rec->minfo.yres = ivideo.video_height;
        rec->minfo.v_xres = ivideo.video_vwidth;
---------------------------------------------------------
[BUG]
/home/junfeng/linux-2.5.63/sound/oss/awe_wave.c:2049:awe_ioctl:
ERROR:tainted:2049:2049: passing arg into deref cal __constant_memcpy
[dist=1][thru synth_operations:ioctl
/home/junfeng/linux-2.5.63/sound/oss/gus_wave.c:guswave_ioctl:parm2
copy_to_user:parm0][START: arg, unknown->tainted,
/home/junfeng/linux-2.5.63/sound/oss/awe_wave.c, awe_ioctl, 2049]

        case SNDCTL_SYNTH_INFO:
                if (playing_mode == AWE_PLAY_DIRECT)
                        awe_info.nr_voices = awe_max_voices;
                else
                        awe_info.nr_voices = AWE_MAX_CHANNELS;

Error --->
                memcpy((char*)arg, &awe_info, sizeof(awe_info));
                return 0;
                break;

---------------------------------------------------------
[BUG] snd_sb_csp_ioctl -> snd_sb_csp_riff_load ->snd_sb_csp_load.
/home/junfeng/linux-2.5.63/sound/isa/sb/sb16_csp.c:647:snd_sb_csp_load:
ERROR:tainted:647:647:deferencing buf++ tainted by
[dist=-1][(null)][TRANS: buf++, $stop$->tainted,
/home/junfeng/linux-2.5.63/sound/isa/sb/sb16_csp.c, snd_sb_csp_load, 647]

                }
                kfree (_kbuf);
        } else {
                /* load from kernel space */
                while (size--) {

Error --->
                        if (!snd_sbdsp_command(p->chip, *buf++))
                                goto __fail;
                }
        }
---------------------------------------------------------
[BUG] vt_console_print is assigned to struct console.write
/home/junfeng/linux-2.5.63/drivers/char/vt.c:2126:vt_console_print:
ERROR:tainted:2126:2126:deferencing b++ tainted by
[dist=-1][(null)][TRANS: b++, $stop$->tainted,
/home/junfeng/linux-2.5.63/drivers/char/vt.c, vt_console_print, 2126]

        start = (ushort *)pos;

        /* Contrived structure to try to emulate original need_wrap
behaviour
         * Problems caused when we have need_wrap set on '\n' character */
        while (count--) {

Error --->
                c = *b++;
                if (c == 10 || c == 13 || c == 8 || need_wrap) {
                        if (cnt > 0) {
                                if (IS_VISIBLE)
---------------------------------------------------------
[BUG] write_proc
/home/junfeng/linux-2.5.63/drivers/isdn/hardware/eicon/divasproc.c:191:write_d_l1_down:
ERROR:tainted:191:191:deferencing buffer tainted by [dist=1][thru
proc_dir_entry:write_proc
/home/junfeng/linux-2.5.63/drivers/media/video/cpia.c:cpia_write_proc:parm1
copy_from_user:parm1][START: buffer, unknown->tainted,
/home/junfeng/linux-2.5.63/drivers/isdn/hardware/eicon/divasproc.c,
write_d_l1_down, 191]

{
        diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
        PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];

        if ((count == 1) || (count == 2)) {

Error --->
                switch (buffer[0]) {
                case '0':
                        IoAdapter->capi_cfg.cfg_1 &=
                            ~DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON;
---------------------------------------------------------
[BUG] in ioctl
/home/junfeng/linux-2.5.63/drivers/media/radio/radio-cadet.c:396:cadet_do_ioctl:
ERROR:tainted:395:396: passing v into deref cal
__constant_c_and_count_memset [dist=-1][(null)][TRANS: v,
tainted->tainted,
/home/junfeng/linux-2.5.63/drivers/media/radio/radio-cadet.c,
cadet_do_ioctl, 395]

{
        switch(cmd)
        {
                case VIDIOCGCAP:
                {
Start --->
                        struct video_capability *v = arg;
Error --->
                        memset(v,0,sizeof(*v));
                        v->type=VID_TYPE_TUNER;
                        v->channels=2;
                        v->audios=1;
---------------------------------------------------------
[BUG] in ioctl
/home/junfeng/linux-2.5.63/drivers/media/video/bw-qcam.c:836:qcam_do_ioctl:
ERROR:tainted:835:836: passing vw into deref cal
__constant_c_and_count_memset [dist=-1][(null)][TRANS: vw,
tainted->tainted,
/home/junfeng/linux-2.5.63/drivers/media/video/bw-qcam.c, qcam_do_ioctl,
835]

                        /* Ok we figured out what to use from our wide
choice */
                        return 0;
                }
                case VIDIOCGWIN:
                {
Start --->
                        struct video_window *vw = arg;
Error --->
                        memset(vw, 0, sizeof(*vw));
                        vw->width=qcam->width/qcam->transfer_scale;
                        vw->height=qcam->height/qcam->transfer_scale;
                        return 0;
---------------------------------------------------------
[BUG] copy function can take tainted inputs
/home/junfeng/linux-2.5.63/sound/pci/es1938.c:833:snd_es1938_capture_copy:
ERROR:tainted:835:833: passing dst into deref cal __constant_memcpy
[dist=1][thru snd_pcm_ops_t:copy
/home/junfeng/linux-2.5.63/sound/pci/cmipci.c:snd_cmipci_ac3_copy:parm3
copy_from_user:parm1][START: dst, unknown->tainted,
/home/junfeng/linux-2.5.63/sound/pci/es1938.c, snd_es1938_capture_copy,
833]

        es1938_t *chip = snd_pcm_substream_chip(substream);
        pos <<= chip->dma1_shift;
        count <<= chip->dma1_shift;
        snd_assert(pos + count <= chip->dma1_size, return -EINVAL);
        if (pos + count < chip->dma1_size)
Error --->
                memcpy(dst, runtime->dma_area + pos + 1, count);
        else {
Start --->
                memcpy(dst, runtime->dma_area + pos + 1, count - 1);
                ((unsigned char *)dst)[count - 1] = runtime->dma_area[0];
        }
        return 0;

-
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 : Sun Mar 23 2003 - 22:00:46 EST