1  /* { dg-do compile } */
       2  // TODO: remove need for -fanalyzer-checker=taint here:
       3  /* { dg-options "-fanalyzer -fanalyzer-checker=taint" } */
       4  /* { dg-require-effective-target analyzer } */
       5  
       6  /* See notes in this header.  */
       7  #include "taint-CVE-2011-0521.h"
       8  
       9  // TODO: remove need for this option
      10  /* { dg-additional-options "-fanalyzer-checker=taint" } */
      11  
      12  /* Adapted from drivers/media/dvb/ttpci/av7110_ca.c  */
      13  
      14  int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg)
      15  {
      16  	struct dvb_device *dvbdev = file->private_data;
      17  	struct av7110 *av7110 = dvbdev->priv;
      18  	unsigned long arg = (unsigned long) parg;
      19  
      20  	/* case CA_GET_SLOT_INFO:  */
      21  	{
      22  		ca_slot_info_t *info=(ca_slot_info_t *)parg;
      23  
      24  		if (info->num < 0 || info->num > 1)
      25  			return -EINVAL;
      26  		av7110->ci_slot[info->num].num = info->num; /* { dg-bogus "attacker-controlled value" } */
      27  		av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
      28  							CA_CI_LINK : CA_CI;
      29  		memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t));
      30  	}
      31  	return 0;
      32  }
      33  
      34  /* Adapted from drivers/media/dvb/dvb-core/dvbdev.c
      35     Somewhat simplified: rather than pass in a callback that can
      36     be dvb_ca_ioctl, call dvb_ca_ioctl directly.  */
      37  
      38  static DEFINE_MUTEX(dvbdev_mutex);
      39  
      40  int dvb_usercopy(struct file *file,
      41  		 unsigned int cmd, unsigned long arg)
      42  {
      43  	char    sbuf[128];
      44  	void    *mbuf = NULL;
      45  	void    *parg = NULL;
      46  	int     err  = -1;
      47  
      48  	/*  Copy arguments into temp kernel buffer  */
      49  	switch (_IOC_DIR(cmd)) {
      50  	case _IOC_NONE:
      51  		/*
      52  		 * For this command, the pointer is actually an integer
      53  		 * argument.
      54  		 */
      55  		parg = (void *) arg;
      56  		break;
      57  	case _IOC_READ: /* some v4l ioctls are marked wrong ... */
      58  	case _IOC_WRITE:
      59  	case (_IOC_WRITE | _IOC_READ):
      60  		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
      61  			parg = sbuf;
      62  		} else {
      63  			/* too big to allocate from stack */
      64  			mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
      65  			if (NULL == mbuf)
      66  				return -ENOMEM;
      67  			parg = mbuf;
      68  		}
      69  
      70  		err = -EFAULT;
      71  		if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
      72  			goto out;
      73  		break;
      74  	}
      75  
      76  	/* call driver */
      77  	mutex_lock(&dvbdev_mutex);
      78  	if ((err = dvb_ca_ioctl(file, cmd, parg)) == -ENOIOCTLCMD)
      79  		err = -EINVAL;
      80  	mutex_unlock(&dvbdev_mutex);
      81  
      82  	if (err < 0)
      83  		goto out;
      84  
      85  	/*  Copy results into user buffer  */
      86  	switch (_IOC_DIR(cmd))
      87  	{
      88  	case _IOC_READ:
      89  	case (_IOC_WRITE | _IOC_READ):
      90  		if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
      91  			err = -EFAULT;
      92  		break;
      93  	}
      94  
      95  out:
      96  	kfree(mbuf);
      97  	return err;
      98  }