Exemple #1
0
static int compat_agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
{
	struct agp_region32 ureserve;
	struct agp_region kreserve;
	struct agp_client *client;
	struct agp_file_private *client_priv;

	DBG("");
	if (copy_from_user(&ureserve, arg, sizeof(ureserve)))
		return -EFAULT;

	if ((unsigned) ureserve.seg_count >= ~0U/sizeof(struct agp_segment32))
		return -EFAULT;

	kreserve.pid = ureserve.pid;
	kreserve.seg_count = ureserve.seg_count;

	client = agp_find_client_by_pid(kreserve.pid);

	if (kreserve.seg_count == 0) {
		/* remove a client */
		client_priv = agp_find_private(kreserve.pid);

		if (client_priv != NULL) {
			set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
			set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
		}
		if (client == NULL) {
			/* client is already removed */
			return 0;
		}
		return agp_remove_client(kreserve.pid);
	} else {
		struct agp_segment32 *usegment;
		struct agp_segment *ksegment;
		int seg;

		if (ureserve.seg_count >= 16384)
			return -EINVAL;

		usegment = kmalloc(sizeof(*usegment) * ureserve.seg_count, GFP_KERNEL);
		if (!usegment)
			return -ENOMEM;

		ksegment = kmalloc(sizeof(*ksegment) * kreserve.seg_count, GFP_KERNEL);
		if (!ksegment) {
			kfree(usegment);
			return -ENOMEM;
		}

		if (copy_from_user(usegment, (void __user *) ureserve.seg_list,
				   sizeof(*usegment) * ureserve.seg_count)) {
			kfree(usegment);
			kfree(ksegment);
			return -EFAULT;
		}

		for (seg = 0; seg < ureserve.seg_count; seg++) {
			ksegment[seg].pg_start = usegment[seg].pg_start;
			ksegment[seg].pg_count = usegment[seg].pg_count;
			ksegment[seg].prot = usegment[seg].prot;
		}

		kfree(usegment);
		kreserve.seg_list = ksegment;

		if (client == NULL) {
			/* Create the client and add the segment */
			client = agp_create_client(kreserve.pid);

			if (client == NULL) {
				kfree(ksegment);
				return -ENOMEM;
			}
			client_priv = agp_find_private(kreserve.pid);

			if (client_priv != NULL) {
				set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
				set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
			}
		}
		return agp_create_segment(client, &kreserve);
	}
	/* Will never really happen */
	return -EINVAL;
}
static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
{
	struct agp_region reserve;
	struct agp_client *client;
	struct agp_file_private *client_priv;

	DBG("");
	if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))
		return -EFAULT;

	if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
		return -EFAULT;

	client = agp_find_client_by_pid(reserve.pid);

	if (reserve.seg_count == 0) {
		/* remove a client */
		client_priv = agp_find_private(reserve.pid);

		if (client_priv != NULL) {
			set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
			set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
		}
		if (client == NULL) {
			/* client is already removed */
			return 0;
		}
		return agp_remove_client(reserve.pid);
	} else {
		struct agp_segment *segment;

		if (reserve.seg_count >= 16384)
			return -EINVAL;

		segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count),
				  GFP_KERNEL);

		if (segment == NULL)
			return -ENOMEM;

		if (copy_from_user(segment, (void __user *) reserve.seg_list,
				   sizeof(struct agp_segment) * reserve.seg_count)) {
			kfree(segment);
			return -EFAULT;
		}
		reserve.seg_list = segment;

		if (client == NULL) {
			/* Create the client and add the segment */
			client = agp_create_client(reserve.pid);

			if (client == NULL) {
				kfree(segment);
				return -ENOMEM;
			}
			client_priv = agp_find_private(reserve.pid);

			if (client_priv != NULL) {
				set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
				set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
			}
		}
		return agp_create_segment(client, &reserve);
	}
	/* Will never really happen */
	return -EINVAL;
}