コード例 #1
0
long compat_sys_semctl(int first, int second, int third, void __user *uptr)
{
	union semun fourth;
	u32 pad;
	int err, err2;
	struct semid64_ds s64;
	struct semid64_ds __user *up64;
	int version = compat_ipc_parse_version(&third);

	if (!uptr)
		return -EINVAL;
	if (get_user(pad, (u32 __user *) uptr))
		return -EFAULT;
	if ((third & (~IPC_64)) == SETVAL)
		fourth.val = (int) pad;
	else
		fourth.__pad = compat_ptr(pad);
	switch (third & (~IPC_64)) {
	case IPC_INFO:
	case IPC_RMID:
	case SEM_INFO:
	case GETVAL:
	case GETPID:
	case GETNCNT:
	case GETZCNT:
	case GETALL:
	case SETVAL:
	case SETALL:
		err = sys_semctl(first, second, third, fourth);
		break;

	case IPC_STAT:
	case SEM_STAT:
		up64 = compat_alloc_user_space(sizeof(s64));
		fourth.__pad = up64;
		err = sys_semctl(first, second, third, fourth);
		if (err < 0)
			break;
		if (copy_from_user(&s64, up64, sizeof(s64)))
			err2 = -EFAULT;
		else if (version == IPC_64)
			err2 = put_compat_semid64_ds(&s64, compat_ptr(pad));
		else
			err2 = put_compat_semid_ds(&s64, compat_ptr(pad));
		if (err2)
			err = -EFAULT;
		break;

	case IPC_SET:
		if (version == IPC_64) {
			err = get_compat_semid64_ds(&s64, compat_ptr(pad));
		} else {
			err = get_compat_semid_ds(&s64, compat_ptr(pad));
		}
		up64 = compat_alloc_user_space(sizeof(s64));
		if (copy_to_user(up64, &s64, sizeof(s64)))
			err = -EFAULT;
		if (err)
			break;

		fourth.__pad = up64;
		err = sys_semctl(first, second, third, fourth);
		break;

	default:
		err = -EINVAL;
		break;
	}
	return err;
}
コード例 #2
0
ファイル: compat.c プロジェクト: laborjack/ENGLinuxLatest
int compat_mc_getsockopt(struct sock *sock, int level, int optname,
	char __user *optval, int __user *optlen,
	int (*getsockopt)(struct sock *, int, int, char __user *, int __user *))
{
	struct compat_group_filter __user *gf32 = (void *)optval;
	struct group_filter __user *kgf;
	int __user	*koptlen;
	u32 interface, fmode, numsrc;
	int klen, ulen, err;

	if (optname != MCAST_MSFILTER)
		return getsockopt(sock, level, optname, optval, optlen);

	koptlen = compat_alloc_user_space(sizeof(*koptlen));
	if (!access_ok(VERIFY_READ, optlen, sizeof(*optlen)) ||
	    __get_user(ulen, optlen))
		return -EFAULT;

	/* adjust len for pad */
	klen = ulen + sizeof(*kgf) - sizeof(*gf32);

	if (klen < GROUP_FILTER_SIZE(0))
		return -EINVAL;

	if (!access_ok(VERIFY_WRITE, koptlen, sizeof(*koptlen)) ||
	    __put_user(klen, koptlen))
		return -EFAULT;

	/* have to allow space for previous compat_alloc_user_space, too */
	kgf = compat_alloc_user_space(klen+sizeof(*optlen));

	if (!access_ok(VERIFY_READ, gf32, __COMPAT_GF0_SIZE) ||
	    __get_user(interface, &gf32->gf_interface) ||
	    __get_user(fmode, &gf32->gf_fmode) ||
	    __get_user(numsrc, &gf32->gf_numsrc) ||
	    __put_user(interface, &kgf->gf_interface) ||
	    __put_user(fmode, &kgf->gf_fmode) ||
	    __put_user(numsrc, &kgf->gf_numsrc) ||
	    copy_in_user(&kgf->gf_group, &gf32->gf_group, sizeof(kgf->gf_group)))
		return -EFAULT;

	err = getsockopt(sock, level, optname, (char __user *)kgf, koptlen);
	if (err)
		return err;

	if (!access_ok(VERIFY_READ, koptlen, sizeof(*koptlen)) ||
	    __get_user(klen, koptlen))
		return -EFAULT;

	ulen = klen - (sizeof(*kgf)-sizeof(*gf32));

	if (!access_ok(VERIFY_WRITE, optlen, sizeof(*optlen)) ||
	    __put_user(ulen, optlen))
		return -EFAULT;

	if (!access_ok(VERIFY_READ, kgf, klen) ||
	    !access_ok(VERIFY_WRITE, gf32, ulen) ||
	    __get_user(interface, &kgf->gf_interface) ||
	    __get_user(fmode, &kgf->gf_fmode) ||
	    __get_user(numsrc, &kgf->gf_numsrc) ||
	    __put_user(interface, &gf32->gf_interface) ||
	    __put_user(fmode, &gf32->gf_fmode) ||
	    __put_user(numsrc, &gf32->gf_numsrc))
		return -EFAULT;
	if (numsrc) {
		int copylen;

		klen -= GROUP_FILTER_SIZE(0);
		copylen = numsrc * sizeof(gf32->gf_slist[0]);
		if (copylen > klen)
			copylen = klen;
		if (copy_in_user(gf32->gf_slist, kgf->gf_slist, copylen))
			return -EFAULT;
	}
	return err;
}
コード例 #3
0
ファイル: compat.c プロジェクト: laborjack/ENGLinuxLatest
int compat_mc_setsockopt(struct sock *sock, int level, int optname,
	char __user *optval, unsigned int optlen,
	int (*setsockopt)(struct sock *, int, int, char __user *, unsigned int))
{
	char __user	*koptval = optval;
	int		koptlen = optlen;

	switch (optname) {
	case MCAST_JOIN_GROUP:
	case MCAST_LEAVE_GROUP:
	{
		struct compat_group_req __user *gr32 = (void *)optval;
		struct group_req __user *kgr =
			compat_alloc_user_space(sizeof(struct group_req));
		u32 interface;

		if (!access_ok(VERIFY_READ, gr32, sizeof(*gr32)) ||
		    !access_ok(VERIFY_WRITE, kgr, sizeof(struct group_req)) ||
		    __get_user(interface, &gr32->gr_interface) ||
		    __put_user(interface, &kgr->gr_interface) ||
		    copy_in_user(&kgr->gr_group, &gr32->gr_group,
				sizeof(kgr->gr_group)))
			return -EFAULT;
		koptval = (char __user *)kgr;
		koptlen = sizeof(struct group_req);
		break;
	}
	case MCAST_JOIN_SOURCE_GROUP:
	case MCAST_LEAVE_SOURCE_GROUP:
	case MCAST_BLOCK_SOURCE:
	case MCAST_UNBLOCK_SOURCE:
	{
		struct compat_group_source_req __user *gsr32 = (void *)optval;
		struct group_source_req __user *kgsr = compat_alloc_user_space(
			sizeof(struct group_source_req));
		u32 interface;

		if (!access_ok(VERIFY_READ, gsr32, sizeof(*gsr32)) ||
		    !access_ok(VERIFY_WRITE, kgsr,
			sizeof(struct group_source_req)) ||
		    __get_user(interface, &gsr32->gsr_interface) ||
		    __put_user(interface, &kgsr->gsr_interface) ||
		    copy_in_user(&kgsr->gsr_group, &gsr32->gsr_group,
				sizeof(kgsr->gsr_group)) ||
		    copy_in_user(&kgsr->gsr_source, &gsr32->gsr_source,
				sizeof(kgsr->gsr_source)))
			return -EFAULT;
		koptval = (char __user *)kgsr;
		koptlen = sizeof(struct group_source_req);
		break;
	}
	case MCAST_MSFILTER:
	{
		struct compat_group_filter __user *gf32 = (void *)optval;
		struct group_filter __user *kgf;
		u32 interface, fmode, numsrc;

		if (!access_ok(VERIFY_READ, gf32, __COMPAT_GF0_SIZE) ||
		    __get_user(interface, &gf32->gf_interface) ||
		    __get_user(fmode, &gf32->gf_fmode) ||
		    __get_user(numsrc, &gf32->gf_numsrc))
			return -EFAULT;
		koptlen = optlen + sizeof(struct group_filter) -
				sizeof(struct compat_group_filter);
		if (koptlen < GROUP_FILTER_SIZE(numsrc))
			return -EINVAL;
		kgf = compat_alloc_user_space(koptlen);
		if (!access_ok(VERIFY_WRITE, kgf, koptlen) ||
		    __put_user(interface, &kgf->gf_interface) ||
		    __put_user(fmode, &kgf->gf_fmode) ||
		    __put_user(numsrc, &kgf->gf_numsrc) ||
		    copy_in_user(&kgf->gf_group, &gf32->gf_group,
				sizeof(kgf->gf_group)) ||
		    (numsrc && copy_in_user(kgf->gf_slist, gf32->gf_slist,
				numsrc * sizeof(kgf->gf_slist[0]))))
			return -EFAULT;
		koptval = (char __user *)kgf;
		break;
	}

	default:
		break;
	}
	return setsockopt(sock, level, optname, koptval, koptlen);
}
コード例 #4
0
ファイル: compat.c プロジェクト: DentonGentry/gfiber-gfrg100
long compat_sys_shmctl(int first, int second, void __user *uptr)
{
	void __user *p;
	struct shmid64_ds s64;
	struct shminfo64 smi;
	int err, err2;
	int version = compat_ipc_parse_version(&second);

	switch (second & (~IPC_64)) {
	case IPC_RMID:
	case SHM_LOCK:
	case SHM_UNLOCK:
		err = sys_shmctl(first, second, uptr);
		break;

	case IPC_INFO:
		p = compat_alloc_user_space(sizeof(smi));
		err = sys_shmctl(first, second, p);
		if (err < 0)
			break;
		if (copy_from_user(&smi, p, sizeof(smi)))
			err2 = -EFAULT;
		else if (version == IPC_64)
			err2 = put_compat_shminfo64(&smi, uptr);
		else
			err2 = put_compat_shminfo(&smi, uptr);
		if (err2)
			err = -EFAULT;
		break;


	case IPC_SET:
		if (version == IPC_64) {
			err = get_compat_shmid64_ds(&s64, uptr);
		} else {
			err = get_compat_shmid_ds(&s64, uptr);
		}
		if (err)
			break;
		p = compat_alloc_user_space(sizeof(s64));
		if (copy_to_user(p, &s64, sizeof(s64)))
			err = -EFAULT;
		else
			err = sys_shmctl(first, second, p);
		break;

	case IPC_STAT:
	case SHM_STAT:
		p = compat_alloc_user_space(sizeof(s64));
		err = sys_shmctl(first, second, p);
		if (err < 0)
			break;
		if (copy_from_user(&s64, p, sizeof(s64)))
			err2 = -EFAULT;
		else if (version == IPC_64)
			err2 = put_compat_shmid64_ds(&s64, uptr);
		else
			err2 = put_compat_shmid_ds(&s64, uptr);
		if (err2)
			err = -EFAULT;
		break;

	case SHM_INFO:
		p = compat_alloc_user_space(sizeof(struct shm_info));
		err = sys_shmctl(first, second, p);
		if (err < 0)
			break;
		err2 = put_compat_shm_info(p, uptr);
		if (err2)
			err = -EFAULT;
		break;

	default:
		err = -EINVAL;
		break;
	}
	return err;
}
コード例 #5
0
static long compat_fimg2d_ioctl32(struct file *file, unsigned int cmd,
							unsigned long arg)
{
	switch (cmd) {
	case COMPAT_FIMG2D_BITBLT_BLIT:
	{
		struct compat_fimg2d_blit __user *data32;
		struct fimg2d_blit __user *data;
		struct mm_struct *mm;
		enum blit_op op;
		enum blit_sync sync;
		enum fimg2d_qos_level qos_lv;
		compat_uint_t seq_no;
		unsigned long stack_cursor = 0;
		int err;

		mm = get_task_mm(current);
		if (!mm) {
			fimg2d_err("no mm for ctx\n");
			return -ENXIO;
		}

		data32 = compat_ptr(arg);
		data = compat_alloc_user_space(sizeof(*data));
		if (!data) {
			fimg2d_err("failed to allocate user compat space\n");
			mmput(mm);
			return -ENOMEM;
		}

		stack_cursor += sizeof(*data);
		if (clear_user(data, sizeof(*data))) {
			fimg2d_err("failed to access to userspace\n");
			mmput(mm);
			return -EPERM;
		}

		err = get_user(op, &data32->op);
		err |= put_user(op, &data->op);
		if (err) {
			fimg2d_err("failed to get compat data\n");
			mmput(mm);
			return err;
		}

		err = compat_get_fimg2d_param(&data->param, &data32->param);
		if (err) {
			fimg2d_err("failed to get compat data\n");
			mmput(mm);
			return err;
		}

		if (data32->src) {
			data->src = compat_alloc_user_space(sizeof(*data->src) +
								stack_cursor);
			if (!data->src) {
				fimg2d_err("failed to allocate user compat space\n");
				mmput(mm);
				return -ENOMEM;
			}

			stack_cursor += sizeof(*data->src);
			err = compat_get_fimg2d_image(data->src, data32->src);
			if (err) {
				fimg2d_err("failed to get compat data\n");
				mmput(mm);
				return err;
			}
		}

		if (data32->msk) {
			data->msk = compat_alloc_user_space(sizeof(*data->msk) +
								stack_cursor);
			if (!data->msk) {
				fimg2d_err("failed to allocate user compat space\n");
				mmput(mm);
				return -ENOMEM;
			}

			stack_cursor += sizeof(*data->msk);
			err = compat_get_fimg2d_image(data->msk, data32->msk);
			if (err) {
				fimg2d_err("failed to get compat data\n");
				mmput(mm);
				return err;
			}
		}

		if (data32->tmp) {
			data->tmp = compat_alloc_user_space(sizeof(*data->tmp) +
								stack_cursor);
			if (!data->tmp) {
				fimg2d_err("failed to allocate user compat space\n");
				mmput(mm);
				return -ENOMEM;
			}

			stack_cursor += sizeof(*data->tmp);
			err = compat_get_fimg2d_image(data->tmp, data32->tmp);
			if (err) {
				fimg2d_err("failed to get compat data\n");
				mmput(mm);
				return err;
			}
		}

		if (data32->dst) {
			data->dst = compat_alloc_user_space(sizeof(*data->dst) +
								stack_cursor);
			if (!data->dst) {
				fimg2d_err("failed to allocate user compat space\n");
				mmput(mm);
				return -ENOMEM;
			}

			stack_cursor += sizeof(*data->dst);
			err = compat_get_fimg2d_image(data->dst, data32->dst);
			if (err) {
				fimg2d_err("failed to get compat data\n");
				mmput(mm);
				return err;
			}
		}

		err = get_user(sync, &data32->sync);
		err |= put_user(sync, &data->sync);
		if (err) {
			fimg2d_err("failed to get compat data\n");
			mmput(mm);
			return err;
		}

		err = get_user(seq_no, &data32->seq_no);
		err |= put_user(seq_no, &data->seq_no);
		if (err) {
			fimg2d_err("failed to get compat data\n");
			mmput(mm);
			return err;
		}

		err = get_user(qos_lv, &data32->qos_lv);
		err |= put_user(qos_lv, &data->qos_lv);
		if (err) {
			fimg2d_err("failed to get compat data\n");
			mmput(mm);
			return err;
		}

		err = file->f_op->unlocked_ioctl(file,
				FIMG2D_BITBLT_BLIT, (unsigned long)data);
		mmput(mm);
		return err;
	}
	case COMPAT_FIMG2D_BITBLT_VERSION:
	{
		struct compat_fimg2d_version __user *data32;
		struct fimg2d_version __user *data;
		compat_uint_t i;
		int err;

		data32 = compat_ptr(arg);
		data = compat_alloc_user_space(sizeof(*data));
		if (!data) {
			fimg2d_err("failed to allocate user compat space\n");
			return -ENOMEM;
		}

		err = get_user(i, &data32->hw);
		err |= put_user(i, &data->hw);
		err |= get_user(i, &data32->sw);
		err |= put_user(i, &data->sw);

		if (err)
			return err;

		return file->f_op->unlocked_ioctl(file,
				FIMG2D_BITBLT_VERSION, (unsigned long)data);
	}
	case FIMG2D_BITBLT_ACTIVATE:
	{
		return file->f_op->unlocked_ioctl(file,
				FIMG2D_BITBLT_ACTIVATE, arg);
	}
	default:
		fimg2d_err("unknown ioctl\n");
		return -EINVAL;
	}
}
コード例 #6
0
static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
{
	struct v4l2_plane32 __user *uplane32;
	struct v4l2_plane __user *uplane;
	compat_caddr_t p;
	int num_planes;
	int ret;

	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
		get_user(kp->index, &up->index) ||
		get_user(kp->type, &up->type) ||
		get_user(kp->flags, &up->flags) ||
		get_user(kp->memory, &up->memory) ||
		get_user(kp->input, &up->input))
			return -EFAULT;

	if (V4L2_TYPE_IS_OUTPUT(kp->type))
		if (get_user(kp->bytesused, &up->bytesused) ||
			get_user(kp->field, &up->field) ||
			get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
			get_user(kp->timestamp.tv_usec,
					&up->timestamp.tv_usec))
			return -EFAULT;

	if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
		if (get_user(kp->length, &up->length))
			return -EFAULT;

		num_planes = kp->length;
		if (num_planes == 0) {
			kp->m.planes = NULL;
			/* num_planes == 0 is legal, e.g. when userspace doesn't
			 * need planes array on DQBUF*/
			return 0;
		}

		if (get_user(p, &up->m.planes))
			return -EFAULT;

		uplane32 = compat_ptr(p);
		if (!access_ok(VERIFY_READ, uplane32,
				num_planes * sizeof(struct v4l2_plane32)))
			return -EFAULT;

		/* We don't really care if userspace decides to kill itself
		 * by passing a very big num_planes value */
		uplane = compat_alloc_user_space(num_planes *
						sizeof(struct v4l2_plane));
		kp->m.planes = uplane;

		while (--num_planes >= 0) {
			ret = get_v4l2_plane32(uplane, uplane32, kp->memory);
			if (ret)
				return ret;
			++uplane;
			++uplane32;
		}
	} else {
		switch (kp->memory) {
		case V4L2_MEMORY_MMAP:
			if (get_user(kp->length, &up->length) ||
				get_user(kp->m.offset, &up->m.offset))
				return -EFAULT;
			break;
		case V4L2_MEMORY_USERPTR:
			{
			compat_long_t tmp;

			if (get_user(kp->length, &up->length) ||
			    get_user(tmp, &up->m.userptr))
				return -EFAULT;

			kp->m.userptr = (unsigned long)compat_ptr(tmp);
			}
			break;
		case V4L2_MEMORY_OVERLAY:
			if (get_user(kp->m.offset, &up->m.offset))
				return -EFAULT;
			break;
		}
	}

	return 0;
}