blob: 30cab38e002f033827113661bca102eb22b56ee0 [file] [log] [blame]
/* { 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;
}