VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
b24413180f560 (Greg Kroah-Hartman   2017-11-01 15:07:57 +0100   1) // SPDX-License-Identifier: GPL-2.0
bf3c2d6d2f964 (Rasmus Villemoes     2015-02-12 15:03:16 -0800   2) #include <linux/compiler.h>
bf3c2d6d2f964 (Rasmus Villemoes     2015-02-12 15:03:16 -0800   3) #include <linux/export.h>
4d0e9df5e43db (Albert van der Linde 2020-10-15 20:13:50 -0700   4) #include <linux/fault-inject-usercopy.h>
1771c6e1a567e (Andrey Ryabinin      2016-05-20 16:59:31 -0700   5) #include <linux/kasan-checks.h>
bf90e56e467ed (Mark Rutland         2016-10-11 13:51:27 -0700   6) #include <linux/thread_info.h>
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700   7) #include <linux/uaccess.h>
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700   8) #include <linux/kernel.h>
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700   9) #include <linux/errno.h>
903f433f8f7a3 (Andrey Konovalov     2019-09-25 16:48:27 -0700  10) #include <linux/mm.h>
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  11) 
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  12) #include <asm/byteorder.h>
36126f8f2ed81 (Linus Torvalds       2012-05-26 10:43:17 -0700  13) #include <asm/word-at-a-time.h>
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  14) 
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  15) #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  16) #define IS_UNALIGNED(src, dst)	0
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  17) #else
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  18) #define IS_UNALIGNED(src, dst)	\
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  19) 	(((long) dst | (long) src) & (sizeof(long) - 1))
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  20) #endif
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  21) 
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  22) /*
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  23)  * Do a strncpy, return length of string without final '\0'.
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  24)  * 'count' is the user-supplied count (return 'count' if we
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  25)  * hit it), 'max' is the address space maximum (and we return
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  26)  * -EFAULT if we hit it).
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  27)  */
29da93fea3ea3 (Peter Zijlstra       2019-04-24 09:19:25 +0200  28) static inline long do_strncpy_from_user(char *dst, const char __user *src,
29da93fea3ea3 (Peter Zijlstra       2019-04-24 09:19:25 +0200  29) 					unsigned long count, unsigned long max)
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  30) {
36126f8f2ed81 (Linus Torvalds       2012-05-26 10:43:17 -0700  31) 	const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
29da93fea3ea3 (Peter Zijlstra       2019-04-24 09:19:25 +0200  32) 	unsigned long res = 0;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  33) 
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  34) 	if (IS_UNALIGNED(src, dst))
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  35) 		goto byte_at_a_time;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  36) 
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  37) 	while (max >= sizeof(unsigned long)) {
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  38) 		unsigned long c, data, mask;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  39) 
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  40) 		/* Fall back to byte-at-a-time if we get a page fault */
1bd4403d86a1c (Linus Torvalds       2016-08-08 13:02:01 -0700  41) 		unsafe_get_user(c, (unsigned long __user *)(src+res), byte_at_a_time);
1bd4403d86a1c (Linus Torvalds       2016-08-08 13:02:01 -0700  42) 
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  43) 		/*
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  44) 		 * Note that we mask out the bytes following the NUL. This is
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  45) 		 * important to do because string oblivious code may read past
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  46) 		 * the NUL. For those routines, we don't want to give them
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  47) 		 * potentially random bytes after the NUL in `src`.
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  48) 		 *
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  49) 		 * One example of such code is BPF map keys. BPF treats map keys
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  50) 		 * as an opaque set of bytes. Without the post-NUL mask, any BPF
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  51) 		 * maps keyed by strings returned from strncpy_from_user() may
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  52) 		 * have multiple entries for semantically identical strings.
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  53) 		 */
36126f8f2ed81 (Linus Torvalds       2012-05-26 10:43:17 -0700  54) 		if (has_zero(c, &data, &constants)) {
36126f8f2ed81 (Linus Torvalds       2012-05-26 10:43:17 -0700  55) 			data = prep_zero_mask(c, data, &constants);
36126f8f2ed81 (Linus Torvalds       2012-05-26 10:43:17 -0700  56) 			data = create_zero_mask(data);
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  57) 			mask = zero_bytemask(data);
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  58) 			*(unsigned long *)(dst+res) = c & mask;
36126f8f2ed81 (Linus Torvalds       2012-05-26 10:43:17 -0700  59) 			return res + find_zero(data);
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  60) 		}
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  61) 
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  62) 		*(unsigned long *)(dst+res) = c;
6fa6d28051e9f (Daniel Xu            2020-11-17 12:05:45 -0800  63) 
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  64) 		res += sizeof(unsigned long);
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  65) 		max -= sizeof(unsigned long);
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  66) 	}
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  67) 
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  68) byte_at_a_time:
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  69) 	while (max) {
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  70) 		char c;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  71) 
1bd4403d86a1c (Linus Torvalds       2016-08-08 13:02:01 -0700  72) 		unsafe_get_user(c,src+res, efault);
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  73) 		dst[res] = c;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  74) 		if (!c)
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  75) 			return res;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  76) 		res++;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  77) 		max--;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  78) 	}
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  79) 
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  80) 	/*
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  81) 	 * Uhhuh. We hit 'max'. But was that the user-specified maximum
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  82) 	 * too? If so, that's ok - we got as much as the user asked for.
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  83) 	 */
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  84) 	if (res >= count)
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  85) 		return res;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  86) 
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  87) 	/*
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  88) 	 * Nope: we hit the address space limit, and we still had more
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  89) 	 * characters the caller would have wanted. That's an EFAULT.
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  90) 	 */
1bd4403d86a1c (Linus Torvalds       2016-08-08 13:02:01 -0700  91) efault:
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  92) 	return -EFAULT;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  93) }
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  94) 
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  95) /**
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  96)  * strncpy_from_user: - Copy a NUL terminated string from userspace.
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  97)  * @dst:   Destination address, in kernel space.  This buffer must be at
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  98)  *         least @count bytes long.
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700  99)  * @src:   Source address, in user space.
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 100)  * @count: Maximum number of bytes to copy, including the trailing NUL.
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 101)  *
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 102)  * Copies a NUL-terminated string from userspace to kernel space.
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 103)  *
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 104)  * On success, returns the length of the string (not including the trailing
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 105)  * NUL).
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 106)  *
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 107)  * If access to userspace fails, returns -EFAULT (some data may have been
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 108)  * copied).
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 109)  *
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 110)  * If @count is smaller than the length of the string, copies @count bytes
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 111)  * and returns @count.
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 112)  */
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 113) long strncpy_from_user(char *dst, const char __user *src, long count)
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 114) {
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 115) 	unsigned long max_addr, src_addr;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 116) 
07887358993d4 (KP Singh             2020-06-04 16:50:11 -0700 117) 	might_fault();
4d0e9df5e43db (Albert van der Linde 2020-10-15 20:13:50 -0700 118) 	if (should_fail_usercopy())
4d0e9df5e43db (Albert van der Linde 2020-10-15 20:13:50 -0700 119) 		return -EFAULT;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 120) 	if (unlikely(count <= 0))
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 121) 		return 0;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 122) 
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 123) 	max_addr = user_addr_max();
903f433f8f7a3 (Andrey Konovalov     2019-09-25 16:48:27 -0700 124) 	src_addr = (unsigned long)untagged_addr(src);
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 125) 	if (likely(src_addr < max_addr)) {
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 126) 		unsigned long max = max_addr - src_addr;
9fd4470ff4974 (Linus Torvalds       2015-12-17 10:05:19 -0800 127) 		long retval;
9fd4470ff4974 (Linus Torvalds       2015-12-17 10:05:19 -0800 128) 
ab10ae1c3bef5 (Christophe Leroy     2020-01-23 08:34:18 +0000 129) 		/*
ab10ae1c3bef5 (Christophe Leroy     2020-01-23 08:34:18 +0000 130) 		 * Truncate 'max' to the user-specified limit, so that
ab10ae1c3bef5 (Christophe Leroy     2020-01-23 08:34:18 +0000 131) 		 * we only have one limit we need to check in the loop
ab10ae1c3bef5 (Christophe Leroy     2020-01-23 08:34:18 +0000 132) 		 */
ab10ae1c3bef5 (Christophe Leroy     2020-01-23 08:34:18 +0000 133) 		if (max > count)
ab10ae1c3bef5 (Christophe Leroy     2020-01-23 08:34:18 +0000 134) 			max = count;
ab10ae1c3bef5 (Christophe Leroy     2020-01-23 08:34:18 +0000 135) 
1771c6e1a567e (Andrey Ryabinin      2016-05-20 16:59:31 -0700 136) 		kasan_check_write(dst, count);
bf90e56e467ed (Mark Rutland         2016-10-11 13:51:27 -0700 137) 		check_object_size(dst, count, false);
41cd780524674 (Christophe Leroy     2020-04-03 07:20:51 +0000 138) 		if (user_read_access_begin(src, max)) {
594cc251fdd0d (Linus Torvalds       2019-01-04 12:56:09 -0800 139) 			retval = do_strncpy_from_user(dst, src, count, max);
41cd780524674 (Christophe Leroy     2020-04-03 07:20:51 +0000 140) 			user_read_access_end();
594cc251fdd0d (Linus Torvalds       2019-01-04 12:56:09 -0800 141) 			return retval;
594cc251fdd0d (Linus Torvalds       2019-01-04 12:56:09 -0800 142) 		}
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 143) 	}
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 144) 	return -EFAULT;
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 145) }
2922585b93294 (David S. Miller      2012-05-24 13:12:28 -0700 146) EXPORT_SYMBOL(strncpy_from_user);