mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
uaccess: add copy_struct_{from,to}_bounce_buffer() helpers
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>
Link: https://patch.msgid.link/f29570914590c50b9b6f451eb3a38d0fe1d954df.1775576651.git.metze@samba.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
db04935129
commit
2eef8b32e4
|
|
@ -518,6 +518,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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user