^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Access kernel or user memory without faulting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #ifdef HAVE_GET_KERNEL_NOFAULT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define copy_from_kernel_nofault_loop(dst, src, len, type, err_label) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) while (len >= sizeof(type)) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) __get_kernel_nofault(dst, src, type, err_label); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) dst += sizeof(type); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) src += sizeof(type); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) len -= sizeof(type); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) long copy_from_kernel_nofault(void *dst, const void *src, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if (!copy_from_kernel_nofault_allowed(src, size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) pagefault_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) copy_from_kernel_nofault_loop(dst, src, size, u64, Efault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) copy_from_kernel_nofault_loop(dst, src, size, u32, Efault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) copy_from_kernel_nofault_loop(dst, src, size, u16, Efault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) copy_from_kernel_nofault_loop(dst, src, size, u8, Efault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) pagefault_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) Efault:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) pagefault_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) EXPORT_SYMBOL_GPL(copy_from_kernel_nofault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define copy_to_kernel_nofault_loop(dst, src, len, type, err_label) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) while (len >= sizeof(type)) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) __put_kernel_nofault(dst, src, type, err_label); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) dst += sizeof(type); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) src += sizeof(type); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) len -= sizeof(type); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) long copy_to_kernel_nofault(void *dst, const void *src, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) pagefault_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) copy_to_kernel_nofault_loop(dst, src, size, u64, Efault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) copy_to_kernel_nofault_loop(dst, src, size, u32, Efault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) copy_to_kernel_nofault_loop(dst, src, size, u16, Efault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) copy_to_kernel_nofault_loop(dst, src, size, u8, Efault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) pagefault_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) Efault:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) pagefault_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) const void *src = unsafe_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (unlikely(count <= 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (!copy_from_kernel_nofault_allowed(unsafe_addr, count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) pagefault_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) __get_kernel_nofault(dst, src, u8, Efault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) dst++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) src++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) } while (dst[-1] && src - unsafe_addr < count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) pagefault_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) dst[-1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return src - unsafe_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) Efault:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) pagefault_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) dst[-1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #else /* HAVE_GET_KERNEL_NOFAULT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * copy_from_kernel_nofault(): safely attempt to read from kernel-space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * @dst: pointer to the buffer that shall take the data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * @src: address to read from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * @size: size of the data chunk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * Safely read from kernel address @src to the buffer at @dst. If a kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * fault happens, handle that and return -EFAULT. If @src is not a valid kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * address, return -ERANGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * We ensure that the copy_from_user is executed in atomic context so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * do_page_fault() doesn't attempt to take mmap_lock. This makes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * copy_from_kernel_nofault() suitable for use within regions where the caller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * already holds mmap_lock, or other locks which nest inside mmap_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) long copy_from_kernel_nofault(void *dst, const void *src, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) mm_segment_t old_fs = get_fs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (!copy_from_kernel_nofault_allowed(src, size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) set_fs(KERNEL_DS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) pagefault_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ret = __copy_from_user_inatomic(dst, (__force const void __user *)src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) pagefault_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) set_fs(old_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) EXPORT_SYMBOL_GPL(copy_from_kernel_nofault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * copy_to_kernel_nofault(): safely attempt to write to a location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * @dst: address to write to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * @src: pointer to the data that shall be written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * @size: size of the data chunk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * Safely write to address @dst from the buffer at @src. If a kernel fault
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * happens, handle that and return -EFAULT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) long copy_to_kernel_nofault(void *dst, const void *src, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) mm_segment_t old_fs = get_fs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) set_fs(KERNEL_DS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) pagefault_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ret = __copy_to_user_inatomic((__force void __user *)dst, src, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) pagefault_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) set_fs(old_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * strncpy_from_kernel_nofault: - Copy a NUL terminated string from unsafe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * @dst: Destination address, in kernel space. This buffer must be at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * least @count bytes long.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * @unsafe_addr: Unsafe address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * @count: Maximum number of bytes to copy, including the trailing NUL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * Copies a NUL-terminated string from unsafe address to kernel buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * On success, returns the length of the string INCLUDING the trailing NUL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * If access fails, returns -EFAULT (some data may have been copied and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * trailing NUL added). If @unsafe_addr is not a valid kernel address, return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * -ERANGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * If @count is smaller than the length of the string, copies @count-1 bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * sets the last byte of @dst buffer to NUL and returns @count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) mm_segment_t old_fs = get_fs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) const void *src = unsafe_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (unlikely(count <= 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (!copy_from_kernel_nofault_allowed(unsafe_addr, count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) set_fs(KERNEL_DS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) pagefault_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ret = __get_user(*dst++, (const char __user __force *)src++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) } while (dst[-1] && ret == 0 && src - unsafe_addr < count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) dst[-1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) pagefault_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) set_fs(old_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return ret ? -EFAULT : src - unsafe_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #endif /* HAVE_GET_KERNEL_NOFAULT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * copy_from_user_nofault(): safely attempt to read from a user-space location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * @dst: pointer to the buffer that shall take the data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * @src: address to read from. This must be a user address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * @size: size of the data chunk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * Safely read from user address @src to the buffer at @dst. If a kernel fault
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * happens, handle that and return -EFAULT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) long copy_from_user_nofault(void *dst, const void __user *src, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) long ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) mm_segment_t old_fs = force_uaccess_begin();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (access_ok(src, size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) pagefault_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ret = __copy_from_user_inatomic(dst, src, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) pagefault_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) force_uaccess_end(old_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) EXPORT_SYMBOL_GPL(copy_from_user_nofault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * copy_to_user_nofault(): safely attempt to write to a user-space location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * @dst: address to write to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * @src: pointer to the data that shall be written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * @size: size of the data chunk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * Safely write to address @dst from the buffer at @src. If a kernel fault
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * happens, handle that and return -EFAULT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) long copy_to_user_nofault(void __user *dst, const void *src, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) long ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) mm_segment_t old_fs = force_uaccess_begin();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (access_ok(dst, size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) pagefault_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ret = __copy_to_user_inatomic(dst, src, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) pagefault_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) force_uaccess_end(old_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) EXPORT_SYMBOL_GPL(copy_to_user_nofault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * strncpy_from_user_nofault: - Copy a NUL terminated string from unsafe user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * @dst: Destination address, in kernel space. This buffer must be at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * least @count bytes long.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * @unsafe_addr: Unsafe user address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * @count: Maximum number of bytes to copy, including the trailing NUL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * Copies a NUL-terminated string from unsafe user address to kernel buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * On success, returns the length of the string INCLUDING the trailing NUL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * If access fails, returns -EFAULT (some data may have been copied
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * and the trailing NUL added).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * If @count is smaller than the length of the string, copies @count-1 bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * sets the last byte of @dst buffer to NUL and returns @count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) long strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) long count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) mm_segment_t old_fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (unlikely(count <= 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) old_fs = force_uaccess_begin();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) pagefault_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ret = strncpy_from_user(dst, unsafe_addr, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) pagefault_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) force_uaccess_end(old_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (ret >= count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ret = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) dst[ret - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) } else if (ret > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ret++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * strnlen_user_nofault: - Get the size of a user string INCLUDING final NUL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * @unsafe_addr: The string to measure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * @count: Maximum count (including NUL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * Get the size of a NUL-terminated string in user space without pagefault.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * Returns the size of the string INCLUDING the terminating NUL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * If the string is too long, returns a number larger than @count. User
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * has to check the return value against "> count".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * On exception (or invalid count), returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * Unlike strnlen_user, this can be used from IRQ handler etc. because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * it disables pagefaults.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) long strnlen_user_nofault(const void __user *unsafe_addr, long count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) mm_segment_t old_fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) old_fs = force_uaccess_begin();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) pagefault_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ret = strnlen_user(unsafe_addr, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) pagefault_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) force_uaccess_end(old_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }