public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] uaccess/sockptr: copy_struct_ fixes and more helpers
@ 2026-04-07 16:03 Stefan Metzmacher
  2026-04-07 16:03 ` [PATCH 1/5] uaccess: fix ignored_trailing logic in copy_struct_to_user() Stefan Metzmacher
                   ` (5 more replies)
  0 siblings, 6 replies; 13+ messages in thread
From: Stefan Metzmacher @ 2026-04-07 16:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: metze, Dmitry Safonov, Dmitry Safonov, Francesco Ruggeri,
	Salam Noureddine, David Ahern, David S . Miller, Michal Luczaj,
	David Wei, Luiz Augusto von Dentz, Luiz Augusto von Dentz,
	Marcel Holtmann, Xin Long, Eric Dumazet, Kuniyuki Iwashima,
	Paolo Abeni, Willem de Bruijn, Neal Cardwell, Jakub Kicinski,
	Simon Horman, Aleksa Sarai, Christian Brauner, Kees Cook, netdev,
	linux-bluetooth

Hi,

here are some patches related to
copy_struct_{from,to}_{user,sockptr}()
I collected during my work on an IPPROTO_SMBDIRECT
implementation wrapping the smbdirect code used
by cifs.ko and ksmbd.ko.

The first patch fixes copy_struct_to_user()
to behave like documented.

The 2nd patch fixes the case where
copy_struct_from_user() is called by
copy_struct_from_sockptr().

The 3rd patch introduces
copy_struct_{from,to}_bounce_buffer()
as a result of a discussion about the
IPPROTO_QUIC driver in order to
be future prove when handling msg_control
messages in sendmsg and recvmsg.
But I'll likely also use them in my
IPPROTO_SMBDIRECT driver.

The 4th patch makes copy_struct_from_sockptr()
a trivial wrapper switching between
copy_struct_from_user() and
copy_struct_from_bounce_buffer()

The 5th patch introduces copy_struct_to_sockptr()
which I'll also use in my IPPROTO_SMBDIRECT driver.

As future cleanup I was thinking about trick
to hide size_t ksize from the callers, similar
to what was done with kmalloc_obj(). Whould
others think that would be useful?

Stefan Metzmacher (5):
  uaccess: fix ignored_trailing logic in copy_struct_to_user()
  sockptr: fix usize check in copy_struct_from_sockptr() for user
    pointers
  uaccess: add copy_struct_{from,to}_bounce_buffer() helpers
  sockptr: let copy_struct_from_sockptr() use
    copy_struct_from_bounce_buffer()
  sockptr: introduce copy_struct_to_sockptr()

 include/linux/sockptr.h | 28 ++++++++----------
 include/linux/uaccess.h | 65 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 76 insertions(+), 17 deletions(-)

-- 
2.43.0


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

* [PATCH 1/5] uaccess: fix ignored_trailing logic in copy_struct_to_user()
  2026-04-07 16:03 [PATCH 0/5] uaccess/sockptr: copy_struct_ fixes and more helpers Stefan Metzmacher
@ 2026-04-07 16:03 ` Stefan Metzmacher
  2026-04-09  6:33   ` Aleksa Sarai
  2026-04-07 16:03 ` [PATCH 2/5] sockptr: fix usize check in copy_struct_from_sockptr() for user pointers Stefan Metzmacher
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Stefan Metzmacher @ 2026-04-07 16:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: metze, Dmitry Safonov, Dmitry Safonov, Francesco Ruggeri,
	Salam Noureddine, David Ahern, David S . Miller, Michal Luczaj,
	David Wei, Luiz Augusto von Dentz, Luiz Augusto von Dentz,
	Marcel Holtmann, Xin Long, Eric Dumazet, Kuniyuki Iwashima,
	Paolo Abeni, Willem de Bruijn, Neal Cardwell, Jakub Kicinski,
	Simon Horman, Aleksa Sarai, Christian Brauner, Kees Cook, netdev,
	linux-bluetooth

Currently all callers pass ignored_trailing=NULL, but I have
code that will make use of.

Now it actually behaves like documented:

* If @usize < @ksize, then the kernel is trying to pass userspace a newer
  struct than it supports. Thus we only copy the interoperable portions
  (@usize) and ignore the rest (but @ignored_trailing is set to %true if
  any of the trailing (@ksize - @usize) bytes are non-zero).

Fixes: 424a55a4a908 ("uaccess: add copy_struct_to_user helper")
Cc: Dmitry Safonov <0x7f454c46@gmail.com>
Cc: Dmitry Safonov <dima@arista.com>
Cc: Francesco Ruggeri <fruggeri@arista.com>
Cc: Salam Noureddine <noureddine@arista.com>
Cc: David Ahern <dsahern@kernel.org>
Cc: David S. Miller <davem@davemloft.net>
Cc: Michal Luczaj <mhal@rbox.co>
Cc: David Wei <dw@davidwei.uk>
Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Cc: Marcel Holtmann <marcel@holtmann.org>
Cc: Xin Long <lucien.xin@gmail.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Willem de Bruijn <willemb@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Simon Horman <horms@kernel.org>
Cc: Aleksa Sarai <cyphar@cyphar.com>
Cc: Christian Brauner <brauner@kernel.org>
CC: Kees Cook <keescook@chromium.org>
Cc: netdev@vger.kernel.org
Cc: linux-bluetooth@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 include/linux/uaccess.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 4fe63169d5a2..1234b5fa4761 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -505,7 +505,7 @@ copy_struct_to_user(void __user *dst, size_t usize, const void *src,
 			return -EFAULT;
 	}
 	if (ignored_trailing)
-		*ignored_trailing = ksize < usize &&
+		*ignored_trailing = usize < ksize &&
 			memchr_inv(src + size, 0, rest) != NULL;
 	/* Copy the interoperable parts of the struct. */
 	if (copy_to_user(dst, src, size))
-- 
2.43.0


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

* [PATCH 2/5] sockptr: fix usize check in copy_struct_from_sockptr() for user pointers
  2026-04-07 16:03 [PATCH 0/5] uaccess/sockptr: copy_struct_ fixes and more helpers Stefan Metzmacher
  2026-04-07 16:03 ` [PATCH 1/5] uaccess: fix ignored_trailing logic in copy_struct_to_user() Stefan Metzmacher
