| Robert Richter | 1ac2e6c | 2011-06-07 11:49:55 +0200 | [diff] [blame] | 1 | /* | 
 | 2 |  * User address space access functions. | 
 | 3 |  * | 
 | 4 |  *  For licencing details see kernel-base/COPYING | 
 | 5 |  */ | 
 | 6 |  | 
 | 7 | #include <linux/highmem.h> | 
 | 8 | #include <linux/module.h> | 
 | 9 |  | 
| Linus Torvalds | 92ae03f | 2012-04-06 14:32:32 -0700 | [diff] [blame] | 10 | #include <asm/word-at-a-time.h> | 
 | 11 |  | 
| Robert Richter | 1ac2e6c | 2011-06-07 11:49:55 +0200 | [diff] [blame] | 12 | /* | 
 | 13 |  * best effort, GUP based copy_from_user() that is NMI-safe | 
 | 14 |  */ | 
 | 15 | unsigned long | 
 | 16 | copy_from_user_nmi(void *to, const void __user *from, unsigned long n) | 
 | 17 | { | 
 | 18 | 	unsigned long offset, addr = (unsigned long)from; | 
 | 19 | 	unsigned long size, len = 0; | 
 | 20 | 	struct page *page; | 
 | 21 | 	void *map; | 
 | 22 | 	int ret; | 
 | 23 |  | 
 | 24 | 	do { | 
 | 25 | 		ret = __get_user_pages_fast(addr, 1, 0, &page); | 
 | 26 | 		if (!ret) | 
 | 27 | 			break; | 
 | 28 |  | 
 | 29 | 		offset = addr & (PAGE_SIZE - 1); | 
 | 30 | 		size = min(PAGE_SIZE - offset, n - len); | 
 | 31 |  | 
 | 32 | 		map = kmap_atomic(page); | 
 | 33 | 		memcpy(to, map+offset, size); | 
 | 34 | 		kunmap_atomic(map); | 
 | 35 | 		put_page(page); | 
 | 36 |  | 
 | 37 | 		len  += size; | 
 | 38 | 		to   += size; | 
 | 39 | 		addr += size; | 
 | 40 |  | 
 | 41 | 	} while (len < n); | 
 | 42 |  | 
 | 43 | 	return len; | 
 | 44 | } | 
 | 45 | EXPORT_SYMBOL_GPL(copy_from_user_nmi); | 
| Linus Torvalds | 92ae03f | 2012-04-06 14:32:32 -0700 | [diff] [blame] | 46 |  | 
 | 47 | static inline unsigned long count_bytes(unsigned long mask) | 
 | 48 | { | 
 | 49 | 	mask = (mask - 1) & ~mask; | 
 | 50 | 	mask >>= 7; | 
 | 51 | 	return count_masked_bytes(mask); | 
 | 52 | } | 
 | 53 |  | 
 | 54 | /* | 
 | 55 |  * Do a strncpy, return length of string without final '\0'. | 
 | 56 |  * 'count' is the user-supplied count (return 'count' if we | 
 | 57 |  * hit it), 'max' is the address space maximum (and we return | 
 | 58 |  * -EFAULT if we hit it). | 
 | 59 |  */ | 
