linux-hardening.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/5] Introduce new wrappers to copy user-arrays
@ 2023-09-20 12:36 Philipp Stanner
  2023-09-20 12:36 ` [PATCH v3 1/5] string.h: add array-wrappers for (v)memdup_user() Philipp Stanner
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Philipp Stanner @ 2023-09-20 12:36 UTC (permalink / raw)
  To: Kees Cook, Andy Shevchenko, Eric Biederman, Christian Brauner,
	David Disseldorp, Luis Chamberlain, Siddh Raman Pant, Nick Alcock,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Daniel Vetter, Zack Rusin
  Cc: VMware Graphics Reviewers, dri-devel, linux-kernel, kexec,
	linux-hardening, Philipp Stanner

Hi!

David Airlie suggested that we could implement new wrappers around
(v)memdup_user() for duplicating user arrays.

This small patch series first implements the two new wrapper functions
memdup_array_user() and vmemdup_array_user(). They calculate the
array-sizes safely, i.e., they return an error in case of an overflow.

It then implements the new wrappers in two components in kernel/ and two
in the drm-subsystem.

In total, there are 18 files in the kernel that use (v)memdup_user() to
duplicate arrays. My plan is to provide patches for the other 14
successively once this series has been merged.


Changes since v2:
- Remove the unlikely() from the overflow-check, since the latter
  already implements one (Dan Carpenter)
- Add the Reviewd-bys for the changes already reviewed in v2

Changes since v1:
- Insert new headers alphabetically ordered
- Remove empty lines in functions' docstrings
- Return -EOVERFLOW instead of -EINVAL from wrapper functions

P.

Philipp Stanner (5):
  string.h: add array-wrappers for (v)memdup_user()
  kernel: kexec: copy user-array safely
  kernel: watch_queue: copy user-array safely
  drm_lease.c: copy user-array safely
  drm: vmgfx_surface.c: copy user-array safely

 drivers/gpu/drm/drm_lease.c             |  4 +--
 drivers/gpu/drm/vmwgfx/vmwgfx_surface.c |  4 +--
 include/linux/string.h                  | 40 +++++++++++++++++++++++++
 kernel/kexec.c                          |  2 +-
 kernel/watch_queue.c                    |  2 +-
 5 files changed, 46 insertions(+), 6 deletions(-)

-- 
2.41.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v3 1/5] string.h: add array-wrappers for (v)memdup_user()
  2023-09-20 12:36 [PATCH v3 0/5] Introduce new wrappers to copy user-arrays Philipp Stanner
@ 2023-09-20 12:36 ` Philipp Stanner
  2023-09-20 12:36 ` [PATCH v3 2/5] kernel: kexec: copy user-array safely Philipp Stanner
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Philipp Stanner @ 2023-09-20 12:36 UTC (permalink / raw)
  To: Kees Cook, Andy Shevchenko, Eric Biederman, Christian Brauner,
	David Disseldorp, Luis Chamberlain, Siddh Raman Pant, Nick Alcock,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Daniel Vetter, Zack Rusin
  Cc: VMware Graphics Reviewers, dri-devel, linux-kernel, kexec,
	linux-hardening, Philipp Stanner, David Airlie, Andy Shevchenko

Currently, user array duplications are sometimes done without an
overflow check. Sometimes the checks are done manually; sometimes the
array size is calculated with array_size() and sometimes by calculating
n * size directly in code.

Introduce wrappers for arrays for memdup_user() and vmemdup_user() to
provide a standardized and safe way for duplicating user arrays.

This is both for new code as well as replacing usage of (v)memdup_user()
in existing code that uses, e.g., n * size to calculate array sizes.

Suggested-by: David Airlie <airlied@redhat.com>
Signed-off-by: Philipp Stanner <pstanner@redhat.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Zack Rusin <zackr@vmware.com>
---
 include/linux/string.h | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/include/linux/string.h b/include/linux/string.h
index dbfc66400050..debf4ef1098f 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -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
  */
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v3 2/5] kernel: kexec: copy user-array safely
  2023-09-20 12:36 [PATCH v3 0/5] Introduce new wrappers to copy user-arrays Philipp Stanner
  2023-09-20 12:36 ` [PATCH v3 1/5] string.h: add array-wrappers for (v)memdup_user() Philipp Stanner
@ 2023-09-20 12:36 ` Philipp Stanner
  2023-09-20 12:36 ` [PATCH v3 3/5] kernel: watch_queue: " Philipp Stanner
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Philipp Stanner @ 2023-09-20 12:36 UTC (permalink / raw)
  To: Kees Cook, Andy Shevchenko, Eric Biederman, Christian Brauner,
	David Disseldorp, Luis Chamberlain, Siddh Raman Pant, Nick Alcock,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Daniel Vetter, Zack Rusin
  Cc: VMware Graphics Reviewers, dri-devel, linux-kernel, kexec,
	linux-hardening, Philipp Stanner, David Airlie, Baoquan He

Currently, there is no overflow-check with memdup_user().

Use the new function memdup_array_user() instead of memdup_user() for
duplicating the user-space array safely.

Suggested-by: David Airlie <airlied@redhat.com>
Signed-off-by: Philipp Stanner <pstanner@redhat.com>
Acked-by: Baoquan He <bhe@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Zack Rusin <zackr@vmware.com>
---
 kernel/kexec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/kexec.c b/kernel/kexec.c
