On 13/12/2022 12:55, Beata Michalska wrote:
Introduce a variant of copy_struct_from_user that will make use of copy_to_user_with_ptr as its actual copying routine, in order to
Just noticed, s/copy_to_user/copy_from_user/
Kevin
preserve capability tags throughout the process.
Signed-off-by: Beata Michalska beata.michalska@arm.com
include/linux/uaccess.h | 60 ++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 13 deletions(-)
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index 88b2224e85c3..e17bd4dce0d6 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h @@ -356,6 +356,24 @@ __copy_from_user_inatomic_nocache(void *to, const void __user *from, extern __must_check int check_zeroed_user(const void __user *from, size_t size); +static __always_inline __must_check int +__copy_struct_from_user_prepare(void *dst, size_t ksize, const void __user *src,
size_t usize)+{
- size_t size = min(ksize, usize);
 - size_t rest = max(ksize, usize) - size;
 - /* Deal with trailing bytes. */
 - if (usize < ksize) {
 memset(dst + size, 0, rest);- } else if (usize > ksize) {
 int ret = check_zeroed_user(src + size, rest);if (ret <= 0)return ret ?: -E2BIG;- }
 - return 0;
 +}
/**
- copy_struct_from_user: copy a struct from userspace
 - @dst: Destination address, in kernel space. This buffer must be @ksize
 @@ -408,20 +426,36 @@ copy_struct_from_user(void *dst, size_t ksize, const void __user *src, size_t usize) { size_t size = min(ksize, usize);
- size_t rest = max(ksize, usize) - size;
 
- int ret;
 
- /* Deal with trailing bytes. */
 - if (usize < ksize) {
 memset(dst + size, 0, rest);- } else if (usize > ksize) {
 int ret = check_zeroed_user(src + size, rest);if (ret <= 0)return ret ?: -E2BIG;- }
 - /* Copy the interoperable parts of the struct. */
 - if (copy_from_user(dst, src, size))
 return -EFAULT;- return 0;
 
- ret = __copy_struct_from_user_prepare(dst, ksize, src, usize);
 - return ret ?: (copy_from_user(dst, src, size) ? -EFAULT : 0);
 +}
+/**
- copy_struct_from_user_with_ptr: copy a struct from userspace
 
- @dst: Destination address, in kernel space. This buffer must be @ksize
 
bytes long.
- @ksize: Size of @dst struct.
 
- @src: Source address, in userspace.
 
- @usize: (Alleged) size of @src struct.
 
- Counterpart of copy_struct_from_user that deals with structures,
 
- members of which can contain user pointers.
 
- Otherwise, same logic/requirements apply.
 - */
 +static __always_inline __must_check int +copy_struct_from_user_with_ptr(void *dst, size_t ksize, const void __user *src,
size_t usize)+{
- size_t size = min(ksize, usize);
 - int ret;
 - ret = __copy_struct_from_user_prepare(dst, ksize, src, usize);
 - return ret ?: (copy_from_user_with_ptr(dst, src, size) ? -EFAULT : 0);
 } bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size);