Commit 11ae5eb5 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'topic/vmemdup-user-array-2023-10-24-1' of...

Merge tag 'topic/vmemdup-user-array-2023-10-24-1' of git://anongit.freedesktop.org/drm/drm into drm-next

vmemdup-user-array API and changes with it.

This is just a process PR to merge the topic branch into drm-next, this contains some core kernel and drm changes.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Dave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231024010905.646830-1-airlied@redhat.com
parents 3f5ba636 06ab64a0
......@@ -510,8 +510,8 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
/* Handle leased objects, if any */
idr_init(&leases);
if (object_count != 0) {
object_ids = memdup_user(u64_to_user_ptr(cl->object_ids),
array_size(object_count, sizeof(__u32)));
object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
object_count, sizeof(__u32));
if (IS_ERR(object_ids)) {
ret = PTR_ERR(object_ids);
idr_destroy(&leases);
......
......@@ -774,9 +774,9 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
sizeof(metadata->mip_levels));
metadata->num_sizes = num_sizes;
metadata->sizes =
memdup_user((struct drm_vmw_size __user *)(unsigned long)
memdup_array_user((struct drm_vmw_size __user *)(unsigned long)
req->size_addr,
sizeof(*metadata->sizes) * metadata->num_sizes);
metadata->num_sizes, sizeof(*metadata->sizes));
if (IS_ERR(metadata->sizes)) {
ret = PTR_ERR(metadata->sizes);
goto out_no_sizes;
......
......@@ -5,7 +5,9 @@
#include <linux/compiler.h> /* for inline */
#include <linux/types.h> /* for size_t */
#include <linux/stddef.h> /* for NULL */
#include <linux/err.h> /* for ERR_PTR() */
#include <linux/errno.h> /* for E2BIG */
#include <linux/overflow.h> /* for check_mul_overflow() */
#include <linux/stdarg.h>
#include <uapi/linux/string.h>
......@@ -14,6 +16,44 @@ extern void *memdup_user(const void __user *, size_t);
extern void *vmemdup_user(const void __user *, size_t);
extern void *memdup_user_nul(const void __user *, size_t);
/**
* memdup_array_user - duplicate array from user space
* @src: source address in user space
* @n: number of array members to copy
* @size: size of one array member
*
* Return: an ERR_PTR() on failure. Result is physically
* contiguous, to be freed by kfree().
*/
static inline void *memdup_array_user(const void __user *src, size_t n, size_t size)
{
size_t nbytes;
if (check_mul_overflow(n, size, &nbytes))
return ERR_PTR(-EOVERFLOW);
return memdup_user(src, nbytes);
}
/**
* vmemdup_array_user - duplicate array from user space
* @src: source address in user space
* @n: number of array members to copy
* @size: size of one array member
*
* Return: an ERR_PTR() on failure. Result may be not
* physically contiguous. Use kvfree() to free.
*/
static inline void *vmemdup_array_user(const void __user *src, size_t n, size_t size)
{
size_t nbytes;
if (check_mul_overflow(n, size, &nbytes))
return ERR_PTR(-EOVERFLOW);
return vmemdup_user(src, nbytes);
}
/*
* Include machine specific inline routines
*/
......
......@@ -247,7 +247,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
((flags & KEXEC_ARCH_MASK) != KEXEC_ARCH_DEFAULT))
return -EINVAL;
ksegments = memdup_user(segments, nr_segments * sizeof(ksegments[0]));
ksegments = memdup_array_user(segments, nr_segments, sizeof(ksegments[0]));
if (IS_ERR(ksegments))
return PTR_ERR(ksegments);
......
......@@ -331,7 +331,7 @@ long watch_queue_set_filter(struct pipe_inode_info *pipe,
filter.__reserved != 0)
return -EINVAL;
tf = memdup_user(_filter->filters, filter.nr_filters * sizeof(*tf));
tf = memdup_array_user(_filter->filters, filter.nr_filters, sizeof(*tf));
if (IS_ERR(tf))
return PTR_ERR(tf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment