14
14
15
15
#include "trace_kprobe_selftest.h"
16
16
#include "trace_probe.h"
17
+ #include "trace_probe_tmpl.h"
17
18
18
19
#define KPROBE_EVENT_SYSTEM "kprobes"
19
20
#define KRETPROBE_MAXACTIVE_MAX 4096
@@ -120,160 +121,6 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs);
120
121
static int kretprobe_dispatcher (struct kretprobe_instance * ri ,
121
122
struct pt_regs * regs );
122
123
123
- /* Memory fetching by symbol */
124
- struct symbol_cache {
125
- char * symbol ;
126
- long offset ;
127
- unsigned long addr ;
128
- };
129
-
130
- unsigned long update_symbol_cache (struct symbol_cache * sc )
131
- {
132
- sc -> addr = (unsigned long )kallsyms_lookup_name (sc -> symbol );
133
-
134
- if (sc -> addr )
135
- sc -> addr += sc -> offset ;
136
-
137
- return sc -> addr ;
138
- }
139
-
140
- void free_symbol_cache (struct symbol_cache * sc )
141
- {
142
- kfree (sc -> symbol );
143
- kfree (sc );
144
- }
145
-
146
- struct symbol_cache * alloc_symbol_cache (const char * sym , long offset )
147
- {
148
- struct symbol_cache * sc ;
149
-
150
- if (!sym || strlen (sym ) == 0 )
151
- return NULL ;
152
-
153
- sc = kzalloc (sizeof (struct symbol_cache ), GFP_KERNEL );
154
- if (!sc )
155
- return NULL ;
156
-
157
- sc -> symbol = kstrdup (sym , GFP_KERNEL );
158
- if (!sc -> symbol ) {
159
- kfree (sc );
160
- return NULL ;
161
- }
162
- sc -> offset = offset ;
163
- update_symbol_cache (sc );
164
-
165
- return sc ;
166
- }
167
-
168
- /*
169
- * Kprobes-specific fetch functions
170
- */
171
- #define DEFINE_FETCH_stack (type ) \
172
- static void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs, \
173
- void *offset, void *dest) \
174
- { \
175
- *(type *)dest = (type)regs_get_kernel_stack_nth(regs, \
176
- (unsigned int)((unsigned long)offset)); \
177
- } \
178
- NOKPROBE_SYMBOL(FETCH_FUNC_NAME(stack, type));
179
-
180
- DEFINE_BASIC_FETCH_FUNCS (stack )
181
- /* No string on the stack entry */
182
- #define fetch_stack_string NULL
183
- #define fetch_stack_string_size NULL
184
-
185
- #define DEFINE_FETCH_memory (type ) \
186
- static void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs, \
187
- void *addr, void *dest) \
188
- { \
189
- type retval; \
190
- if (probe_kernel_address(addr, retval)) \
191
- *(type *)dest = 0; \
192
- else \
193
- *(type *)dest = retval; \
194
- } \
195
- NOKPROBE_SYMBOL(FETCH_FUNC_NAME(memory, type));
196
-
197
- DEFINE_BASIC_FETCH_FUNCS (memory )
198
- /*
199
- * Fetch a null-terminated string. Caller MUST set *(u32 *)dest with max
200
- * length and relative data location.
201
- */
202
- static void FETCH_FUNC_NAME (memory , string )(struct pt_regs * regs ,
203
- void * addr , void * dest )
204
- {
205
- int maxlen = get_rloc_len (* (u32 * )dest );
206
- u8 * dst = get_rloc_data (dest );
207
- long ret ;
208
-
209
- if (!maxlen )
210
- return ;
211
-
212
- /*
213
- * Try to get string again, since the string can be changed while
214
- * probing.
215
- */
216
- ret = strncpy_from_unsafe (dst , addr , maxlen );
217
-
218
- if (ret < 0 ) { /* Failed to fetch string */
219
- dst [0 ] = '\0' ;
220
- * (u32 * )dest = make_data_rloc (0 , get_rloc_offs (* (u32 * )dest ));
221
- } else {
222
- * (u32 * )dest = make_data_rloc (ret , get_rloc_offs (* (u32 * )dest ));
223
- }
224
- }
225
- NOKPROBE_SYMBOL (FETCH_FUNC_NAME (memory , string ));
226
-
227
- /* Return the length of string -- including null terminal byte */
228
- static void FETCH_FUNC_NAME (memory , string_size )(struct pt_regs * regs ,
229
- void * addr , void * dest )
230
- {
231
- mm_segment_t old_fs ;
232
- int ret , len = 0 ;
233
- u8 c ;
234
-
235
- old_fs = get_fs ();
236
- set_fs (KERNEL_DS );
237
- pagefault_disable ();
238
-
239
- do {
240
- ret = __copy_from_user_inatomic (& c , (u8 * )addr + len , 1 );
241
- len ++ ;
242
- } while (c && ret == 0 && len < MAX_STRING_SIZE );
243
-
244
- pagefault_enable ();
245
- set_fs (old_fs );
246
-
247
- if (ret < 0 ) /* Failed to check the length */
248
- * (u32 * )dest = 0 ;
249
- else
250
- * (u32 * )dest = len ;
251
- }
252
- NOKPROBE_SYMBOL (FETCH_FUNC_NAME (memory , string_size ));
253
-
254
- #define DEFINE_FETCH_symbol (type ) \
255
- void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs, void *data, void *dest)\
256
- { \
257
- struct symbol_cache *sc = data; \
258
- if (sc->addr) \
259
- fetch_memory_##type(regs, (void *)sc->addr, dest); \
260
- else \
261
- *(type *)dest = 0; \
262
- } \
263
- NOKPROBE_SYMBOL(FETCH_FUNC_NAME(symbol, type));
264
-
265
- DEFINE_BASIC_FETCH_FUNCS (symbol )
266
- DEFINE_FETCH_symbol (string )
267
- DEFINE_FETCH_symbol (string_size )
268
-
269
- /* kprobes don't support file_offset fetch methods */
270
- #define fetch_file_offset_u8 NULL
271
- #define fetch_file_offset_u16 NULL
272
- #define fetch_file_offset_u32 NULL
273
- #define fetch_file_offset_u64 NULL
274
- #define fetch_file_offset_string NULL
275
- #define fetch_file_offset_string_size NULL
276
-
277
124
/* Fetch type information table */
278
125
static const struct fetch_type kprobes_fetch_type_table [] = {
279
126
/* Special types */
@@ -529,7 +376,7 @@ static bool within_notrace_func(struct trace_kprobe *tk)
529
376
/* Internal register function - just handle k*probes and flags */
530
377
static int __register_trace_kprobe (struct trace_kprobe * tk )
531
378
{
532
- int i , ret ;
379
+ int ret ;
533
380
534
381
if (trace_probe_is_registered (& tk -> tp ))
535
382
return - EINVAL ;
@@ -540,9 +387,6 @@ static int __register_trace_kprobe(struct trace_kprobe *tk)
540
387
return - EINVAL ;
541
388
}
542
389
543
- for (i = 0 ; i < tk -> tp .nr_args ; i ++ )
544
- traceprobe_update_arg (& tk -> tp .args [i ]);
545
-
546
390
/* Set/clear disabled flag according to tp->flag */
547
391
if (trace_probe_is_enabled (& tk -> tp ))
548
392
tk -> rp .kp .flags &= ~KPROBE_FLAG_DISABLED ;
@@ -876,8 +720,8 @@ static int create_trace_kprobe(int argc, char **argv)
876
720
877
721
/* Parse fetch argument */
878
722
ret = traceprobe_parse_probe_arg (arg , & tk -> tp .size , parg ,
879
- is_return , true,
880
- kprobes_fetch_type_table );
723
+ is_return , true,
724
+ kprobes_fetch_type_table );
881
725
if (ret ) {
882
726
pr_info ("Parse error at argument[%d]. (%d)\n" , i , ret );
883
727
goto error ;
@@ -1031,6 +875,133 @@ static const struct file_operations kprobe_profile_ops = {
1031
875
.release = seq_release ,
1032
876
};
1033
877
878
+ /* Kprobe specific fetch functions */
879
+
880
+ /* Return the length of string -- including null terminal byte */
881
+ static nokprobe_inline void
882
+ fetch_store_strlen (unsigned long addr , void * dest )
883
+ {
884
+ mm_segment_t old_fs ;
885
+ int ret , len = 0 ;
886
+ u8 c ;
887
+
888
+ old_fs = get_fs ();
889
+ set_fs (KERNEL_DS );
890
+ pagefault_disable ();
891
+
892
+ do {
893
+ ret = __copy_from_user_inatomic (& c , (u8 * )addr + len , 1 );
894
+ len ++ ;
895
+ } while (c && ret == 0 && len < MAX_STRING_SIZE );
896
+
897
+ pagefault_enable ();
898
+ set_fs (old_fs );
899
+
900
+ if (ret < 0 ) /* Failed to check the length */
901
+ * (u32 * )dest = 0 ;
902
+ else
903
+ * (u32 * )dest = len ;
904
+ }
905
+
906
+ /*
907
+ * Fetch a null-terminated string. Caller MUST set *(u32 *)buf with max
908
+ * length and relative data location.
909
+ */
910
+ static nokprobe_inline void
911
+ fetch_store_string (unsigned long addr , void * dest )
912
+ {
913
+ int maxlen = get_rloc_len (* (u32 * )dest );
914
+ u8 * dst = get_rloc_data (dest );
915
+ long ret ;
916
+
917
+ if (!maxlen )
918
+ return ;
919
+
920
+ /*
921
+ * Try to get string again, since the string can be changed while
922
+ * probing.
923
+ */
924
+ ret = strncpy_from_unsafe (dst , (void * )addr , maxlen );
925
+
926
+ if (ret < 0 ) { /* Failed to fetch string */
927
+ dst [0 ] = '\0' ;
928
+ * (u32 * )dest = make_data_rloc (0 , get_rloc_offs (* (u32 * )dest ));
929
+ } else {
930
+ * (u32 * )dest = make_data_rloc (ret , get_rloc_offs (* (u32 * )dest ));
931
+ }
932
+ }
933
+
934
+ /* Note that we don't verify it, since the code does not come from user space */
935
+ static int
936
+ process_fetch_insn (struct fetch_insn * code , struct pt_regs * regs , void * dest ,
937
+ bool pre )
938
+ {
939
+ unsigned long val ;
940
+ int ret ;
941
+
942
+ /* 1st stage: get value from context */
943
+ switch (code -> op ) {
944
+ case FETCH_OP_REG :
945
+ val = regs_get_register (regs , code -> param );
946
+ break ;
947
+ case FETCH_OP_STACK :
948
+ val = regs_get_kernel_stack_nth (regs , code -> param );
949
+ break ;
950
+ case FETCH_OP_STACKP :
951
+ val = kernel_stack_pointer (regs );
952
+ break ;
953
+ case FETCH_OP_RETVAL :
954
+ val = regs_return_value (regs );
955
+ break ;
956
+ case FETCH_OP_IMM :
957
+ val = code -> immediate ;
958
+ break ;
959
+ case FETCH_OP_COMM :
960
+ val = (unsigned long )current -> comm ;
961
+ break ;
962
+ default :
963
+ return - EILSEQ ;
964
+ }
965
+ code ++ ;
966
+
967
+ /* 2nd stage: dereference memory if needed */
968
+ while (code -> op == FETCH_OP_DEREF ) {
969
+ ret = probe_kernel_read (& val , (void * )val + code -> offset ,
970
+ sizeof (val ));
971
+ if (ret )
972
+ return ret ;
973
+ code ++ ;
974
+ }
975
+
976
+ /* 3rd stage: store value to buffer */
977
+ switch (code -> op ) {
978
+ case FETCH_OP_ST_RAW :
979
+ fetch_store_raw (val , code , dest );
980
+ break ;
981
+ case FETCH_OP_ST_MEM :
982
+ probe_kernel_read (dest , (void * )val + code -> offset , code -> size );
983
+ break ;
984
+ case FETCH_OP_ST_STRING :
985
+ if (pre )
986
+ fetch_store_strlen (val + code -> offset , dest );
987
+ else
988
+ fetch_store_string (val + code -> offset , dest );
989
+ break ;
990
+ default :
991
+ return - EILSEQ ;
992
+ }
993
+ code ++ ;
994
+
995
+ /* 4th stage: modify stored value if needed */
996
+ if (code -> op == FETCH_OP_MOD_BF ) {
997
+ fetch_apply_bitfield (code , dest );
998
+ code ++ ;
999
+ }
1000
+
1001
+ return code -> op == FETCH_OP_END ? 0 : - EILSEQ ;
1002
+ }
1003
+ NOKPROBE_SYMBOL (process_fetch_insn )
1004
+
1034
1005
/* Kprobe handler */
1035
1006
static nokprobe_inline void
1036
1007
__kprobe_trace_func (struct trace_kprobe * tk , struct pt_regs * regs ,
0 commit comments