linux/mm/maccess.c
<<
>>
Prefs
   1/*
   2 * Access kernel memory without faulting.
   3 */
   4#include <linux/export.h>
   5#include <linux/mm.h>
   6#include <linux/uaccess.h>
   7
   8static __always_inline long
   9probe_read_common(void *dst, const void __user *src, size_t size)
  10{
  11        long ret;
  12
  13        pagefault_disable();
  14        ret = __copy_from_user_inatomic(dst, src, size);
  15        pagefault_enable();
  16
  17        return ret ? -EFAULT : 0;
  18}
  19
  20static __always_inline long
  21probe_write_common(void __user *dst, const void *src, size_t size)
  22{
  23        long ret;
  24
  25        pagefault_disable();
  26        ret = __copy_to_user_inatomic(dst, src, size);
  27        pagefault_enable();
  28
  29        return ret ? -EFAULT : 0;
  30}
  31
  32/**
  33 * probe_kernel_read(): safely attempt to read from a kernel-space location
  34 * @dst: pointer to the buffer that shall take the data
  35 * @src: address to read from
  36 * @size: size of the data chunk
  37 *
  38 * Safely read from address @src to the buffer at @dst.  If a kernel fault
  39 * happens, handle that and return -EFAULT.
  40 *
  41 * We ensure that the copy_from_user is executed in atomic context so that
  42 * do_page_fault() doesn't attempt to take mmap_sem.  This makes
  43 * probe_kernel_read() suitable for use within regions where the caller
  44 * already holds mmap_sem, or other locks which nest inside mmap_sem.
  45 *
  46 * probe_kernel_read_strict() is the same as probe_kernel_read() except for
  47 * the case where architectures have non-overlapping user and kernel address
  48 * ranges: probe_kernel_read_strict() will additionally return -EFAULT for
  49 * probing memory on a user address range where probe_user_read() is supposed
  50 * to be used instead.
  51 */
  52
  53long __weak probe_kernel_read(void *dst, const void *src, size_t size)
  54    __attribute__((alias("__probe_kernel_read")));
  55
  56long __weak probe_kernel_read_strict(void *dst, const void *src, size_t size)
  57    __attribute__((alias("__probe_kernel_read")));
  58
  59long __probe_kernel_read(void *dst, const void *src, size_t size)
  60{
  61        long ret;
  62        mm_segment_t old_fs = get_fs();
  63
  64        set_fs(KERNEL_DS);
  65        ret = probe_read_common(dst, (__force const void __user *)src, size);
  66        set_fs(old_fs);
  67
  68        return ret;
  69}
  70EXPORT_SYMBOL_GPL(probe_kernel_read);
  71
  72/**
  73 * probe_user_read(): safely attempt to read from a user-space location
  74 * @dst: pointer to the buffer that shall take the data
  75 * @src: address to read from. This must be a user address.
  76 * @size: size of the data chunk
  77 *
  78 * Safely read from user address @src to the buffer at @dst. If a kernel fault
  79 * happens, handle that and return -EFAULT.
  80 */
  81
  82long __weak probe_user_read(void *dst, const void __user *src, size_t size)
  83    __attribute__((alias("__probe_user_read")));
  84
  85long __probe_user_read(void *dst, const void __user *src, size_t size)
  86{
  87        long ret = -EFAULT;
  88        mm_segment_t old_fs = get_fs();
  89
  90        set_fs(USER_DS);
  91        if (access_ok(src, size))
  92                ret = probe_read_common(dst, src, size);
  93        set_fs(old_fs);
  94
  95        return ret;
  96}
  97EXPORT_SYMBOL_GPL(probe_user_read);
  98
  99/**
 100 * probe_kernel_write(): safely attempt to write to a location
 101 * @dst: address to write to
 102 * @src: pointer to the data that shall be written
 103 * @size: size of the data chunk
 104 *
 105 * Safely write to address @dst from the buffer at @src.  If a kernel fault
 106 * happens, handle that and return -EFAULT.
 107 */
 108
 109long __weak probe_kernel_write(void *dst, const void *src, size_t size)
 110    __attribute__((alias("__probe_kernel_write")));
 111
 112long __probe_kernel_write(void *dst, const void *src, size_t size)
 113{
 114        long ret;
 115        mm_segment_t old_fs = get_fs();
 116
 117        set_fs(KERNEL_DS);
 118        ret = probe_write_common((__force void __user *)dst, src, size);
 119        set_fs(old_fs);
 120
 121        return ret;
 122}
 123EXPORT_SYMBOL_GPL(probe_kernel_write);
 124
 125/**
 126 * probe_user_write(): safely attempt to write to a user-space location
 127 * @dst: address to write to
 128 * @src: pointer to the data that shall be written
 129 * @size: size of the data chunk
 130 *
 131 * Safely write to address @dst from the buffer at @src.  If a kernel fault
 132 * happens, handle that and return -EFAULT.
 133 */
 134
 135long __weak probe_user_write(void __user *dst, const void *src, size_t size)
 136    __attribute__((alias("__probe_user_write")));
 137
 138long __probe_user_write(void __user *dst, const void *src, size_t size)
 139{
 140        long ret = -EFAULT;
 141        mm_segment_t old_fs = get_fs();
 142
 143        set_fs(USER_DS);
 144        if (access_ok(dst, size))
 145                ret = probe_write_common(dst, src, size);
 146        set_fs(old_fs);
 147
 148        return ret;
 149}
 150EXPORT_SYMBOL_GPL(probe_user_write);
 151
 152/**
 153 * strncpy_from_unsafe: - Copy a NUL terminated string from unsafe address.
 154 * @dst:   Destination address, in kernel space.  This buffer must be at
 155 *         least @count bytes long.
 156 * @unsafe_addr: Unsafe address.
 157 * @count: Maximum number of bytes to copy, including the trailing NUL.
 158 *
 159 * Copies a NUL-terminated string from unsafe address to kernel buffer.
 160 *
 161 * On success, returns the length of the string INCLUDING the trailing NUL.
 162 *
 163 * If access fails, returns -EFAULT (some data may have been copied
 164 * and the trailing NUL added).
 165 *
 166 * If @count is smaller than the length of the string, copies @count-1 bytes,
 167 * sets the last byte of @dst buffer to NUL and returns @count.
 168 *
 169 * strncpy_from_unsafe_strict() is the same as strncpy_from_unsafe() except
 170 * for the case where architectures have non-overlapping user and kernel address
 171 * ranges: strncpy_from_unsafe_strict() will additionally return -EFAULT for
 172 * probing memory on a user address range where strncpy_from_unsafe_user() is
 173 * supposed to be used instead.
 174 */
 175
 176long __weak strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count)
 177    __attribute__((alias("__strncpy_from_unsafe")));
 178
 179long __weak strncpy_from_unsafe_strict(char *dst, const void *unsafe_addr,
 180                                       long count)
 181    __attribute__((alias("__strncpy_from_unsafe")));
 182
 183long __strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count)
 184{
 185        mm_segment_t old_fs = get_fs();
 186        const void *src = unsafe_addr;
 187        long ret;
 188
 189        if (unlikely(count <= 0))
 190                return 0;
 191
 192        set_fs(KERNEL_DS);
 193        pagefault_disable();
 194
 195        do {
 196                ret = __get_user(*dst++, (const char __user __force *)src++);
 197        } while (dst[-1] && ret == 0 && src - unsafe_addr < count);
 198
 199        dst[-1] = '\0';
 200        pagefault_enable();
 201        set_fs(old_fs);
 202
 203        return ret ? -EFAULT : src - unsafe_addr;
 204}
 205
 206/**
 207 * strncpy_from_unsafe_user: - Copy a NUL terminated string from unsafe user
 208 *                              address.
 209 * @dst:   Destination address, in kernel space.  This buffer must be at
 210 *         least @count bytes long.
 211 * @unsafe_addr: Unsafe user address.
 212 * @count: Maximum number of bytes to copy, including the trailing NUL.
 213 *
 214 * Copies a NUL-terminated string from unsafe user address to kernel buffer.
 215 *
 216 * On success, returns the length of the string INCLUDING the trailing NUL.
 217 *
 218 * If access fails, returns -EFAULT (some data may have been copied
 219 * and the trailing NUL added).
 220 *
 221 * If @count is smaller than the length of the string, copies @count-1 bytes,
 222 * sets the last byte of @dst buffer to NUL and returns @count.
 223 */
 224long strncpy_from_unsafe_user(char *dst, const void __user *unsafe_addr,
 225                              long count)
 226{
 227        mm_segment_t old_fs = get_fs();
 228        long ret;
 229
 230        if (unlikely(count <= 0))
 231                return 0;
 232
 233        set_fs(USER_DS);
 234        pagefault_disable();
 235        ret = strncpy_from_user(dst, unsafe_addr, count);
 236        pagefault_enable();
 237        set_fs(old_fs);
 238
 239        if (ret >= count) {
 240                ret = count;
 241                dst[ret - 1] = '\0';
 242        } else if (ret > 0) {
 243                ret++;
 244        }
 245
 246        return ret;
 247}
 248
 249/**
 250 * strnlen_unsafe_user: - Get the size of a user string INCLUDING final NUL.
 251 * @unsafe_addr: The string to measure.
 252 * @count: Maximum count (including NUL)
 253 *
 254 * Get the size of a NUL-terminated string in user space without pagefault.
 255 *
 256 * Returns the size of the string INCLUDING the terminating NUL.
 257 *
 258 * If the string is too long, returns a number larger than @count. User
 259 * has to check the return value against "> count".
 260 * On exception (or invalid count), returns 0.
 261 *
 262 * Unlike strnlen_user, this can be used from IRQ handler etc. because
 263 * it disables pagefaults.
 264 */
 265long strnlen_unsafe_user(const void __user *unsafe_addr, long count)
 266{
 267        mm_segment_t old_fs = get_fs();
 268        int ret;
 269
 270        set_fs(USER_DS);
 271        pagefault_disable();
 272        ret = strnlen_user(unsafe_addr, count);
 273        pagefault_enable();
 274        set_fs(old_fs);
 275
 276        return ret;
 277}
 278