@ 2026-04-07 16:03 ` Stefan Metzmacher
  2026-04-09  6:37   ` Aleksa Sarai
  2026-04-07 16:03 ` [PATCH 3/5] uaccess: add copy_struct_{from,to}_bounce_buffer() helpers Stefan Metzmacher
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Stefan Metzmacher @ 2026-04-07 16:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: metze, Dmitry Safonov, Dmitry Safonov, Francesco Ruggeri,
	Salam Noureddine, David Ahern, David S . Miller, Michal Luczaj,
	David Wei, Luiz Augusto von Dentz, Luiz Augusto von Dentz,
	Marcel Holtmann, Xin Long, Eric Dumazet, Kuniyuki Iwashima,
	Paolo Abeni, Willem de Bruijn, Neal Cardwell, Jakub Kicinski,
	Simon Horman, Aleksa Sarai, Christian Brauner, Kees Cook, netdev,
	linux-bluetooth

copy_struct_from_user will never hit the check_zeroed_user() call
and will never return -E2BIG if new userspace passed new bits in a
larger structure than the current kernel structure.

As far as I can there are no critical/related uapi changes in

- include/net/bluetooth/bluetooth.h and net/bluetooth/sco.c
  after the use of copy_struct_from_sockptr in v6.13-rc3
- include/uapi/linux/tcp.h and net/ipv4/tcp_ao.c
  after the use of copy_struct_from_sockptr in v6.6-rc1

So that new callers will get the correct behavior from the start.

Fixes: 4954f17ddefc ("net/tcp: Introduce TCP_AO setsockopt()s")
Fixes: ef84703a911f ("net/tcp: Add TCP-AO getsockopt()s")
Fixes: faadfaba5e01 ("net/tcp: Add TCP_AO_REPAIR")
Fixes: 3e643e4efa1e ("Bluetooth: Improve setsockopt() handling of malformed user input")
Cc: Dmitry Safonov <0x7f454c46@gmail.com>
Cc: Dmitry Safonov <dima@arista.com>
Cc: Francesco Ruggeri <fruggeri@arista.com>
Cc: Salam Noureddine <noureddine@arista.com>
Cc: David Ahern <dsahern@kernel.org>
Cc: David S. Miller <davem@davemloft.net>
Cc: Michal Luczaj <mhal@rbox.co>
Cc: David Wei <dw@davidwei.uk>
Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Cc: Marcel Holtmann <marcel@holtmann.org>
Cc: Xin Long <lucien.xin@gmail.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Willem de Bruijn <willemb@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Simon Horman <horms@kernel.org>
Cc: Aleksa Sarai <cyphar@cyphar.com>
Cc: Christian Brauner <brauner@kernel.org>
CC: Kees Cook <keescook@chromium.org>
Cc: netdev@vger.kernel.org
Cc: linux-bluetooth@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 include/linux/sockptr.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/sockptr.h b/include/linux/sockptr.h
index 3e6c8e9d67ae..ba88f4d78c1b 100644
--- a/include/linux/sockptr.h
+++ b/include/linux/sockptr.h
@@ -91,7 +91,7 @@ static inline int copy_struct_from_sockptr(void *dst, size_t ksize,
 	size_t rest = max(ksize, usize) - size;
 
 	if (!sockptr_is_kernel(src))
-		return copy_struct_from_user(dst, ksize, src.user, size);
+		return copy_struct_from_user(dst, ksize, src.user, usize);
 
 	if (usize < ksize) {
 		memset(dst + size, 0, rest);
-- 
2.43.0


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

* [PATCH 3/5] uaccess: add copy_struct_{from,to}_bounce_buffer() helpers
  2026-04-07 16:03 [PATCH 0/5] uaccess/sockptr: copy_struct_ fixes and more helpers Stefan Metzmacher
  2026-04-07 16:03 ` [PATCH 1/5] uaccess: fix ignored_trailing logic in copy_struct_to_user() Stefan Metzmacher
  2026-04-07 16:03 ` [PATCH 2/5] sockptr: fix usize check in copy_struct_from_sockptr() for user pointers Stefan Metzmacher
@ 2026-04-07 16:03 ` Stefan Metzmacher
  2026-04-07 18:25   ` David Laight
  2026-04-07 16:03 ` [PATCH 4/5] sockptr: let copy_struct_from_sockptr() use copy_struct_from_bounce_buffer() Stefan Metzmacher
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Stefan Metzmacher @ 2026-04-07 16:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: metze, Dmitry Safonov, Dmitry Safonov, Francesco Ruggeri,
	Salam Noureddine, David Ahern, David S . Miller, Michal Luczaj,
	David Wei, Luiz Augusto von Dentz, Luiz Augusto von Dentz,
	Marcel Holtmann, Xin Long, Eric Dumazet, Kuniyuki Iwashima,
	Paolo Abeni, Willem de Bruijn, Neal Cardwell, Jakub Kicinski,
	Simon Horman, Aleksa Sarai, Christian Brauner, Kees Cook, netdev,
	linux-bluetooth

These are similar to copy_struct_{from,to}_user() but operate
on kernel buffers instead of user buffers.

They can be used when there is a temporary bounce buffer used,
e.g. in msg_control or similar places.

It allows us to have the same logic to handle old vs. current
and current vs. new structures in the same compatible way.

copy_struct_from_sockptr() will also be able to
use copy_struct_from_bounce_buffer() for the kernel
case as follow us patch.

I'll use this in my IPPROTO_SMBDIRECT work,
but maybe it will also be useful for others...
IPPROTO_QUIC will likely also use it.

Cc: Dmitry Safonov <0x7f454c46@gmail.com>
Cc: Dmitry Safonov <dima@arista.com>
Cc: Francesco Ruggeri <fruggeri@arista.com>
Cc: Salam Noureddine <noureddine@arista.com>
Cc: David Ahern <dsahern@kernel.org>
Cc: David S. Miller <davem@davemloft.net>
Cc: Michal Luczaj <mhal@rbox.co>
Cc: David Wei <dw@davidwei.uk>
Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Cc: Marcel Holtmann <marcel@holtmann.org>
Cc: Xin Long <lucien.xin@gmail.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Willem de Bruijn <willemb@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Simon Horman <horms@kernel.org>
Cc: Aleksa Sarai <cyphar@cyphar.com>
Cc: Christian Brauner <brauner@kernel.org>
CC: Kees Cook <keescook@chromium.org>
Cc: netdev@vger.kernel.org
Cc: linux-bluetooth@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 include/linux/uaccess.h | 63 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 1234b5fa4761..a6cd4f48bb99 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -513,6 +513,69 @@ copy_struct_to_user(void __user *dst, size_t usize, const void *src,
 	return 0;
 }
 
