/* Shared header for the various taint-CVE-2011-0521-*.c tests.
   These are a series of successively simpler reductions of the reproducer.
   Ideally the analyzer would detect the issue in all of the testcases,
   but currently requires some simplification of the code to do so.

   "The dvb_ca_ioctl function in drivers/media/dvb/ttpci/av7110_ca.c in the
   Linux kernel before 2.6.38-rc2 does not check the sign of a certain integer
   field, which allows local users to cause a denial of service (memory
   corruption) or possibly have unspecified other impact via a negative value."

   Adapted from Linux 2.6.38, which is under the GPLv2.

   Fixed in e.g. cb26a24ee9706473f31d34cc259f4dcf45cd0644 on linux-2.6.38.y  */

#include <string.h>
#include "test-uaccess.h"
#include "../analyzer/analyzer-decls.h"

typedef unsigned int u32;

/* Adapted from include/linux/compiler.h  */

#define __force

/* Adapted from include/asm-generic/errno-base.h  */

#define	ENOMEM		12	/* Out of memory */
#define	EFAULT		14	/* Bad address */
#define	ENODEV		19	/* No such device */
#define	EINVAL		22	/* Invalid argument */

/* Adapted from include/linux/errno.h  */

#define ENOIOCTLCMD	515	/* No ioctl command */

/* Adapted from include/linux/fs.h  */

struct file {
	/* [...snip...] */
	void			*private_data;
	/* [...snip...] */
};

/* Adapted from drivers/media/dvb/dvb-core/dvbdev.h  */

struct dvb_device {
	/* [...snip...] */
	int (*kernel_ioctl)(struct file *file, unsigned int cmd, void *arg);

	void *priv;
};


/* Adapted from include/linux/dvb/ca.h  */

typedef struct ca_slot_info {
	int num;               /* slot number */

	int type;              /* CA interface this slot supports */
#define CA_CI            1     /* CI high level interface */
#define CA_CI_LINK       2     /* CI link layer level interface */
	/* [...snip...] */
} ca_slot_info_t;


/* Adapted from drivers/media/dvb/ttpci/av7110.h  */

struct av7110 {
	/* [...snip...] */
	ca_slot_info_t		ci_slot[2];
	/* [...snip...] */
	u32		    arm_app;
	/* [...snip...] */
};

/* Adapted from drivers/media/dvb/ttpci/av7110_hw.h  */

#define FW_CI_LL_SUPPORT(arm_app) ((arm_app) & 0x80000000)

/* Adapted from include/asm-generic/ioctl.h  */

#define _IOC_NRBITS	8
#define _IOC_TYPEBITS	8

#define _IOC_SIZEBITS	14
#define _IOC_DIRBITS	2

#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
#define _IOC_NRSHIFT	0
#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)

#define _IOC_NONE	0U
#define _IOC_WRITE	1U
#define _IOC_READ	2U

#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)

/* Adapted from include/linux/mutex.h  */

struct mutex {
	/* [...snip...] */
};

#define __MUTEX_INITIALIZER(lockname) \
		{ /* [...snip...] */ }

#define DEFINE_MUTEX(mutexname) \
	struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)

extern void mutex_lock(struct mutex *lock);
extern void mutex_unlock(struct mutex *lock);

/* Adapted from include/linux/types.h  */

#define __bitwise__
typedef unsigned __bitwise__ gfp_t;

/* Adapted from include/linux/gfp.h  */

#define ___GFP_WAIT		0x10u
#define ___GFP_IO		0x40u
#define ___GFP_FS		0x80u
#define __GFP_WAIT	((__force gfp_t)___GFP_WAIT)
#define __GFP_IO	((__force gfp_t)___GFP_IO)
#define __GFP_FS	((__force gfp_t)___GFP_FS)
#define GFP_KERNEL  (__GFP_WAIT | __GFP_IO | __GFP_FS)

/* Adapted from include/linux/slab.h  */

void kfree(const void *);
void *kmalloc(size_t size, gfp_t flags)
  __attribute__((malloc (kfree)));
