Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Access kernel or user memory without faulting.
0004  */
0005 #include <linux/export.h>
0006 #include <linux/mm.h>
0007 #include <linux/uaccess.h>
0008 
0009 bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src,
0010         size_t size)
0011 {
0012     return true;
0013 }
0014 
0015 #define copy_from_kernel_nofault_loop(dst, src, len, type, err_label)   \
0016     while (len >= sizeof(type)) {                   \
0017         __get_kernel_nofault(dst, src, type, err_label);        \
0018         dst += sizeof(type);                    \
0019         src += sizeof(type);                    \
0020         len -= sizeof(type);                    \
0021     }
0022 
0023 long copy_from_kernel_nofault(void *dst, const void *src, size_t size)
0024 {
0025     unsigned long align = 0;
0026 
0027     if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
0028         align = (unsigned long)dst | (unsigned long)src;
0029 
0030     if (!copy_from_kernel_nofault_allowed(src, size))
0031         return -ERANGE;
0032 
0033     pagefault_disable();
0034     if (!(align & 7))
0035         copy_from_kernel_nofault_loop(dst, src, size, u64, Efault);
0036     if (!(align & 3))
0037         copy_from_kernel_nofault_loop(dst, src, size, u32, Efault);
0038     if (!(align & 1))
0039         copy_from_kernel_nofault_loop(dst, src, size, u16, Efault);
0040     copy_from_kernel_nofault_loop(dst, src, size, u8, Efault);
0041     pagefault_enable();
0042     return 0;
0043 Efault:
0044     pagefault_enable();
0045     return -EFAULT;
0046 }
0047 EXPORT_SYMBOL_GPL(copy_from_kernel_nofault);
0048 
0049 #define copy_to_kernel_nofault_loop(dst, src, len, type, err_label) \
0050     while (len >= sizeof(type)) {                   \
0051         __put_kernel_nofault(dst, src, type, err_label);        \
0052         dst += sizeof(type);                    \
0053         src += sizeof(type);                    \
0054         len -= sizeof(type);                    \
0055     }
0056 
0057 long copy_to_kernel_nofault(void *dst, const void *src, size_t size)
0058 {
0059     unsigned long align = 0;
0060 
0061     if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
0062         align = (unsigned long)dst | (unsigned long)src;
0063 
0064     pagefault_disable();
0065     if (!(align & 7))
0066         copy_to_kernel_nofault_loop(dst, src, size, u64, Efault);
0067     if (!(align & 3))
0068         copy_to_kernel_nofault_loop(dst, src, size, u32, Efault);
0069     if (!(align & 1))
0070         copy_to_kernel_nofault_loop(dst, src, size, u16, Efault);
0071     copy_to_kernel_nofault_loop(dst, src, size, u8, Efault);
0072     pagefault_enable();
0073     return 0;
0074 Efault:
0075     pagefault_enable();
0076     return -EFAULT;
0077 }
0078 
0079 long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
0080 {
0081     const void *src = unsafe_addr;
0082 
0083     if (unlikely(count <= 0))
0084         return 0;
0085     if (!copy_from_kernel_nofault_allowed(unsafe_addr, count))
0086         return -ERANGE;
0087 
0088     pagefault_disable();
0089     do {
0090         __get_kernel_nofault(dst, src, u8, Efault);
0091         dst++;
0092         src++;
0093     } while (dst[-1] && src - unsafe_addr < count);
0094     pagefault_enable();
0095 
0096     dst[-1] = '\0';
0097     return src - unsafe_addr;
0098 Efault:
0099     pagefault_enable();
0100     dst[-1] = '\0';
0101     return -EFAULT;
0102 }
0103 
0104 /**
0105  * copy_from_user_nofault(): safely attempt to read from a user-space location
0106  * @dst: pointer to the buffer that shall take the data
0107  * @src: address to read from. This must be a user address.
0108  * @size: size of the data chunk
0109  *
0110  * Safely read from user address @src to the buffer at @dst. If a kernel fault
0111  * happens, handle that and return -EFAULT.
0112  */
0113 long copy_from_user_nofault(void *dst, const void __user *src, size_t size)
0114 {
0115     long ret = -EFAULT;
0116     if (access_ok(src, size)) {
0117         pagefault_disable();
0118         ret = __copy_from_user_inatomic(dst, src, size);
0119         pagefault_enable();
0120     }
0121 
0122     if (ret)
0123         return -EFAULT;
0124     return 0;
0125 }
0126 EXPORT_SYMBOL_GPL(copy_from_user_nofault);
0127 
0128 /**
0129  * copy_to_user_nofault(): safely attempt to write to a user-space location
0130  * @dst: address to write to
0131  * @src: pointer to the data that shall be written
0132  * @size: size of the data chunk
0133  *
0134  * Safely write to address @dst from the buffer at @src.  If a kernel fault
0135  * happens, handle that and return -EFAULT.
0136  */
0137 long copy_to_user_nofault(void __user *dst, const void *src, size_t size)
0138 {
0139     long ret = -EFAULT;
0140 
0141     if (access_ok(dst, size)) {
0142         pagefault_disable();
0143         ret = __copy_to_user_inatomic(dst, src, size);
0144         pagefault_enable();
0145     }
0146 
0147     if (ret)
0148         return -EFAULT;
0149     return 0;
0150 }
0151 EXPORT_SYMBOL_GPL(copy_to_user_nofault);
0152 
0153 /**
0154  * strncpy_from_user_nofault: - Copy a NUL terminated string from unsafe user
0155  *              address.
0156  * @dst:   Destination address, in kernel space.  This buffer must be at
0157  *         least @count bytes long.
0158  * @unsafe_addr: Unsafe user address.
0159  * @count: Maximum number of bytes to copy, including the trailing NUL.
0160  *
0161  * Copies a NUL-terminated string from unsafe user address to kernel buffer.
0162  *
0163  * On success, returns the length of the string INCLUDING the trailing NUL.
0164  *
0165  * If access fails, returns -EFAULT (some data may have been copied
0166  * and the trailing NUL added).
0167  *
0168  * If @count is smaller than the length of the string, copies @count-1 bytes,
0169  * sets the last byte of @dst buffer to NUL and returns @count.
0170  */
0171 long strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
0172                   long count)
0173 {
0174     long ret;
0175 
0176     if (unlikely(count <= 0))
0177         return 0;
0178 
0179     pagefault_disable();
0180     ret = strncpy_from_user(dst, unsafe_addr, count);
0181     pagefault_enable();
0182 
0183     if (ret >= count) {
0184         ret = count;
0185         dst[ret - 1] = '\0';
0186     } else if (ret > 0) {
0187         ret++;
0188     }
0189 
0190     return ret;
0191 }
0192 
0193 /**
0194  * strnlen_user_nofault: - Get the size of a user string INCLUDING final NUL.
0195  * @unsafe_addr: The string to measure.
0196  * @count: Maximum count (including NUL)
0197  *
0198  * Get the size of a NUL-terminated string in user space without pagefault.
0199  *
0200  * Returns the size of the string INCLUDING the terminating NUL.
0201  *
0202  * If the string is too long, returns a number larger than @count. User
0203  * has to check the return value against "> count".
0204  * On exception (or invalid count), returns 0.
0205  *
0206  * Unlike strnlen_user, this can be used from IRQ handler etc. because
0207  * it disables pagefaults.
0208  */
0209 long strnlen_user_nofault(const void __user *unsafe_addr, long count)
0210 {
0211     int ret;
0212 
0213     pagefault_disable();
0214     ret = strnlen_user(unsafe_addr, count);
0215     pagefault_enable();
0216 
0217     return ret;
0218 }
0219 
0220 void __copy_overflow(int size, unsigned long count)
0221 {
0222     WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count);
0223 }
0224 EXPORT_SYMBOL(__copy_overflow);