+static __always_inline void
+__copy_struct_generic_bounce_buffer(void *dst, size_t dstsize,
+				    const void *src, size_t srcsize,
+				    bool *ignored_trailing)
+{
+	size_t size = min(dstsize, srcsize);
+	size_t rest = max(dstsize, srcsize) - size;
+
+	/* Deal with trailing bytes. */
+	if (dstsize > srcsize)
+		memset(dst + size, 0, rest);
+	if (ignored_trailing)
+		*ignored_trailing = dstsize < srcsize &&
+			memchr_inv(src + size, 0, rest) != NULL;
+	/* Copy the interoperable parts of the struct. */
+	memcpy(dst, src, size);
+}
+
+/**
+ * This is like copy_struct_from_user(), but the
+ * src buffer was already copied into a kernel
+ * bounce buffer, so it will never return -EFAULT.
+ */
+static __always_inline __must_check int
+copy_struct_from_bounce_buffer(void *dst, size_t dstsize,
+			       const void *src, size_t srcsize)
+{
+	bool ignored_trailing;
+
+	/* Double check if ksize is larger than a known object size. */
+	if (WARN_ON_ONCE(dstsize > __builtin_object_size(dst, 1)))
+		return -E2BIG;
+
+	__copy_struct_generic_bounce_buffer(dst, dstsize,
+					    src, srcsize,
+					    &ignored_trailing);
+	if (unlikely(ignored_trailing))
+		return -E2BIG;
+
+	return 0;
+}
+
+/**
+ * This is like copy_struct_to_user(), but the
+ * dst buffer is a kernel bounce buffer instead
+ * of a direct userspace buffer, so it will never return -EFAULT.
+ */
+static __always_inline __must_check int
+copy_struct_to_bounce_buffer(void *dst, size_t dstsize,
+			     const void *src,
+			     size_t srcsize,
+			     bool *ignored_trailing)
+{
+	/* Double check if srcsize is larger than a known object size. */
+	if (WARN_ON_ONCE(srcsize > __builtin_object_size(src, 1)))
+		return -E2BIG;
+
+	__copy_struct_generic_bounce_buffer(dst, dstsize,
+					    src, srcsize,
+					    ignored_trailing);
+	return 0;
+}
+
 bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size);
 
 long copy_from_kernel_nofault(void *dst, const void *src, size_t size);
-- 
2.43.0


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

* [PATCH 4/5] sockptr: let copy_struct_from_sockptr() use copy_struct_from_bounce_buffer()
  2026-04-07 16:03 [PATCH 0/5] uaccess/sockptr: copy_struct_ fixes and more helpers Stefan Metzmacher
                   ` (2 preceding siblings ...)
  2026-04-07 16:03 ` [PATCH 3/5] uaccess: add copy_struct_{from,to}_bounce_buffer() helpers Stefan Metzmacher
@ 2026-04-07 16:03 ` Stefan Metzmacher
  2026-04-07 16:03 ` [PATCH 5/5] sockptr: introduce copy_struct_to_sockptr() Stefan Metzmacher
  2026-04-09 13:05 ` [PATCH 0/5] uaccess/sockptr: copy_struct_ fixes and more helpers Christian Brauner
  5 siblings, 0 replies; 13+ messages in thread
From: Stefan Metzmacher @ 2026-04-07 16:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: metze, Dmitry Safonov, Dmitry Safonov, Francesco Ruggeri,
	Salam Noureddine, David Ahern, David S . Miller, Michal Luczaj,
	David Wei, Luiz Augusto von Dentz, Luiz Augusto von Dentz,
	Marcel Holtmann, Xin Long, Eric Dumazet, Kuniyuki Iwashima,
	Paolo Abeni, Willem de Bruijn, Neal Cardwell, Jakub Kicinski,
	Simon Horman, Aleksa Sarai, Christian Brauner, Kees Cook, netdev,
	linux-bluetooth

The world would be better without sockptr_t, but this at least
simplifies copy_struct_from_sockptr() to be just a dispatcher for
copy_struct_from_user() or copy_struct_from_bounce_buffer() without any
special logic on its own.

Cc: Dmitry Safonov <0x7f454c46@gmail.com>
Cc: Dmitry Safonov <dima@arista.com>
Cc: Francesco Ruggeri <fruggeri@arista.com>
Cc: Salam Noureddine <noureddine@arista.com>
Cc: David Ahern <dsahern@kernel.org>
Cc: David S. Miller <davem@davemloft.net>
Cc: Michal Luczaj <mhal@rbox.co>
Cc: David Wei <dw@davidwei.uk>
Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Cc: Marcel Holtmann <marcel@holtmann.org>
Cc: Xin Long <lucien.xin@gmail.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Willem de Bruijn <willemb@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Simon Horman <horms@kernel.org>
Cc: Aleksa Sarai <cyphar@cyphar.com>
Cc: Christian Brauner <brauner@kernel.org>
CC: Kees Cook <keescook@chromium.org>
Cc: netdev@vger.kernel.org
Cc: linux-bluetooth@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 include/linux/sockptr.h | 16 +---------------
 1 file changed, 1 insertion(+), 15 deletions(-)

diff --git a/include/linux/sockptr.h b/include/linux/sockptr.h
index ba88f4d78c1b..706a8526cf3c 100644
--- a/include/linux/sockptr.h
+++ b/include/linux/sockptr.h
@@ -87,24 +87,10 @@ static inline int copy_safe_from_sockptr(void *dst, size_t ksize,
 static inline int copy_struct_from_sockptr(void *dst, size_t ksize,
 		sockptr_t src, size_t usize)
 {
-	size_t size = min(ksize, usize);
-	size_t rest = max(ksize, usize) - size;
-
 	if (!sockptr_is_kernel(src))
 		return copy_struct_from_user(dst, ksize, src.user, usize);
 
-	if (usize < ksize) {
-		memset(dst + size, 0, rest);
-	} else if (usize > ksize) {
-		char *p = src.kernel;
-
-		while (rest--) {
-			if (*p++)
-				return -E2BIG;
-		}
-	}
-	memcpy(dst, src.kernel, size);
-	return 0;
+	return copy_struct_from_bounce_buffer(dst, ksize, src.kernel, usize);
 }
 
 static inline int copy_to_sockptr_offset(sockptr_t dst, size_t offset,
-- 
2.43.0


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

* [PATCH 5/5] sockptr: introduce copy_struct_to_sockptr()
  2026-04-07 16:03 [PATCH 0/5] uaccess/sockptr: copy_struct_ fixes and more helpers Stefan Metzmacher
                   ` (3 preceding siblings ...)
  2026-04-07 16:03 ` [PATCH 4/5] sockptr: let copy_struct_from_sockptr() use copy_struct_from_bounce_buffer() Stefan Metzmacher
@ 2026-04-07 16:03 ` Stefan Metzmacher
  2026-04-09 13:05 ` [PATCH 0/5] uaccess/sockptr: copy_struct_ fixes and more helpers Christian Brauner
  5 siblings, 0 replies; 13+ messages in thread
From: Stefan Metzmacher @ 2026-04-07 16:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: metze, Dmitry Safonov, Dmitry Safonov, Francesco Ruggeri,
	Salam Noureddine, David Ahern, David S . Miller, Michal Luczaj,
	David Wei, Luiz Augusto von Dentz, Luiz Augusto von Dentz,
	Marcel Holtmann, Xin Long, Eric Dumazet, Kuniyuki Iwashima,
	Paolo Abeni, Willem de Bruijn, Neal Cardwell, Jakub Kicinski,
	Simon Horman, Aleksa Sarai, Christian Brauner, Kees Cook, netdev,
	linux-bluetooth

We already have copy_struct_from_sockptr() as wrapper to
copy_struct_from_user() or copy_struct_from_bounce_buffer(),
so it's good to have copy_struct_to_sockptr()
as well matching the behavior of copy_struct_to_user()
or copy_struct_to_bounce_buffer().

The world would be better without sockptr_t, but having
copy_struct_to_sockptr() is better than open code it
in various places.

I'll use this in my IPPROTO_SMBDIRECT work,
but maybe it will also be useful for others...
IPPROTO_QUIC will likely also use it.

Cc: Dmitry Safonov <0x7f454c46@gmail.com>
Cc: Dmitry Safonov <dima@arista.com>
Cc: Francesco Ruggeri <fruggeri@arista.com>
Cc: Salam Noureddine <noureddine@arista.com>
Cc: David Ahern <dsahern@kernel.org>
Cc: David S. Miller <davem@davemloft.net>
Cc: Michal Luczaj <mhal@rbox.co>
Cc: David Wei <dw@davidwei.uk>
Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Cc: Marcel Holtmann <marcel@holtmann.org>
Cc: Xin Long <lucien.xin@gmail.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Willem de Bruijn <willemb@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Simon Horman <horms@kernel.org>
Cc: Aleksa Sarai <cyphar@cyphar.com>
Cc: Christian Brauner <brauner@kernel.org>
CC: Kees Cook <keescook@chromium.org>
Cc: netdev@vger.kernel.org
Cc: linux-bluetooth@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 include/linux/sockptr.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/linux/sockptr.h b/include/linux/sockptr.h
index 706a8526cf3c..9c2429c1a570 100644
--- a/include/linux/sockptr.h
+++ b/include/linux/sockptr.h
@@ -107,6 +107,16 @@ static inline int copy_to_sockptr(sockptr_t dst, const void *src, size_t size)
 	return copy_to_sockptr_offset(dst, 0, src, size);
 }
 
+static inline int
+copy_struct_to_sockptr(sockptr_t dst, size_t usize, const void *src,
+		       size_t ksize, bool *ignored_trailing)
+{
+	if (!sockptr_is_kernel(dst))
+		return copy_struct_to_user(dst.user, usize, src, ksize, ignored_trailing);
+
+	return copy_struct_to_bounce_buffer(dst.kernel, usize, src, ksize, ignored_trailing);
+}
+
 static inline void *memdup_sockptr_noprof(sockptr_t src, size_t len)
 {
 	void *p = kmalloc_track_caller_noprof(len, GFP_USER | __GFP_NOWARN);
-- 
2.43.0


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

* Re: [PATCH 3/5] uaccess: add copy_struct_{from,to}_bounce_buffer() helpers
  2026-04-07 16:03 ` [PATCH 3/5] uaccess: add copy_struct_{from,to}_bounce_buffer() helpers Stefan Metzmacher
