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 */ 23static 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 54byte_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 */ 99long 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} 114EXPORT_SYMBOL(strncpy_from_user); 115