root/lib/usercopy.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _copy_from_user
  2. _copy_to_user
  3. check_zeroed_user

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/uaccess.h>
   3 #include <linux/bitops.h>
   4 
   5 /* out-of-line parts */
   6 
   7 #ifndef INLINE_COPY_FROM_USER
   8 unsigned long _copy_from_user(void *to, const void __user *from, unsigned long n)
   9 {
  10         unsigned long res = n;
  11         might_fault();
  12         if (likely(access_ok(from, n))) {
  13                 kasan_check_write(to, n);
  14                 res = raw_copy_from_user(to, from, n);
  15         }
  16         if (unlikely(res))
  17                 memset(to + (n - res), 0, res);
  18         return res;
  19 }
  20 EXPORT_SYMBOL(_copy_from_user);
  21 #endif
  22 
  23 #ifndef INLINE_COPY_TO_USER
  24 unsigned long _copy_to_user(void __user *to, const void *from, unsigned long n)
  25 {
  26         might_fault();
  27         if (likely(access_ok(to, n))) {
  28                 kasan_check_read(from, n);
  29                 n = raw_copy_to_user(to, from, n);
  30         }
  31         return n;
  32 }
  33 EXPORT_SYMBOL(_copy_to_user);
  34 #endif
  35 
  36 /**
  37  * check_zeroed_user: check if a userspace buffer only contains zero bytes
  38  * @from: Source address, in userspace.
  39  * @size: Size of buffer.
  40  *
  41  * This is effectively shorthand for "memchr_inv(from, 0, size) == NULL" for
  42  * userspace addresses (and is more efficient because we don't care where the
  43  * first non-zero byte is).
  44  *
  45  * Returns:
  46  *  * 0: There were non-zero bytes present in the buffer.
  47  *  * 1: The buffer was full of zero bytes.
  48  *  * -EFAULT: access to userspace failed.
  49  */
  50 int check_zeroed_user(const void __user *from, size_t size)
  51 {
  52         unsigned long val;
  53         uintptr_t align = (uintptr_t) from % sizeof(unsigned long);
  54 
  55         if (unlikely(size == 0))
  56                 return 1;
  57 
  58         from -= align;
  59         size += align;
  60 
  61         if (!user_access_begin(from, size))
  62                 return -EFAULT;
  63 
  64         unsafe_get_user(val, (unsigned long __user *) from, err_fault);
  65         if (align)
  66                 val &= ~aligned_byte_mask(align);
  67 
  68         while (size > sizeof(unsigned long)) {
  69                 if (unlikely(val))
  70                         goto done;
  71 
  72                 from += sizeof(unsigned long);
  73                 size -= sizeof(unsigned long);
  74 
  75                 unsafe_get_user(val, (unsigned long __user *) from, err_fault);
  76         }
  77 
  78         if (size < sizeof(unsigned long))
  79                 val &= aligned_byte_mask(size);
  80 
  81 done:
  82         user_access_end();
  83         return (val == 0);
  84 err_fault:
  85         user_access_end();
  86         return -EFAULT;
  87 }
  88 EXPORT_SYMBOL(check_zeroed_user);

/* [<][>][^][v][top][bottom][index][help] */