| Linus Torvalds | 12e993b | 2012-04-15 17:23:00 -0700 | [diff] [blame] | 60 | static inline long do_strncpy_from_user(char *dst, const char __user *src, long count, unsigned long max) | 
| Linus Torvalds | 92ae03f | 2012-04-06 14:32:32 -0700 | [diff] [blame] | 61 | { | 
 | 62 | 	long res = 0; | 
 | 63 |  | 
 | 64 | 	/* | 
 | 65 | 	 * Truncate 'max' to the user-specified limit, so that | 
 | 66 | 	 * we only have one limit we need to check in the loop | 
 | 67 | 	 */ | 
 | 68 | 	if (max > count) | 
 | 69 | 		max = count; | 
 | 70 |  | 
 | 71 | 	while (max >= sizeof(unsigned long)) { | 
 | 72 | 		unsigned long c; | 
 | 73 |  | 
 | 74 | 		/* Fall back to byte-at-a-time if we get a page fault */ | 
 | 75 | 		if (unlikely(__get_user(c,(unsigned long __user *)(src+res)))) | 
 | 76 | 			break; | 
 | 77 | 		/* This can write a few bytes past the NUL character, but that's ok */ | 
 | 78 | 		*(unsigned long *)(dst+res) = c; | 
 | 79 | 		c = has_zero(c); | 
 | 80 | 		if (c) | 
 | 81 | 			return res + count_bytes(c); | 
 | 82 | 		res += sizeof(unsigned long); | 
 | 83 | 		max -= sizeof(unsigned long); | 
 | 84 | 	} | 
 | 85 |  | 
 | 86 | 	while (max) { | 
 | 87 | 		char c; | 
 | 88 |  | 
 | 89 | 		if (unlikely(__get_user(c,src+res))) | 
 | 90 | 			return -EFAULT; | 
 | 91 | 		dst[res] = c; | 
 | 92 | 		if (!c) | 
 | 93 | 			return res; | 
 | 94 | 		res++; | 
 | 95 | 		max--; | 
 | 96 | 	} | 
 | 97 |  | 
 | 98 | 	/* | 
 | 99 | 	 * Uhhuh. We hit 'max'. But was that the user-specified maximum | 
 | 100 | 	 * too? If so, that's ok - we got as much as the user asked for. | 
 | 101 | 	 */ | 
 | 102 | 	if (res >= count) | 
| Linus Torvalds | 12e993b | 2012-04-15 17:23:00 -0700 | [diff] [blame] | 103 | 		return res; | 
| Linus Torvalds | 92ae03f | 2012-04-06 14:32:32 -0700 | [diff] [blame] | 104 |  | 
 | 105 | 	/* | 
 | 106 | 	 * Nope: we hit the address space limit, and we still had more | 
 | 107 | 	 * characters the caller would have wanted. That's an EFAULT. | 
 | 108 | 	 */ | 
 | 109 | 	return -EFAULT; | 
 | 110 | } | 
 | 111 |  | 
 | 112 | /** | 
 | 113 |  * strncpy_from_user: - Copy a NUL terminated string from userspace. | 
 | 114 |  * @dst:   Destination address, in kernel space.  This buffer must be at | 
 | 115 |  *         least @count bytes long. | 
 | 116 |  * @src:   Source address, in user space. | 
 | 117 |  * @count: Maximum number of bytes to copy, including the trailing NUL. | 
 | 118 |  * | 
 | 119 |  * Copies a NUL-terminated string from userspace to kernel space. | 
 | 120 |  * | 
 | 121 |  * On success, returns the length of the string (not including the trailing | 
 | 122 |  * NUL). | 
 | 123 |  * | 
 | 124 |  * If access to userspace fails, returns -EFAULT (some data may have been | 
 | 125 |  * copied). | 
 | 126 |  * | 
 | 127 |  * If @count is smaller than the length of the string, copies @count bytes | 
 | 128 |  * and returns @count. | 
 | 129 |  */ | 
 | 130 | long | 
 | 131 | strncpy_from_user(char *dst, const char __user *src, long count) | 
 | 132 | { | 
 | 133 | 	unsigned long max_addr, src_addr; | 
 | 134 |  | 
 | 135 | 	if (unlikely(count <= 0)) | 
 | 136 | 		return 0; | 
 | 137 |  | 
 | 138 | 	max_addr = current_thread_info()->addr_limit.seg; | 
 | 139 | 	src_addr = (unsigned long)src; | 
 | 140 | 	if (likely(src_addr < max_addr)) { | 
 | 141 | 		unsigned long max = max_addr - src_addr; | 
 | 142 | 		return do_strncpy_from_user(dst, src, count, max); | 
 | 143 | 	} | 
 | 144 | 	return -EFAULT; | 
 | 145 | } | 
 | 146 | EXPORT_SYMBOL(strncpy_from_user); |