1 #include <linux/compiler.h> 2 #include <linux/export.h> 3 #include <linux/uaccess.h> 4 #include <linux/kernel.h> 5 #include <linux/errno.h> 6 7 #include <asm/byteorder.h> 8 #include <asm/word-at-a-time.h> 9 10 #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 11 #define IS_UNALIGNED(src, dst) 0 12 #else 13 #define IS_UNALIGNED(src, dst) \ 14 (((long) dst | (long) src) & (sizeof(long) - 1)) 15 #endif 16 17 /* 18 * Do a strncpy, return length of string without final '\0'. 19 * 'count' is the user-supplied count (return 'count' if we 20 * hit it), 'max' is the address space maximum (and we return 21 * -EFAULT if we hit it). 22 */ 23 static inline long do_strncpy_from_user(char *dst, const char __user *src, long count, unsigned long max) 24 { 25 const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; 26 long res = 0; 27 28 /* 29 * Truncate 'max' to the user-specified limit, so that 30 * we only have one limit we need to check in the loop 31 */ 32 if (max > count) 33 max = count; 34 35 if (IS_UNALIGNED(src, dst)) 36 goto byte_at_a_time; 37 38 while (max >= sizeof(unsigned long)) { 39 unsigned long c, data; 40 41 /* Fall back to byte-at-a-time if we get a page fault */ 42 if (unlikely(__get_user(c,(unsigned long __user *)(src+res)))) 43 break; 44 *(unsigned long *)(dst+res) = c; 45 if (has_zero(c, &data, &constants)) { 46 data = prep_zero_mask(c, data, &constants); 47 data = create_zero_mask(data); 48 return res + find_zero(data); 49 } 50 res += sizeof(unsigned long); 51 max -= sizeof(unsigned long); 52 } 53 54 byte_at_a_time: 55 while (max) { 56 char c; 57 58 if (unlikely(__get_user(c,src+res))) 59 return -EFAULT; 60 dst[res] = c; 61 if (!c) 62 return res; 63 res++; 64 max--; 65 } 66 67 /* 68 * Uhhuh. We hit 'max'. But was that the user-specified maximum 69 * too? If so, that's ok - we got as much as the user asked for. 70 */ 71 if (res >= count) 72 return res; 73 74 /* 75 * Nope: we hit the address space limit, and we still had more 76 * characters the caller would have wanted. That's an EFAULT. 77 */ 78 return -EFAULT; 79 } 80 81 /** 82 * strncpy_from_user: - Copy a NUL terminated string from userspace. 83 * @dst: Destination address, in kernel space. This buffer must be at 84 * least @count bytes long. 85 * @src: Source address, in user space. 86 * @count: Maximum number of bytes to copy, including the trailing NUL. 87 * 88 * Copies a NUL-terminated string from userspace to kernel space. 89 * 90 * On success, returns the length of the string (not including the trailing 91 * NUL). 92 * 93 * If access to userspace fails, returns -EFAULT (some data may have been 94 * copied). 95 * 96 * If @count is smaller than the length of the string, copies @count bytes 97 * and returns @count. 98 */ 99 long strncpy_from_user(char *dst, const char __user *src, long count) 100 { 101 unsigned long max_addr, src_addr; 102 103 if (unlikely(count <= 0)) 104 return 0; 105 106 max_addr = user_addr_max(); 107 src_addr = (unsigned long)src; 108 if (likely(src_addr < max_addr)) { 109 unsigned long max = max_addr - src_addr; 110 return do_strncpy_from_user(dst, src, count, max); 111 } 112 return -EFAULT; 113 } 114 EXPORT_SYMBOL(strncpy_from_user); 115