index 107f355eac10..8f35a5a42af8 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -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);
 
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v3 3/5] kernel: watch_queue: copy user-array safely
  2023-09-20 12:36 [PATCH v3 0/5] Introduce new wrappers to copy user-arrays Philipp Stanner
  2023-09-20 12:36 ` [PATCH v3 1/5] string.h: add array-wrappers for (v)memdup_user() Philipp Stanner
  2023-09-20 12:36 ` [PATCH v3 2/5] kernel: kexec: copy user-array safely Philipp Stanner
@ 2023-09-20 12:36 ` Philipp Stanner
  2023-09-20 12:36 ` [PATCH v3 4/5] drm_lease.c: " Philipp Stanner
  2023-09-20 12:36 ` [PATCH v3 5/5] drm: vmgfx_surface.c: " Philipp Stanner
  4 siblings, 0 replies; 6+ messages in thread
From: Philipp Stanner @ 2023-09-20 12:36 UTC (permalink / raw)
  To: Kees Cook, Andy Shevchenko, Eric Biederman, Christian Brauner,
	David Disseldorp, Luis Chamberlain, Siddh Raman Pant, Nick Alcock,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Daniel Vetter, Zack Rusin
  Cc: VMware Graphics Reviewers, dri-devel, linux-kernel, kexec,
	linux-hardening, Philipp Stanner, David Airlie

Currently, there is no overflow-check with memdup_user().

Use the new function memdup_array_user() instead of memdup_user() for
duplicating the user-space array safely.

Suggested-by: David Airlie <airlied@redhat.com>
Signed-off-by: Philipp Stanner <pstanner@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Zack Rusin <zackr@vmware.com>
---
 kernel/watch_queue.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/watch_queue.c b/kernel/watch_queue.c
index d0b6b390ee42..778b4056700f 100644
--- a/kernel/watch_queue.c
+++ b/kernel/watch_queue.c
@@ -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);
 
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v3 4/5] drm_lease.c: copy user-array safely
  2023-09-20 12:36 [PATCH v3 0/5] Introduce new wrappers to copy user-arrays Philipp Stanner
                   ` (2 preceding siblings ...)
  2023-09-20 12:36 ` [PATCH v3 3/5] kernel: watch_queue: " Philipp Stanner
@ 2023-09-20 12:36 ` Philipp Stanner
  2023-09-20 12:36 ` [PATCH v3 5/5] drm: vmgfx_surface.c: " Philipp Stanner
  4 siblings, 0 replies; 6+ messages in thread
From: Philipp Stanner @ 2023-09-20 12:36 UTC (permalink / raw)
  To: Kees Cook, Andy Shevchenko, Eric Biederman, Christian Brauner,
	David Disseldorp, Luis Chamberlain, Siddh Raman Pant, Nick Alcock,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Daniel Vetter, Zack Rusin
  Cc: VMware Graphics Reviewers, dri-devel, linux-kernel, kexec,
	linux-hardening, Philipp Stanner, David Airlie

Currently, there is no overflow-check with memdup_user().

Use the new function memdup_array_user() instead of memdup_user() for
duplicating the user-space array safely.

Suggested-by: David Airlie <airlied@redhat.com>
Signed-off-by: Philipp Stanner <pstanner@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Zack Rusin <zackr@vmware.com>
---
 drivers/gpu/drm/drm_lease.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index 150fe1555068..94375c6a5425 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -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);
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v3 5/5] drm: vmgfx_surface.c: copy user-array safely
  2023-09-20 12:36 [PATCH v3 0/5] Introduce new wrappers to copy user-arrays Philipp Stanner
                   ` (3 preceding siblings ...)
  2023-09-20 12:36 ` [PATCH v3 4/5] drm_lease.c: " Philipp Stanner
@ 2023-09-20 12:36 ` Philipp Stanner
  4 siblings, 0 replies; 6+ messages in thread
From: Philipp Stanner @ 2023-09-20 12:36 UTC (permalink / raw)
  To: Kees Cook, Andy Shevchenko, Eric Biederman, Christian Brauner,
	David Disseldorp, Luis Chamberlain, Siddh Raman Pant, Nick Alcock,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Daniel Vetter, Zack Rusin
  Cc: VMware Graphics Reviewers, dri-devel, linux-kernel, kexec,
	linux-hardening, Philipp Stanner, David Airlie

Currently, there is no overflow-check with memdup_user().

Use the new function memdup_array_user() instead of memdup_user() for
duplicating the user-space array safely.

Suggested-by: David Airlie <airlied@redhat.com>
Signed-off-by: Philipp Stanner <pstanner@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Zack Rusin <zackr@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index 5db403ee8261..9be185b094cb 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -777,9 +777,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;
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-09-20 12:38 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-20 12:36 [PATCH v3 0/5] Introduce new wrappers to copy user-arrays Philipp Stanner
2023-09-20 12:36 ` [PATCH v3 1/5] string.h: add array-wrappers for (v)memdup_user() Philipp Stanner
2023-09-20 12:36 ` [PATCH v3 2/5] kernel: kexec: copy user-array safely Philipp Stanner
2023-09-20 12:36 ` [PATCH v3 3/5] kernel: watch_queue: " Philipp Stanner
2023-09-20 12:36 ` [PATCH v3 4/5] drm_lease.c: " Philipp Stanner
2023-09-20 12:36 ` [PATCH v3 5/5] drm: vmgfx_surface.c: " Philipp Stanner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).