Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/bitops.h>
0003 #include <linux/fault-inject-usercopy.h>
0004 #include <linux/instrumented.h>
0005 #include <linux/uaccess.h>
0006 
0007 /* out-of-line parts */
0008 
0009 #ifndef INLINE_COPY_FROM_USER
0010 unsigned long _copy_from_user(void *to, const void __user *from, unsigned long n)
0011 {
0012     unsigned long res = n;
0013     might_fault();
0014     if (!should_fail_usercopy() && likely(access_ok(from, n))) {
0015         instrument_copy_from_user(to, from, n);
0016         res = raw_copy_from_user(to, from, n);
0017     }
0018     if (unlikely(res))
0019         memset(to + (n - res), 0, res);
0020     return res;
0021 }
0022 EXPORT_SYMBOL(_copy_from_user);
0023 #endif
0024 
0025 #ifndef INLINE_COPY_TO_USER
0026 unsigned long _copy_to_user(void __user *to, const void *from, unsigned long n)
0027 {
0028     might_fault();
0029     if (should_fail_usercopy())
0030         return n;
0031     if (likely(access_ok(to, n))) {
0032         instrument_copy_to_user(to, from, n);
0033         n = raw_copy_to_user(to, from, n);
0034     }
0035     return n;
0036 }
0037 EXPORT_SYMBOL(_copy_to_user);
0038 #endif
0039 
0040 /**
0041  * check_zeroed_user: check if a userspace buffer only contains zero bytes
0042  * @from: Source address, in userspace.
0043  * @size: Size of buffer.
0044  *
0045  * This is effectively shorthand for "memchr_inv(from, 0, size) == NULL" for
0046  * userspace addresses (and is more efficient because we don't care where the
0047  * first non-zero byte is).
0048  *
0049  * Returns:
0050  *  * 0: There were non-zero bytes present in the buffer.
0051  *  * 1: The buffer was full of zero bytes.
0052  *  * -EFAULT: access to userspace failed.
0053  */
0054 int check_zeroed_user(const void __user *from, size_t size)
0055 {
0056     unsigned long val;
0057     uintptr_t align = (uintptr_t) from % sizeof(unsigned long);
0058 
0059     if (unlikely(size == 0))
0060         return 1;
0061 
0062     from -= align;
0063     size += align;
0064 
0065     if (!user_read_access_begin(from, size))
0066         return -EFAULT;
0067 
0068     unsafe_get_user(val, (unsigned long __user *) from, err_fault);
0069     if (align)
0070         val &= ~aligned_byte_mask(align);
0071 
0072     while (size > sizeof(unsigned long)) {
0073         if (unlikely(val))
0074             goto done;
0075 
0076         from += sizeof(unsigned long);
0077         size -= sizeof(unsigned long);
0078 
0079         unsafe_get_user(val, (unsigned long __user *) from, err_fault);
0080     }
0081 
0082     if (size < sizeof(unsigned long))
0083         val &= aligned_byte_mask(size);
0084 
0085 done:
0086     user_read_access_end();
0087     return (val == 0);
0088 err_fault:
0089     user_read_access_end();
0090     return -EFAULT;
0091 }
0092 EXPORT_SYMBOL(check_zeroed_user);