diff options
author | Alexei Starovoitov <ast@plumgrid.com> | 2015-08-31 11:57:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-31 15:36:10 -0400 |
commit | dbb7ee0e474cc8221de55583f516275693c5b552 (patch) | |
tree | 1b3a02e7a92051b57922775bbbd977e69ddcbd2d /mm/maccess.c | |
parent | 9dc30648f0708cf063e29470d83f63f8dc8fc430 (diff) |
lib: move strncpy_from_unsafe() into mm/maccess.c
To fix build errors:
kernel/built-in.o: In function `bpf_trace_printk':
bpf_trace.c:(.text+0x11a254): undefined reference to `strncpy_from_unsafe'
kernel/built-in.o: In function `fetch_memory_string':
trace_kprobe.c:(.text+0x11acf8): undefined reference to `strncpy_from_unsafe'
move strncpy_from_unsafe() next to probe_kernel_read/write()
which use the same memory access style.
Reported-by: Fengguang Wu <fengguang.wu@intel.com>
Reported-by: Guenter Roeck <linux@roeck-us.net>
Fixes: 1a6877b9c0c2 ("lib: introduce strncpy_from_unsafe()")
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'mm/maccess.c')
-rw-r--r-- | mm/maccess.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/mm/maccess.c b/mm/maccess.c index d53adf9ba84b..34fe24759ed1 100644 --- a/mm/maccess.c +++ b/mm/maccess.c | |||
@@ -60,3 +60,44 @@ long __probe_kernel_write(void *dst, const void *src, size_t size) | |||
60 | return ret ? -EFAULT : 0; | 60 | return ret ? -EFAULT : 0; |
61 | } | 61 | } |
62 | EXPORT_SYMBOL_GPL(probe_kernel_write); | 62 | EXPORT_SYMBOL_GPL(probe_kernel_write); |
63 | |||
64 | /** | ||
65 | * strncpy_from_unsafe: - Copy a NUL terminated string from unsafe address. | ||
66 | * @dst: Destination address, in kernel space. This buffer must be at | ||
67 | * least @count bytes long. | ||
68 | * @src: Unsafe address. | ||
69 | * @count: Maximum number of bytes to copy, including the trailing NUL. | ||
70 | * | ||
71 | * Copies a NUL-terminated string from unsafe address to kernel buffer. | ||
72 | * | ||
73 | * On success, returns the length of the string INCLUDING the trailing NUL. | ||
74 | * | ||
75 | * If access fails, returns -EFAULT (some data may have been copied | ||
76 | * and the trailing NUL added). | ||
77 | * | ||
78 | * If @count is smaller than the length of the string, copies @count-1 bytes, | ||
79 | * sets the last byte of @dst buffer to NUL and returns @count. | ||
80 | */ | ||
81 | long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count) | ||
82 | { | ||
83 | mm_segment_t old_fs = get_fs(); | ||
84 | const void *src = unsafe_addr; | ||
85 | long ret; | ||
86 | |||
87 | if (unlikely(count <= 0)) | ||
88 | return 0; | ||
89 | |||
90 | set_fs(KERNEL_DS); | ||
91 | pagefault_disable(); | ||
92 | |||
93 | do { | ||
94 | ret = __copy_from_user_inatomic(dst++, | ||
95 | (const void __user __force *)src++, 1); | ||
96 | } while (dst[-1] && ret == 0 && src - unsafe_addr < count); | ||
97 | |||
98 | dst[-1] = '\0'; | ||
99 | pagefault_enable(); | ||
100 | set_fs(old_fs); | ||
101 | |||
102 | return ret < 0 ? ret : src - unsafe_addr; | ||
103 | } | ||