@ 2026-04-07 18:25   ` David Laight
  2026-04-09  8:47     ` Stefan Metzmacher
  0 siblings, 1 reply; 13+ messages in thread
From: David Laight @ 2026-04-07 18:25 UTC (permalink / raw)
  To: Stefan Metzmacher
  Cc: linux-kernel, Dmitry Safonov, Dmitry Safonov, Francesco Ruggeri,
	Salam Noureddine, David Ahern, David S . Miller, Michal Luczaj,
	David Wei, Luiz Augusto von Dentz, Luiz Augusto von Dentz,
	Marcel Holtmann, Xin Long, Eric Dumazet, Kuniyuki Iwashima,
	Paolo Abeni, Willem de Bruijn, Neal Cardwell, Jakub Kicinski,
	Simon Horman, Aleksa Sarai, Christian Brauner, Kees Cook, netdev,
	linux-bluetooth

On Tue,  7 Apr 2026 18:03:15 +0200
Stefan Metzmacher <metze@samba.org> wrote:

> These are similar to copy_struct_{from,to}_user() but operate
> on kernel buffers instead of user buffers.
> 
> They can be used when there is a temporary bounce buffer used,
> e.g. in msg_control or similar places.
> 
> It allows us to have the same logic to handle old vs. current
> and current vs. new structures in the same compatible way.
> 
> copy_struct_from_sockptr() will also be able to
> use copy_struct_from_bounce_buffer() for the kernel
> case as follow us patch.
> 
> I'll use this in my IPPROTO_SMBDIRECT work,
> but maybe it will also be useful for others...
> IPPROTO_QUIC will likely also use it.
> 
> Cc: Dmitry Safonov <0x7f454c46@gmail.com>
> Cc: Dmitry Safonov <dima@arista.com>
> Cc: Francesco Ruggeri <fruggeri@arista.com>
> Cc: Salam Noureddine <noureddine@arista.com>
> Cc: David Ahern <dsahern@kernel.org>
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Michal Luczaj <mhal@rbox.co>
> Cc: David Wei <dw@davidwei.uk>
> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
> Cc: Marcel Holtmann <marcel@holtmann.org>
> Cc: Xin Long <lucien.xin@gmail.com>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: Willem de Bruijn <willemb@google.com>
> Cc: Neal Cardwell <ncardwell@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Simon Horman <horms@kernel.org>
> Cc: Aleksa Sarai <cyphar@cyphar.com>
> Cc: Christian Brauner <brauner@kernel.org>
> CC: Kees Cook <keescook@chromium.org>
> Cc: netdev@vger.kernel.org
> Cc: linux-bluetooth@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Stefan Metzmacher <metze@samba.org>
> ---
>  include/linux/uaccess.h | 63 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 63 insertions(+)
> 
> diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
> index 1234b5fa4761..a6cd4f48bb99 100644
> --- a/include/linux/uaccess.h
> +++ b/include/linux/uaccess.h
> @@ -513,6 +513,69 @@ copy_struct_to_user(void __user *dst, size_t usize, const void *src,
>  	return 0;
>  }
>  
> +static __always_inline void
> +__copy_struct_generic_bounce_buffer(void *dst, size_t dstsize,
> +				    const void *src, size_t srcsize,
> +				    bool *ignored_trailing)
> +{
> +	size_t size = min(dstsize, srcsize);
> +	size_t rest = max(dstsize, srcsize) - size;
> +
> +	/* Deal with trailing bytes. */
> +	if (dstsize > srcsize)
> +		memset(dst + size, 0, rest);
> +	if (ignored_trailing)
> +		*ignored_trailing = dstsize < srcsize &&
> +			memchr_inv(src + size, 0, rest) != NULL;
> +	/* Copy the interoperable parts of the struct. */
> +	memcpy(dst, src, size);
> +}

Return 'ignored_trailing' rather than pass by reference.
And this is probably too big to inline.

	David

