0001
0002 #include <linux/bitops.h>
0003 #include <linux/fault-inject-usercopy.h>
0004 #include <linux/instrumented.h>
0005 #include <linux/uaccess.h>
0006
0007
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
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
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);