Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2cffa22 authored by Al Viro's avatar Al Viro
Browse files

Merge branch 'work.drm' into work.__copy_in_user

parents 8d1a81a8 aeba0390
Loading
Loading
Loading
Loading
+65 −51
Original line number Diff line number Diff line
@@ -1258,11 +1258,11 @@ int drm_legacy_addbufs(struct drm_device *dev, void *data,
 * lock, preventing of allocating more buffers after this call. Information
 * about each requested buffer is then copied into user space.
 */
int drm_legacy_infobufs(struct drm_device *dev, void *data,
			struct drm_file *file_priv)
int __drm_legacy_infobufs(struct drm_device *dev,
			void *data, int *p,
			int (*f)(void *, int, struct drm_buf_entry *))
{
	struct drm_device_dma *dma = dev->dma;
	struct drm_buf_info *request = data;
	int i;
	int count;

@@ -1290,26 +1290,12 @@ int drm_legacy_infobufs(struct drm_device *dev, void *data,

	DRM_DEBUG("count = %d\n", count);

	if (request->count >= count) {
	if (*p >= count) {
		for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
			if (dma->bufs[i].buf_count) {
				struct drm_buf_desc __user *to =
				    &request->list[count];
			struct drm_buf_entry *from = &dma->bufs[i];
				if (copy_to_user(&to->count,
						 &from->buf_count,
						 sizeof(from->buf_count)) ||
				    copy_to_user(&to->size,
						 &from->buf_size,
						 sizeof(from->buf_size)) ||
				    copy_to_user(&to->low_mark,
						 &from->low_mark,
						 sizeof(from->low_mark)) ||
				    copy_to_user(&to->high_mark,
						 &from->high_mark,
						 sizeof(from->high_mark)))
			if (from->buf_count) {
				if (f(data, count, from) < 0)
					return -EFAULT;

				DRM_DEBUG("%d %d %d %d %d\n",
					  i,
					  dma->bufs[i].buf_count,
@@ -1320,11 +1306,29 @@ int drm_legacy_infobufs(struct drm_device *dev, void *data,
			}
		}
	}
	request->count = count;
	*p = count;

	return 0;
}

static int copy_one_buf(void *data, int count, struct drm_buf_entry *from)
{
	struct drm_buf_info *request = data;
	struct drm_buf_desc __user *to = &request->list[count];
	struct drm_buf_desc v = {.count = from->buf_count,
				 .size = from->buf_size,
				 .low_mark = from->low_mark,
				 .high_mark = from->high_mark};
	return copy_to_user(to, &v, offsetof(struct drm_buf_desc, flags));
}

int drm_legacy_infobufs(struct drm_device *dev, void *data,
			struct drm_file *file_priv)
{
	struct drm_buf_info *request = data;
	return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf);
}

/**
 * Specifies a low and high water mark for buffer allocation
 *
@@ -1439,15 +1443,15 @@ int drm_legacy_freebufs(struct drm_device *dev, void *data,
 * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
 * drm_mmap_dma().
 */
int drm_legacy_mapbufs(struct drm_device *dev, void *data,
int __drm_legacy_mapbufs(struct drm_device *dev, void *data, int *p,
			 void __user **v,
			 int (*f)(void *, int, unsigned long,
				  struct drm_buf *),
		         struct drm_file *file_priv)
{
	struct drm_device_dma *dma = dev->dma;
	int retcode = 0;
	const int zero = 0;
	unsigned long virtual;
	unsigned long address;
	struct drm_buf_map *request = data;
	int i;

	if (!drm_core_check_feature(dev, DRIVER_LEGACY))
@@ -1467,7 +1471,7 @@ int drm_legacy_mapbufs(struct drm_device *dev, void *data,
	dev->buf_use++;		/* Can't allocate more after this call */
	spin_unlock(&dev->buf_lock);

	if (request->count >= dma->buf_count) {
	if (*p >= dma->buf_count) {
		if ((dev->agp && (dma->flags & _DRM_DMA_USE_AGP))
		    || (drm_core_check_feature(dev, DRIVER_SG)
			&& (dma->flags & _DRM_DMA_USE_SG))) {
@@ -1492,41 +1496,51 @@ int drm_legacy_mapbufs(struct drm_device *dev, void *data,
			retcode = (signed long)virtual;
			goto done;
		}
		request->virtual = (void __user *)virtual;
		*v = (void __user *)virtual;

		for (i = 0; i < dma->buf_count; i++) {
			if (copy_to_user(&request->list[i].idx,
					 &dma->buflist[i]->idx,
					 sizeof(request->list[0].idx))) {
				retcode = -EFAULT;
				goto done;
			}
			if (copy_to_user(&request->list[i].total,
					 &dma->buflist[i]->total,
					 sizeof(request->list[0].total))) {
				retcode = -EFAULT;
				goto done;
			}
			if (copy_to_user(&request->list[i].used,
					 &zero, sizeof(zero))) {
				retcode = -EFAULT;
				goto done;
			}
			address = virtual + dma->buflist[i]->offset;	/* *** */
			if (copy_to_user(&request->list[i].address,
					 &address, sizeof(address))) {
			if (f(data, i, virtual, dma->buflist[i]) < 0) {
				retcode = -EFAULT;
				goto done;
			}
		}
	}
      done:
	request->count = dma->buf_count;
	DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode);
	*p = dma->buf_count;
	DRM_DEBUG("%d buffers, retcode = %d\n", *p, retcode);

	return retcode;
}

static int map_one_buf(void *data, int idx, unsigned long virtual,
			struct drm_buf *buf)
{
	struct drm_buf_map *request = data;
	unsigned long address = virtual + buf->offset;	/* *** */

	if (copy_to_user(&request->list[idx].idx, &buf->idx,
			 sizeof(request->list[0].idx)))
		return -EFAULT;
	if (copy_to_user(&request->list[idx].total, &buf->total,
			 sizeof(request->list[0].total)))
		return -EFAULT;
	if (clear_user(&request->list[idx].used, sizeof(int)))
		return -EFAULT;
	if (copy_to_user(&request->list[idx].address, &address,
			 sizeof(address)))
		return -EFAULT;
	return 0;
}

int drm_legacy_mapbufs(struct drm_device *dev, void *data,
		       struct drm_file *file_priv)
{
	struct drm_buf_map *request = data;
	return __drm_legacy_mapbufs(dev, data, &request->count,
				    &request->virtual, map_one_buf,
				    file_priv);
}

int drm_legacy_dma_ioctl(struct drm_device *dev, void *data,
		  struct drm_file *file_priv)
{
+3 −0
Original line number Diff line number Diff line
@@ -143,3 +143,6 @@ static inline int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc)
	return 0;
}
#endif
drm_ioctl_t drm_version;
drm_ioctl_t drm_getunique;
drm_ioctl_t drm_getclient;
+290 −460

File changed.

Preview size limit exceeded, changes collapsed.

+31 −17
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@
 *
 * Copies the bus id from drm_device::unique into user space.
 */
static int drm_getunique(struct drm_device *dev, void *data,
int drm_getunique(struct drm_device *dev, void *data,
		  struct drm_file *file_priv)
{
	struct drm_unique *u = data;
@@ -172,7 +172,7 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
 * Searches for the client with the specified index and copies its information
 * into userspace
 */
static int drm_getclient(struct drm_device *dev, void *data,
int drm_getclient(struct drm_device *dev, void *data,
		  struct drm_file *file_priv)
{
	struct drm_client *client = data;
@@ -461,7 +461,7 @@ static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
 *
 * Fills in the version information in \p arg.
 */
static int drm_version(struct drm_device *dev, void *data,
int drm_version(struct drm_device *dev, void *data,
		       struct drm_file *file_priv)
{
	struct drm_version *version = data;
@@ -694,6 +694,33 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 * structure.
 */

long drm_ioctl_kernel(struct file *file, drm_ioctl_t *func, void *kdata,
		      u32 flags)
{
	struct drm_file *file_priv = file->private_data;
	struct drm_device *dev = file_priv->minor->dev;
	int retcode;

	if (drm_device_is_unplugged(dev))
		return -ENODEV;

	retcode = drm_ioctl_permit(flags, file_priv);
	if (unlikely(retcode))
		return retcode;

	/* Enforce sane locking for modern driver ioctls. */
	if (!drm_core_check_feature(dev, DRIVER_LEGACY) ||
	    (flags & DRM_UNLOCKED))
		retcode = func(dev, kdata, file_priv);
	else {
		mutex_lock(&drm_global_mutex);
		retcode = func(dev, kdata, file_priv);
		mutex_unlock(&drm_global_mutex);
	}
	return retcode;
}
EXPORT_SYMBOL(drm_ioctl_kernel);

/**
 * drm_ioctl - ioctl callback implementation for DRM drivers
 * @filp: file this ioctl is called on
@@ -762,10 +789,6 @@ long drm_ioctl(struct file *filp,
		goto err_i1;
	}

	retcode = drm_ioctl_permit(ioctl->flags, file_priv);
	if (unlikely(retcode))
		goto err_i1;

	if (ksize <= sizeof(stack_kdata)) {
		kdata = stack_kdata;
	} else {
@@ -784,16 +807,7 @@ long drm_ioctl(struct file *filp,
	if (ksize > in_size)
		memset(kdata + in_size, 0, ksize - in_size);

	/* Enforce sane locking for modern driver ioctls. */
	if (!drm_core_check_feature(dev, DRIVER_LEGACY) ||
	    (ioctl->flags & DRM_UNLOCKED))
		retcode = func(dev, kdata, file_priv);
	else {
		mutex_lock(&drm_global_mutex);
		retcode = func(dev, kdata, file_priv);
		mutex_unlock(&drm_global_mutex);
	}

	retcode = drm_ioctl_kernel(filp, func, kdata, ioctl->flags);
	if (copy_to_user((void __user *)arg, kdata, out_size) != 0)
		retcode = -EFAULT;

+7 −0
Original line number Diff line number Diff line
@@ -74,6 +74,13 @@ int drm_legacy_freebufs(struct drm_device *d, void *v, struct drm_file *f);
int drm_legacy_mapbufs(struct drm_device *d, void *v, struct drm_file *f);
int drm_legacy_dma_ioctl(struct drm_device *d, void *v, struct drm_file *f);

int __drm_legacy_infobufs(struct drm_device *, void *, int *,
			  int (*)(void *, int, struct drm_buf_entry *));
int __drm_legacy_mapbufs(struct drm_device *, void *, int *,
			  void __user **,
			  int (*)(void *, int, unsigned long, struct drm_buf *),
			  struct drm_file *);

#ifdef CONFIG_DRM_VM
void drm_legacy_vma_flush(struct drm_device *d);
#else
Loading