> +
> +/**
> + * This is like copy_struct_from_user(), but the
> + * src buffer was already copied into a kernel
> + * bounce buffer, so it will never return -EFAULT.
> + */
> +static __always_inline __must_check int
> +copy_struct_from_bounce_buffer(void *dst, size_t dstsize,
> +			       const void *src, size_t srcsize)
> +{
> +	bool ignored_trailing;
> +
> +	/* Double check if ksize is larger than a known object size. */
> +	if (WARN_ON_ONCE(dstsize > __builtin_object_size(dst, 1)))
> +		return -E2BIG;
> +
> +	__copy_struct_generic_bounce_buffer(dst, dstsize,
> +					    src, srcsize,
> +					    &ignored_trailing);
> +	if (unlikely(ignored_trailing))
> +		return -E2BIG;
> +
> +	return 0;
> +}
> +
> +/**
> + * This is like copy_struct_to_user(), but the
> + * dst buffer is a kernel bounce buffer instead
> + * of a direct userspace buffer, so it will never return -EFAULT.
> + */
> +static __always_inline __must_check int
> +copy_struct_to_bounce_buffer(void *dst, size_t dstsize,
> +			     const void *src,
> +			     size_t srcsize,
> +			     bool *ignored_trailing)
> +{
> +	/* Double check if srcsize is larger than a known object size. */
> +	if (WARN_ON_ONCE(srcsize > __builtin_object_size(src, 1)))
> +		return -E2BIG;
> +
> +	__copy_struct_generic_bounce_buffer(dst, dstsize,
> +					    src, srcsize,
> +					    ignored_trailing);
> +	return 0;
> +}
> +
>  bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size);
>  
>  long copy_from_kernel_nofault(void *dst, const void *src, size_t size);


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

* Re: [PATCH 1/5] uaccess: fix ignored_trailing logic in copy_struct_to_user()
  2026-04-07 16:03 ` [PATCH 1/5] uaccess: fix ignored_trailing logic in copy_struct_to_user() Stefan Metzmacher
@ 2026-04-09  6:33   ` Aleksa Sarai
  2026-04-09  9:01     ` Stefan Metzmacher
  0 siblings, 1 reply; 13+ messages in thread
From: Aleksa Sarai @ 2026-04-09  6:33 UTC (permalink / raw)
  To: Stefan Metzmacher
  Cc: linux-kernel, Dmitry Safonov, Dmitry Safonov, Francesco Ruggeri,
	Salam Noureddine, David Ahern, David S . Miller, Michal Luczaj,
	David Wei, Luiz Augusto von Dentz, Luiz Augusto von Dentz,
	Marcel Holtmann, Xin Long, Eric Dumazet, Kuniyuki Iwashima,
	Paolo Abeni, Willem de Bruijn, Neal Cardwell, Jakub Kicinski,
	Simon Horman, Christian Brauner, Kees Cook, netdev,
	linux-bluetooth

[-- Attachment #1: Type: text/plain, Size: 3360 bytes --]

On 2026-04-07, Stefan Metzmacher <metze@samba.org> wrote:
> Currently all callers pass ignored_trailing=NULL, but I have
> code that will make use of.
> 
> Now it actually behaves like documented:
> 
> * If @usize < @ksize, then the kernel is trying to pass userspace a newer
>   struct than it supports. Thus we only copy the interoperable portions
>   (@usize) and ignore the rest (but @ignored_trailing is set to %true if
>   any of the trailing (@ksize - @usize) bytes are non-zero).

Good catch, though I want to mention that the current API design for
copy_struct_to_user() is a bit of a compromise -- I was trying to think
of a way of making it generic but what information you need really
depends on your API.

For request-flag APIs (like statx) then you can just unset the bits in
the response mask for fields past usize and so it is a non-fatal error,
but it requires knowing which field offsets map to which flags.

My initial idea for ignored_trailing was for it to return the offset
memchr_inv() gives you -- but unfortunately, this doesn't help in the
more generic case where you have multiple non-zero bits that need to
unset multiple flags.

Out of interest, how did you plan on using it? It might be a good idea
to rethink this API before it starts getting used "in anger" in a way
that leaks to uAPIs we can't change.

In any case, for this patch feel free to take my

Reviewed-by: Aleksa Sarai <aleksa@amutable.com>

> Fixes: 424a55a4a908 ("uaccess: add copy_struct_to_user helper")
> Cc: Dmitry Safonov <0x7f454c46@gmail.com>
> Cc: Dmitry Safonov <dima@arista.com>
> Cc: Francesco Ruggeri <fruggeri@arista.com>
> Cc: Salam Noureddine <noureddine@arista.com>
> Cc: David Ahern <dsahern@kernel.org>
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Michal Luczaj <mhal@rbox.co>
> Cc: David Wei <dw@davidwei.uk>
> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
> Cc: Marcel Holtmann <marcel@holtmann.org>
> Cc: Xin Long <lucien.xin@gmail.com>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: Willem de Bruijn <willemb@google.com>
> Cc: Neal Cardwell <ncardwell@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Simon Horman <horms@kernel.org>
> Cc: Aleksa Sarai <cyphar@cyphar.com>
> Cc: Christian Brauner <brauner@kernel.org>
> CC: Kees Cook <keescook@chromium.org>
> Cc: netdev@vger.kernel.org
> Cc: linux-bluetooth@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Stefan Metzmacher <metze@samba.org>
> ---
>  include/linux/uaccess.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
> index 4fe63169d5a2..1234b5fa4761 100644
> --- a/include/linux/uaccess.h
> +++ b/include/linux/uaccess.h
> @@ -505,7 +505,7 @@ copy_struct_to_user(void __user *dst, size_t usize, const void *src,
>  			return -EFAULT;
>  	}
>  	if (ignored_trailing)
> -		*ignored_trailing = ksize < usize &&
> +		*ignored_trailing = usize < ksize &&
>  			memchr_inv(src + size, 0, rest) != NULL;
>  	/* Copy the interoperable parts of the struct. */
>  	if (copy_to_user(dst, src, size))
> -- 
> 2.43.0
> 

-- 
Aleksa Sarai
https://www.cyphar.com/

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 265 bytes --]

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

* Re: [PATCH 2/5] sockptr: fix usize check in copy_struct_from_sockptr() for user pointers
  2026-04-07 16:03 ` [PATCH 2/5] sockptr: fix usize check in copy_struct_from_sockptr() for user pointers Stefan Metzmacher
@ 2026-04-09  6:37   ` Aleksa Sarai
  2026-04-09  6:39     ` Aleksa Sarai
  0 siblings, 1 reply; 13+ messages in thread
From: Aleksa Sarai @ 2026-04-09  6:37 UTC (permalink / raw)
  To: Stefan Metzmacher
  Cc: linux-kernel, Dmitry Safonov, Dmitry Safonov, Francesco Ruggeri,
	Salam Noureddine, David Ahern, David S . Miller, Michal Luczaj,
	David Wei, Luiz Augusto von Dentz, Luiz Augusto von Dentz,
	Marcel Holtmann, Xin Long, Eric Dumazet, Kuniyuki Iwashima,
	Paolo Abeni, Willem de Bruijn, Neal Cardwell, Jakub Kicinski,
	Simon Horman, Christian Brauner, Kees Cook, netdev,
	linux-bluetooth

