| /* { dg-do compile } */ |
| // TODO: remove need for -fanalyzer-checker=taint here: |
| /* { dg-options "-fanalyzer -fanalyzer-checker=taint" } */ |
| /* { dg-require-effective-target analyzer } */ |
| |
| /* See notes in this header. */ |
| #include "taint-CVE-2011-0521.h" |
| |
| /* Adapted from drivers/media/dvb/ttpci/av7110_ca.c */ |
| |
| int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg) |
| { |
| struct dvb_device *dvbdev = file->private_data; |
| struct av7110 *av7110 = dvbdev->priv; |
| unsigned long arg = (unsigned long) parg; |
| |
| /* case CA_GET_SLOT_INFO: */ |
| { |
| ca_slot_info_t *info=(ca_slot_info_t *)parg; |
| |
| if (info->num > 1) |
| return -EINVAL; |
| av7110->ci_slot[info->num].num = info->num; /* { dg-warning "attacker-controlled value" "" { xfail *-*-* } } */ |
| av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? |
| CA_CI_LINK : CA_CI; |
| memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); |
| } |
| return 0; |
| } |
| |
| /* Adapted from drivers/media/dvb/dvb-core/dvbdev.c |
| Somewhat simplified: rather than pass in a callback that can |
| be dvb_ca_ioctl, call dvb_ca_ioctl directly. */ |
| |
| static DEFINE_MUTEX(dvbdev_mutex); |
| |
| int dvb_usercopy(struct file *file, |
| unsigned int cmd, unsigned long arg) |
| { |
| char sbuf[128]; |
| void *mbuf = NULL; |
| void *parg = NULL; |
| int err = -1; |
| |
| /* Copy arguments into temp kernel buffer */ |
| switch (_IOC_DIR(cmd)) { |
| case _IOC_NONE: |
| /* |
| * For this command, the pointer is actually an integer |
| * argument. |
| */ |
| parg = (void *) arg; |
| break; |
| case _IOC_READ: /* some v4l ioctls are marked wrong ... */ |
| case _IOC_WRITE: |
| case (_IOC_WRITE | _IOC_READ): |
| if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { |
| parg = sbuf; |
| } else { |
| /* too big to allocate from stack */ |
| mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); |
| if (NULL == mbuf) |
| return -ENOMEM; |
| parg = mbuf; |
| } |
| |
| err = -EFAULT; |
| if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) |
| goto out; |
| break; |
| } |
| |
| /* call driver */ |
| mutex_lock(&dvbdev_mutex); |
| if ((err = dvb_ca_ioctl(file, cmd, parg)) == -ENOIOCTLCMD) |
| err = -EINVAL; |
| mutex_unlock(&dvbdev_mutex); |
| |
| if (err < 0) |
| goto out; |
| |
| /* Copy results into user buffer */ |
| switch (_IOC_DIR(cmd)) |
| { |
| case _IOC_READ: |
| case (_IOC_WRITE | _IOC_READ): |
| if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) |
| err = -EFAULT; |
| break; |
| } |
| |
| out: |
| kfree(mbuf); |
| return err; |
| } |