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