[-- Attachment #1: Type: text/plain, Size: 2936 bytes --]

On 2026-04-07, Stefan Metzmacher <metze@samba.org> wrote:
> copy_struct_from_user will never hit the check_zeroed_user() call
> and will never return -E2BIG if new userspace passed new bits in a
> larger structure than the current kernel structure.
> 
> As far as I can there are no critical/related uapi changes in
> 
> - include/net/bluetooth/bluetooth.h and net/bluetooth/sco.c
>   after the use of copy_struct_from_sockptr in v6.13-rc3
> - include/uapi/linux/tcp.h and net/ipv4/tcp_ao.c
>   after the use of copy_struct_from_sockptr in v6.6-rc1
> 
> So that new callers will get the correct behavior from the start.
> 
> Fixes: 4954f17ddefc ("net/tcp: Introduce TCP_AO setsockopt()s")
> Fixes: ef84703a911f ("net/tcp: Add TCP-AO getsockopt()s")
> Fixes: faadfaba5e01 ("net/tcp: Add TCP_AO_REPAIR")
> Fixes: 3e643e4efa1e ("Bluetooth: Improve setsockopt() handling of malformed user input")
> Cc: Dmitry Safonov <0x7f454c46@gmail.com>
> Cc: Dmitry Safonov <dima@arista.com>
> Cc: Francesco Ruggeri <fruggeri@arista.com>
> Cc: Salam Noureddine <noureddine@arista.com>
> Cc: David Ahern <dsahern@kernel.org>
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Michal Luczaj <mhal@rbox.co>
> Cc: David Wei <dw@davidwei.uk>
> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
> Cc: Marcel Holtmann <marcel@holtmann.org>
> Cc: Xin Long <lucien.xin@gmail.com>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Kuniyuki Iwashima <kuniyu@google.com>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: Willem de Bruijn <willemb@google.com>
> Cc: Neal Cardwell <ncardwell@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Simon Horman <horms@kernel.org>
> Cc: Aleksa Sarai <cyphar@cyphar.com>
> Cc: Christian Brauner <brauner@kernel.org>
> CC: Kees Cook <keescook@chromium.org>
> Cc: netdev@vger.kernel.org
> Cc: linux-bluetooth@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Stefan Metzmacher <metze@samba.org>
> ---
>  include/linux/sockptr.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/linux/sockptr.h b/include/linux/sockptr.h
> index 3e6c8e9d67ae..ba88f4d78c1b 100644
> --- a/include/linux/sockptr.h
> +++ b/include/linux/sockptr.h
> @@ -91,7 +91,7 @@ static inline int copy_struct_from_sockptr(void *dst, size_t ksize,
>  	size_t rest = max(ksize, usize) - size;
>  
>  	if (!sockptr_is_kernel(src))
> -		return copy_struct_from_user(dst, ksize, src.user, size);
> +		return copy_struct_from_user(dst, ksize, src.user, usize);
>  
>  	if (usize < ksize) {
>  		memset(dst + size, 0, rest);

It is a little weird that this function open-codes memchr_inv() --
check_zeroed_sockptr() exists and does the right thing. Maybe it'd be
nice to fix that too?

In any case,

Reviewed-by: Aleksa Sarai <aleksa@amutable.com>

-- 
Aleksa Sarai
https://www.cyphar.com/

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 265 bytes --]

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

* Re: [PATCH 2/5] sockptr: fix usize check in copy_struct_from_sockptr() for user pointers
  2026-04-09  6:37   ` Aleksa Sarai
@ 2026-04-09  6:39     ` Aleksa Sarai
  0 siblings, 0 replies; 13+ messages in thread
From: Aleksa Sarai @ 2026-04-09  6:39 UTC (permalink / raw)
  To: Stefan Metzmacher
  Cc: linux-kernel, Dmitry Safonov, Dmitry Safonov, Francesco Ruggeri,
	Salam Noureddine, David Ahern, David S . Miller, Michal Luczaj,
	David Wei, Luiz Augusto von Dentz, Luiz Augusto von Dentz,
	Marcel Holtmann, Xin Long, Eric Dumazet, Kuniyuki Iwashima,
	Paolo Abeni, Willem de Bruijn, Neal Cardwell, Jakub Kicinski,
	Simon Horman, Christian Brauner, Kees Cook, netdev,
	linux-bluetooth

[-- Attachment #1: Type: text/plain, Size: 3196 bytes --]

On 2026-04-09, Aleksa Sarai <cyphar@cyphar.com> wrote:
> On 2026-04-07, Stefan Metzmacher <metze@samba.org> wrote:
> > copy_struct_from_user will never hit the check_zeroed_user() call
> > and will never return -E2BIG if new userspace passed new bits in a
> > larger structure than the current kernel structure.
> > 
> > As far as I can there are no critical/related uapi changes in
> > 
> > - include/net/bluetooth/bluetooth.h and net/bluetooth/sco.c
> >   after the use of copy_struct_from_sockptr in v6.13-rc3
> > - include/uapi/linux/tcp.h and net/ipv4/tcp_ao.c
> >   after the use of copy_struct_from_sockptr in v6.6-rc1
> > 
> > So that new callers will get the correct behavior from the start.
> > 
> > Fixes: 4954f17ddefc ("net/tcp: Introduce TCP_AO setsockopt()s")
> > Fixes: ef84703a911f ("net/tcp: Add TCP-AO getsockopt()s")
> > Fixes: faadfaba5e01 ("net/tcp: Add TCP_AO_REPAIR")
> > Fixes: 3e643e4efa1e ("Bluetooth: Improve setsockopt() handling of malformed user input")
> > Cc: Dmitry Safonov <0x7f454c46@gmail.com>
> > Cc: Dmitry Safonov <dima@arista.com>
> > Cc: Francesco Ruggeri <fruggeri@arista.com>
> > Cc: Salam Noureddine <noureddine@arista.com>
> > Cc: David Ahern <dsahern@kernel.org>
> > Cc: David S. Miller <davem@davemloft.net>
> > Cc: Michal Luczaj <mhal@rbox.co>
> > Cc: David Wei <dw@davidwei.uk>
> > Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> > Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
> > Cc: Marcel Holtmann <marcel@holtmann.org>
> > Cc: Xin Long <lucien.xin@gmail.com>
> > Cc: Eric Dumazet <edumazet@google.com>
> > Cc: Kuniyuki Iwashima <kuniyu@google.com>
> > Cc: Paolo Abeni <pabeni@redhat.com>
> > Cc: Willem de Bruijn <willemb@google.com>
> > Cc: Neal Cardwell <ncardwell@google.com>
> > Cc: Jakub Kicinski <kuba@kernel.org>
> > Cc: Simon Horman <horms@kernel.org>
> > Cc: Aleksa Sarai <cyphar@cyphar.com>
> > Cc: Christian Brauner <brauner@kernel.org>
> > CC: Kees Cook <keescook@chromium.org>
> > Cc: netdev@vger.kernel.org
> > Cc: linux-bluetooth@vger.kernel.org
> > Cc: linux-kernel@vger.kernel.org
> > Signed-off-by: Stefan Metzmacher <metze@samba.org>
> > ---
> >  include/linux/sockptr.h | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/include/linux/sockptr.h b/include/linux/sockptr.h
> > index 3e6c8e9d67ae..ba88f4d78c1b 100644
> > --- a/include/linux/sockptr.h
> > +++ b/include/linux/sockptr.h
> > @@ -91,7 +91,7 @@ static inline int copy_struct_from_sockptr(void *dst, size_t ksize,
> >  	size_t rest = max(ksize, usize) - size;
> >  
> >  	if (!sockptr_is_kernel(src))
> > -		return copy_struct_from_user(dst, ksize, src.user, size);
> > +		return copy_struct_from_user(dst, ksize, src.user, usize);
> >  
> >  	if (usize < ksize) {
> >  		memset(dst + size, 0, rest);
> 
> It is a little weird that this function open-codes memchr_inv() --
> check_zeroed_sockptr() exists and does the right thing. Maybe it'd be
> nice to fix that too?

Ah my bad, I didn't see that you already fixed this in patch #4.

> In any case,
> 
> Reviewed-by: Aleksa Sarai <aleksa@amutable.com>

-- 
Aleksa Sarai
https://www.cyphar.com/

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 265 bytes --]

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

* Re: [PATCH 3/5] uaccess: add copy_struct_{from,to}_bounce_buffer() helpers
  2026-04-07 18:25   ` David Laight
@ 2026-04-09  8:47     ` Stefan Metzmacher
  0 siblings, 0 replies; 13+ messages in thread
From: Stefan Metzmacher @ 2026-04-09  8:47 UTC (permalink / raw)
  To: David Laight
  Cc: linux-kernel, Dmitry Safonov, Dmitry Safonov, Francesco Ruggeri,
	Salam Noureddine, David Ahern, David S . Miller, Michal Luczaj,
	David Wei, Luiz Augusto von Dentz, Luiz Augusto von Dentz,
	Marcel Holtmann, Xin Long, Eric Dumazet, Kuniyuki Iwashima,
	Paolo Abeni, Willem de Bruijn, Neal Cardwell, Jakub Kicinski,
	Simon Horman, Aleksa Sarai, Christian Brauner, Kees Cook, netdev,
	linux-bluetooth

Hi David,

> On Tue,  7 Apr 2026 18:03:15 +0200
> Stefan Metzmacher <metze@samba.org> wrote:
> 
>> These are similar to copy_struct_{from,to}_user() but operate
>> on kernel buffers instead of user buffers.
>>
>> They can be used when there is a temporary bounce buffer used,
>> e.g. in msg_control or similar places.
>>
>> It allows us to have the same logic to handle old vs. current
>> and current vs. new structures in the same compatible way.
>>
>> copy_struct_from_sockptr() will also be able to
>> use copy_struct_from_bounce_buffer() for the kernel
>> case as follow us patch.
>>
>> I'll use this in my IPPROTO_SMBDIRECT work,
>> but maybe it will also be useful for others...
>> IPPROTO_QUIC will likely also use it.
>>
>> Cc: Dmitry Safonov <0x7f454c46@gmail.com>
>> Cc: Dmitry Safonov <dima@arista.com>
>> Cc: Francesco Ruggeri <fruggeri@arista.com>
>> Cc: Salam Noureddine <noureddine@arista.com>
>> Cc: David Ahern <dsahern@kernel.org>
>> Cc: David S. Miller <davem@davemloft.net>
>> Cc: Michal Luczaj <mhal@rbox.co>
>> Cc: David Wei <dw@davidwei.uk>
>> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>> Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
>> Cc: Marcel Holtmann <marcel@holtmann.org>
>> Cc: Xin Long <lucien.xin@gmail.com>
>> Cc: Eric Dumazet <edumazet@google.com>
>> Cc: Kuniyuki Iwashima <kuniyu@google.com>
>> Cc: Paolo Abeni <pabeni@redhat.com>
>> Cc: Willem de Bruijn <willemb@google.com>
>> Cc: Neal Cardwell <ncardwell@google.com>
>> Cc: Jakub Kicinski <kuba@kernel.org>
>> Cc: Simon Horman <horms@kernel.org>
>> Cc: Aleksa Sarai <cyphar@cyphar.com>
>> Cc: Christian Brauner <brauner@kernel.org>
>> CC: Kees Cook <keescook@chromium.org>
>> Cc: netdev@vger.kernel.org
>> Cc: linux-bluetooth@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Signed-off-by: Stefan Metzmacher <metze@samba.org>
>> ---
>>   include/linux/uaccess.h | 63 +++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 63 insertions(+)
>>
>> diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
>> index 1234b5fa4761..a6cd4f48bb99 100644
>> --- a/include/linux/uaccess.h
>> +++ b/include/linux/uaccess.h
>> @@ -513,6 +513,69 @@ copy_struct_to_user(void __user *dst, size_t usize, const void *src,
>>   	return 0;
>>   }
>>   
>> +static __always_inline void
>> +__copy_struct_generic_bounce_buffer(void *dst, size_t dstsize,
>> +				    const void *src, size_t srcsize,
>> +				    bool *ignored_trailing)
>> +{
>> +	size_t size = min(dstsize, srcsize);
>> +	size_t rest = max(dstsize, srcsize) - size;
>> +
>> +	/* Deal with trailing bytes. */
>> +	if (dstsize > srcsize)
>> +		memset(dst + size, 0, rest);
>> +	if (ignored_trailing)
>> +		*ignored_trailing = dstsize < srcsize &&
>> +			memchr_inv(src + size, 0, rest) != NULL;
>> +	/* Copy the interoperable parts of the struct. */
>> +	memcpy(dst, src, size);
>> +}
> 
> Return 'ignored_trailing' rather than pass by reference.

I also thought about that but it makes
the copy_struct_to_ case more complex.

I'm not sure but my guess would be that
the compiler would have the chance to skip the
ignore_trailing logic if (as all current callers do)
NULL is passed.

> And this is probably too big to inline.

In the next patch this replace open coded logic in
copy_struct_from_sockptr. So as all of copy_struct_*
consists of inline functions I thought it would be good to
keep it that way.

So unless there a real good reason to change it
I'd like to keep it as is.

Thanks!
metze

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

* Re: [PATCH 1/5] uaccess: fix ignored_trailing logic in copy_struct_to_user()
  2026-04-09  6:33   ` Aleksa Sarai
@ 2026-04-09  9:01     ` Stefan Metzmacher
  0 siblings, 0 replies; 13+ messages in thread
From: Stefan Metzmacher @ 2026-04-09  9:01 UTC (permalink / raw)
  To: Aleksa Sarai
  Cc: linux-kernel, Dmitry Safonov, Dmitry Safonov, Salam Noureddine,
	David Ahern, David S . Miller, Michal Luczaj, David Wei,
	Luiz Augusto von Dentz, Luiz Augusto von Dentz, Marcel Holtmann,
	Xin Long, Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni,
	Willem de Bruijn, Neal Cardwell, Jakub Kicinski, Simon Horman,
	Christian Brauner, Kees Cook, netdev, linux-bluetooth

Hi Aleksa,

> On 2026-04-07, Stefan Metzmacher <metze@samba.org> wrote:
>> Currently all callers pass ignored_trailing=NULL, but I have
>> code that will make use of.
>>
>> Now it actually behaves like documented:
>>
>> * If @usize < @ksize, then the kernel is trying to pass userspace a newer
>>    struct than it supports. Thus we only copy the interoperable portions
>>    (@usize) and ignore the rest (but @ignored_trailing is set to %true if
>>    any of the trailing (@ksize - @usize) bytes are non-zero).
> 
> Good catch, though I want to mention that the current API design for
> copy_struct_to_user() is a bit of a compromise -- I was trying to think
> of a way of making it generic but what information you need really
> depends on your API.
> 
> For request-flag APIs (like statx) then you can just unset the bits in
> the response mask for fields past usize and so it is a non-fatal error,
> but it requires knowing which field offsets map to which flags.
> 
> My initial idea for ignored_trailing was for it to return the offset
> memchr_inv() gives you -- but unfortunately, this doesn't help in the
> more generic case where you have multiple non-zero bits that need to
> unset multiple flags.

I guess the caller could use if (ignored_trailing) { ... }
to check more complex stuff and then decide ignore or return an error.

> Out of interest, how did you plan on using it? It might be a good idea
> to rethink this API before it starts getting used "in anger" in a way
> that leaks to uAPIs we can't change.

Currently I only use it with WARN_ON_ONCE(ignored_trailing);
in order to catch internal errors. See
https://git.samba.org/?p=metze/linux/wip.git;a=blob;f=fs/smb/common/smbdirect/smbdirect_proto.c;h=ce7c78eb6795041ba672da434ffb01db73269cb7;hb=37c61ef9758f3e113d4078220d8fc2aee366c955#l1625
But I guess I will at least change it to
if (WARN_ON_ONCE(ignored_trailing))
     return...

And in general I thought it would be good practice to
check that case in new code in order to avoid unexpected
behavior.

> In any case, for this patch feel free to take my
> 
> Reviewed-by: Aleksa Sarai <aleksa@amutable.com>

Thanks!
metze


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

* Re: [PATCH 0/5] uaccess/sockptr: copy_struct_ fixes and more helpers
  2026-04-07 16:03 [PATCH 0/5] uaccess/sockptr: copy_struct_ fixes and more helpers Stefan Metzmacher
                   ` (4 preceding siblings ...)
  2026-04-07 16:03 ` [PATCH 5/5] sockptr: introduce copy_struct_to_sockptr() Stefan Metzmacher
@ 2026-04-09 13:05 ` Christian Brauner
  5 siblings, 0 replies; 13+ messages in thread
From: Christian Brauner @ 2026-04-09 13:05 UTC (permalink / raw)
  To: linux-kernel, Stefan Metzmacher
  Cc: Christian Brauner, Dmitry Safonov, Francesco Ruggeri,
	Salam Noureddine, David Ahern, David S . Miller, Michal Luczaj,
	David Wei, Luiz Augusto von Dentz, Luiz Augusto von Dentz,
	Marcel Holtmann, Xin Long, Eric Dumazet, Kuniyuki Iwashima,
	Paolo Abeni, Willem de Bruijn, Neal Cardwell, Jakub Kicinski,
	Simon Horman, Aleksa Sarai, netdev, linux-bluetooth, Kees Cook

On Tue, 07 Apr 2026 18:03:12 +0200, Stefan Metzmacher wrote:
> here are some patches related to
> copy_struct_{from,to}_{user,sockptr}()
> I collected during my work on an IPPROTO_SMBDIRECT
> implementation wrapping the smbdirect code used
> by cifs.ko and ksmbd.ko.
> 
> The first patch fixes copy_struct_to_user()
> to behave like documented.
> 
> [...]

Applied to the vfs-7.2.misc branch of the vfs/vfs.git tree.
Patches in the vfs-7.2.misc branch should appear in linux-next soon.

Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.

It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.

Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs-7.2.misc

[1/5] uaccess: fix ignored_trailing logic in copy_struct_to_user()
      https://git.kernel.org/vfs/vfs/c/0a8d67b47a5c
[2/5] sockptr: fix usize check in copy_struct_from_sockptr() for user pointers
      https://git.kernel.org/vfs/vfs/c/e555ebefea0a
[3/5] uaccess: add copy_struct_{from,to}_bounce_buffer() helpers
      https://git.kernel.org/vfs/vfs/c/14e710721cd3
[4/5] sockptr: let copy_struct_from_sockptr() use copy_struct_from_bounce_buffer()
      https://git.kernel.org/vfs/vfs/c/62343ea38031
[5/5] sockptr: introduce copy_struct_to_sockptr()
      https://git.kernel.org/vfs/vfs/c/9899f22cc41d

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

end of thread, other threads:[~2026-04-09 13:05 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-07 16:03 [PATCH 0/5] uaccess/sockptr: copy_struct_ fixes and more helpers Stefan Metzmacher
2026-04-07 16:03 ` [PATCH 1/5] uaccess: fix ignored_trailing logic in copy_struct_to_user() Stefan Metzmacher
2026-04-09  6:33   ` Aleksa Sarai
2026-04-09  9:01     ` Stefan Metzmacher
2026-04-07 16:03 ` [PATCH 2/5] sockptr: fix usize check in copy_struct_from_sockptr() for user pointers Stefan Metzmacher
2026-04-09  6:37   ` Aleksa Sarai
2026-04-09  6:39     ` Aleksa Sarai
2026-04-07 16:03 ` [PATCH 3/5] uaccess: add copy_struct_{from,to}_bounce_buffer() helpers Stefan Metzmacher
2026-04-07 18:25   ` David Laight
2026-04-09  8:47     ` Stefan Metzmacher
2026-04-07 16:03 ` [PATCH 4/5] sockptr: let copy_struct_from_sockptr() use copy_struct_from_bounce_buffer() Stefan Metzmacher
2026-04-07 16:03 ` [PATCH 5/5] sockptr: introduce copy_struct_to_sockptr() Stefan Metzmacher
2026-04-09 13:05 ` [PATCH 0/5] uaccess/sockptr: copy_struct_ fixes and more helpers Christian Brauner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox