Skip to content

Commit

Permalink
Merge tag 'topic/vmemdup-user-array-2023-10-24-1' of git://anongit.fr…
Browse files Browse the repository at this point in the history
…eedesktop.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: Dave Airlie <airlied@redhat.com>

From: Dave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231024010905.646830-1-airlied@redhat.com
  • Loading branch information
Dave Airlie committed Oct 24, 2023
2 parents 3f5ba63 + 06ab64a commit 11ae5eb
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 6 deletions.
4 changes: 2 additions & 2 deletions drivers/gpu/drm/drm_lease.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
40 changes: 40 additions & 0 deletions include/linux/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand All @@ -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
*/
Expand Down
2 changes: 1 addition & 1 deletion kernel/kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion kernel/watch_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit 11ae5eb

Please sign in to comment.