1
2
3
4#include <linux/export.h>
5#include <linux/mm.h>
6#include <linux/uaccess.h>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23long __weak probe_kernel_read(void *dst, const void *src, size_t size)
24 __attribute__((alias("__probe_kernel_read")));
25
26long __probe_kernel_read(void *dst, const void *src, size_t size)
27{
28 long ret;
29 mm_segment_t old_fs = get_fs();
30
31 set_fs(KERNEL_DS);
32 pagefault_disable();
33 ret = __copy_from_user_inatomic(dst,
34 (__force const void __user *)src, size);
35 pagefault_enable();
36 set_fs(old_fs);
37
38 return ret ? -EFAULT : 0;
39}
40EXPORT_SYMBOL_GPL(probe_kernel_read);
41
42
43
44
45
46
47
48
49
50
51long __weak probe_kernel_write(void *dst, const void *src, size_t size)
52 __attribute__((alias("__probe_kernel_write")));
53
54long __probe_kernel_write(void *dst, const void *src, size_t size)
55{
56 long ret;
57 mm_segment_t old_fs = get_fs();
58
59 set_fs(KERNEL_DS);
60 pagefault_disable();
61 ret = __copy_to_user_inatomic((__force void __user *)dst, src, size);
62 pagefault_enable();
63 set_fs(old_fs);
64
65 return ret ? -EFAULT : 0;
66}
67EXPORT_SYMBOL_GPL(probe_kernel_write);
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count)
87{
88 mm_segment_t old_fs = get_fs();
89 const void *src = unsafe_addr;
90 long ret;
91
92 if (unlikely(count <= 0))
93 return 0;
94
95 set_fs(KERNEL_DS);
96 pagefault_disable();
97
98 do {
99 ret = __get_user(*dst++, (const char __user __force *)src++);
100 } while (dst[-1] && ret == 0 && src - unsafe_addr < count);
101
102 dst[-1] = '\0';
103 pagefault_enable();
104 set_fs(old_fs);
105
106 return ret ? -EFAULT : src - unsafe_addr;
107}
108