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