Commit dbb7ee0e authored by Alexei Starovoitov's avatar Alexei Starovoitov Committed by David S. Miller

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: default avatarFengguang Wu <fengguang.wu@intel.com>
Reported-by: default avatarGuenter Roeck <linux@roeck-us.net>
Fixes: 1a6877b9 ("lib: introduce strncpy_from_unsafe()")
Signed-off-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9dc30648
...@@ -112,44 +112,3 @@ long strncpy_from_user(char *dst, const char __user *src, long count) ...@@ -112,44 +112,3 @@ long strncpy_from_user(char *dst, const char __user *src, long count)
return -EFAULT; return -EFAULT;
} }
EXPORT_SYMBOL(strncpy_from_user); EXPORT_SYMBOL(strncpy_from_user);
/**
* strncpy_from_unsafe: - Copy a NUL terminated string from unsafe address.
* @dst: Destination address, in kernel space. This buffer must be at
* least @count bytes long.
* @src: Unsafe address.
* @count: Maximum number of bytes to copy, including the trailing NUL.
*
* Copies a NUL-terminated string from unsafe address to kernel buffer.
*
* On success, returns the length of the string INCLUDING the trailing NUL.
*
* If access fails, returns -EFAULT (some data may have been copied
* and the trailing NUL added).
*
* If @count is smaller than the length of the string, copies @count-1 bytes,
* sets the last byte of @dst buffer to NUL and returns @count.
*/
long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count)
{
mm_segment_t old_fs = get_fs();
const void *src = unsafe_addr;
long ret;
if (unlikely(count <= 0))
return 0;
set_fs(KERNEL_DS);
pagefault_disable();
do {
ret = __copy_from_user_inatomic(dst++,
(const void __user __force *)src++, 1);
} while (dst[-1] && ret == 0 && src - unsafe_addr < count);
dst[-1] = '\0';
pagefault_enable();
set_fs(old_fs);
return ret < 0 ? ret : src - unsafe_addr;
}
...@@ -60,3 +60,44 @@ long __probe_kernel_write(void *dst, const void *src, size_t size) ...@@ -60,3 +60,44 @@ long __probe_kernel_write(void *dst, const void *src, size_t size)
return ret ? -EFAULT : 0; return ret ? -EFAULT : 0;
} }
EXPORT_SYMBOL_GPL(probe_kernel_write); EXPORT_SYMBOL_GPL(probe_kernel_write);
/**
* strncpy_from_unsafe: - Copy a NUL terminated string from unsafe address.
* @dst: Destination address, in kernel space. This buffer must be at
* least @count bytes long.
* @src: Unsafe address.
* @count: Maximum number of bytes to copy, including the trailing NUL.
*
* Copies a NUL-terminated string from unsafe address to kernel buffer.
*
* On success, returns the length of the string INCLUDING the trailing NUL.
*
* If access fails, returns -EFAULT (some data may have been copied
* and the trailing NUL added).
*
* If @count is smaller than the length of the string, copies @count-1 bytes,
* sets the last byte of @dst buffer to NUL and returns @count.
*/
long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count)
{
mm_segment_t old_fs = get_fs();
const void *src = unsafe_addr;
long ret;
if (unlikely(count <= 0))
return 0;
set_fs(KERNEL_DS);
pagefault_disable();
do {
ret = __copy_from_user_inatomic(dst++,
(const void __user __force *)src++, 1);
} while (dst[-1] && ret == 0 && src - unsafe_addr < count);
dst[-1] = '\0';
pagefault_enable();
set_fs(old_fs);
return ret < 0 ? ret : src - unsafe_addr;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment