Fix: syscall filtering: NULL pointer deref
[lttng-modules.git] / lttng-syscalls.c
1 /*
2 * lttng-syscalls.c
3 *
4 * LTTng syscall probes.
5 *
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include <linux/module.h>
24 #include <linux/slab.h>
25 #include <linux/compat.h>
26 #include <linux/err.h>
27 #include <linux/bitmap.h>
28 #include <linux/in.h>
29 #include <linux/in6.h>
30 #include <linux/seq_file.h>
31 #include <linux/stringify.h>
32 #include <asm/ptrace.h>
33 #include <asm/syscall.h>
34
35 #include "lib/bitfield.h"
36 #include "wrapper/tracepoint.h"
37 #include "lttng-events.h"
38
39 #ifndef CONFIG_COMPAT
40 # ifndef is_compat_task
41 # define is_compat_task() (0)
42 # endif
43 #endif
44
45 enum sc_type {
46 SC_TYPE_ENTRY,
47 SC_TYPE_EXIT,
48 SC_TYPE_COMPAT_ENTRY,
49 SC_TYPE_COMPAT_EXIT,
50 };
51
52 #define SYSCALL_ENTRY_TOK syscall_entry_
53 #define COMPAT_SYSCALL_ENTRY_TOK compat_syscall_entry_
54 #define SYSCALL_EXIT_TOK syscall_exit_
55 #define COMPAT_SYSCALL_EXIT_TOK compat_syscall_exit_
56
57 #define SYSCALL_ENTRY_STR __stringify(SYSCALL_ENTRY_TOK)
58 #define COMPAT_SYSCALL_ENTRY_STR __stringify(COMPAT_SYSCALL_ENTRY_TOK)
59 #define SYSCALL_EXIT_STR __stringify(SYSCALL_EXIT_TOK)
60 #define COMPAT_SYSCALL_EXIT_STR __stringify(COMPAT_SYSCALL_EXIT_TOK)
61
62 static
63 void syscall_entry_probe(void *__data, struct pt_regs *regs, long id);
64 static
65 void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret);
66
67 /*
68 * Forward declarations for old kernels.
69 */
70 struct mmsghdr;
71 struct rlimit64;
72 struct oldold_utsname;
73 struct old_utsname;
74 struct sel_arg_struct;
75 struct mmap_arg_struct;
76
77 #ifdef IA32_NR_syscalls
78 #define NR_compat_syscalls IA32_NR_syscalls
79 #else
80 #define NR_compat_syscalls NR_syscalls
81 #endif
82
83 /*
84 * Create LTTng tracepoint probes.
85 */
86 #define LTTNG_PACKAGE_BUILD
87 #define CREATE_TRACE_POINTS
88 #define TP_MODULE_NOINIT
89 #define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers
90
91 #define PARAMS(args...) args
92
93 /* Handle unknown syscalls */
94 #define TRACE_SYSTEM syscalls_unknown
95 #include "instrumentation/syscalls/headers/syscalls_unknown.h"
96 #undef TRACE_SYSTEM
97
98 #define SC_ENTER
99
100 #undef sc_exit
101 #define sc_exit(...)
102 #undef sc_in
103 #define sc_in(...) __VA_ARGS__
104 #undef sc_out
105 #define sc_out(...)
106 #undef sc_inout
107 #define sc_inout(...) __VA_ARGS__
108
109 /* Hijack probe callback for system call enter */
110 #undef TP_PROBE_CB
111 #define TP_PROBE_CB(_template) &syscall_entry_probe
112 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
113 LTTNG_TRACEPOINT_EVENT(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
114 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
115 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
116 LTTNG_TRACEPOINT_EVENT_CODE(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
117 PARAMS(_locvar), PARAMS(_code), \
118 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
119 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
120 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_entry_##_name, PARAMS(_struct), PARAMS(_assign), \
121 PARAMS(_printk))
122 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
123 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_entry_##_template, syscall_entry_##_name)
124 #undef TRACE_SYSTEM
125 #define TRACE_SYSTEM syscall_entry_integers
126 #define TRACE_INCLUDE_FILE syscalls_integers
127 #include "instrumentation/syscalls/headers/syscalls_integers.h"
128 #undef TRACE_INCLUDE_FILE
129 #undef TRACE_SYSTEM
130 #define TRACE_SYSTEM syscall_entry_pointers
131 #define TRACE_INCLUDE_FILE syscalls_pointers
132 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
133 #undef TRACE_INCLUDE_FILE
134 #undef TRACE_SYSTEM
135 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
136 #undef SC_LTTNG_TRACEPOINT_EVENT
137 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
138 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
139 #undef TP_PROBE_CB
140 #undef _TRACE_SYSCALLS_INTEGERS_H
141 #undef _TRACE_SYSCALLS_POINTERS_H
142
143 /* Hijack probe callback for compat system call enter */
144 #define TP_PROBE_CB(_template) &syscall_entry_probe
145 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
146 LTTNG_TRACEPOINT_EVENT(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
147 PARAMS(_struct), PARAMS(_assign), \
148 PARAMS(_printk))
149 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
150 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
151 PARAMS(_locvar), PARAMS(_code), \
152 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
153 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
154 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_entry_##_name, PARAMS(_struct), \
155 PARAMS(_assign), PARAMS(_printk))
156 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
157 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_entry_##_template, \
158 compat_syscall_entry_##_name)
159 #define TRACE_SYSTEM compat_syscall_entry_integers
160 #define TRACE_INCLUDE_FILE compat_syscalls_integers
161 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
162 #undef TRACE_INCLUDE_FILE
163 #undef TRACE_SYSTEM
164 #define TRACE_SYSTEM compat_syscall_entry_pointers
165 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
166 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
167 #undef TRACE_INCLUDE_FILE
168 #undef TRACE_SYSTEM
169 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
170 #undef SC_LTTNG_TRACEPOINT_EVENT
171 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
172 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
173 #undef TP_PROBE_CB
174 #undef _TRACE_SYSCALLS_INTEGERS_H
175 #undef _TRACE_SYSCALLS_POINTERS_H
176
177 #undef SC_ENTER
178
179 #define SC_EXIT
180
181 #undef sc_exit
182 #define sc_exit(...) __VA_ARGS__
183 #undef sc_in
184 #define sc_in(...)
185 #undef sc_out
186 #define sc_out(...) __VA_ARGS__
187 #undef sc_inout
188 #define sc_inout(...) __VA_ARGS__
189
190 /* Hijack probe callback for system call exit */
191 #define TP_PROBE_CB(_template) &syscall_exit_probe
192 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
193 LTTNG_TRACEPOINT_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
194 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
195 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
196 LTTNG_TRACEPOINT_EVENT_CODE(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
197 PARAMS(_locvar), PARAMS(_code), \
198 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
199 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
200 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_struct), \
201 PARAMS(_assign), PARAMS(_printk))
202 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
203 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_exit_##_template, \
204 syscall_exit_##_name)
205 #define TRACE_SYSTEM syscall_exit_integers
206 #define TRACE_INCLUDE_FILE syscalls_integers
207 #include "instrumentation/syscalls/headers/syscalls_integers.h"
208 #undef TRACE_INCLUDE_FILE
209 #undef TRACE_SYSTEM
210 #define TRACE_SYSTEM syscall_exit_pointers
211 #define TRACE_INCLUDE_FILE syscalls_pointers
212 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
213 #undef TRACE_INCLUDE_FILE
214 #undef TRACE_SYSTEM
215 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
216 #undef SC_LTTNG_TRACEPOINT_EVENT
217 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
218 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
219 #undef TP_PROBE_CB
220 #undef _TRACE_SYSCALLS_INTEGERS_H
221 #undef _TRACE_SYSCALLS_POINTERS_H
222
223
224 /* Hijack probe callback for compat system call exit */
225 #define TP_PROBE_CB(_template) &syscall_exit_probe
226 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
227 LTTNG_TRACEPOINT_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
228 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
229 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
230 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
231 PARAMS(_locvar), PARAMS(_code), \
232 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
233 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
234 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_struct), \
235 PARAMS(_assign), PARAMS(_printk))
236 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
237 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_exit_##_template, \
238 compat_syscall_exit_##_name)
239 #define TRACE_SYSTEM compat_syscall_exit_integers
240 #define TRACE_INCLUDE_FILE compat_syscalls_integers
241 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
242 #undef TRACE_INCLUDE_FILE
243 #undef TRACE_SYSTEM
244 #define TRACE_SYSTEM compat_syscall_exit_pointers
245 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
246 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
247 #undef TRACE_INCLUDE_FILE
248 #undef TRACE_SYSTEM
249 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
250 #undef SC_LTTNG_TRACEPOINT_EVENT
251 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
252 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
253 #undef TP_PROBE_CB
254 #undef _TRACE_SYSCALLS_INTEGERS_H
255 #undef _TRACE_SYSCALLS_POINTERS_H
256
257 #undef SC_EXIT
258
259 #undef TP_MODULE_NOINIT
260 #undef LTTNG_PACKAGE_BUILD
261 #undef CREATE_TRACE_POINTS
262
263 struct trace_syscall_entry {
264 void *func;
265 const struct lttng_event_desc *desc;
266 const struct lttng_event_field *fields;
267 unsigned int nrargs;
268 };
269
270 #define CREATE_SYSCALL_TABLE
271
272 #define SC_ENTER
273
274 #undef sc_exit
275 #define sc_exit(...)
276
277 #undef TRACE_SYSCALL_TABLE
278 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
279 [ _nr ] = { \
280 .func = __event_probe__syscall_entry_##_template, \
281 .nrargs = (_nrargs), \
282 .fields = __event_fields___syscall_entry_##_template, \
283 .desc = &__event_desc___syscall_entry_##_name, \
284 },
285
286 /* Syscall enter tracing table */
287 static const struct trace_syscall_entry sc_table[] = {
288 #include "instrumentation/syscalls/headers/syscalls_integers.h"
289 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
290 };
291
292 #undef TRACE_SYSCALL_TABLE
293 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
294 [ _nr ] = { \
295 .func = __event_probe__compat_syscall_entry_##_template, \
296 .nrargs = (_nrargs), \
297 .fields = __event_fields___compat_syscall_entry_##_template, \
298 .desc = &__event_desc___compat_syscall_entry_##_name, \
299 },
300
301 /* Compat syscall enter table */
302 const struct trace_syscall_entry compat_sc_table[] = {
303 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
304 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
305 };
306
307 #undef SC_ENTER
308
309 #define SC_EXIT
310
311 #undef sc_exit
312 #define sc_exit(...) __VA_ARGS__
313
314 #undef TRACE_SYSCALL_TABLE
315 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
316 [ _nr ] = { \
317 .func = __event_probe__syscall_exit_##_template, \
318 .nrargs = (_nrargs), \
319 .fields = __event_fields___syscall_exit_##_template, \
320 .desc = &__event_desc___syscall_exit_##_name, \
321 },
322
323 /* Syscall exit table */
324 static const struct trace_syscall_entry sc_exit_table[] = {
325 #include "instrumentation/syscalls/headers/syscalls_integers.h"
326 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
327 };
328
329 #undef TRACE_SYSCALL_TABLE
330 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
331 [ _nr ] = { \
332 .func = __event_probe__compat_syscall_exit_##_template, \
333 .nrargs = (_nrargs), \
334 .fields = __event_fields___compat_syscall_exit_##_template, \
335 .desc = &__event_desc___compat_syscall_exit_##_name, \
336 },
337
338 /* Compat syscall exit table */
339 const struct trace_syscall_entry compat_sc_exit_table[] = {
340 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
341 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
342 };
343
344 #undef SC_EXIT
345
346 #undef CREATE_SYSCALL_TABLE
347
348 struct lttng_syscall_filter {
349 DECLARE_BITMAP(sc, NR_syscalls);
350 DECLARE_BITMAP(sc_compat, NR_compat_syscalls);
351 };
352
353 static void syscall_entry_unknown(struct lttng_event *event,
354 struct pt_regs *regs, unsigned int id)
355 {
356 unsigned long args[UNKNOWN_SYSCALL_NRARGS];
357
358 syscall_get_arguments(current, regs, 0, UNKNOWN_SYSCALL_NRARGS, args);
359 if (unlikely(is_compat_task()))
360 __event_probe__compat_syscall_entry_unknown(event, id, args);
361 else
362 __event_probe__syscall_entry_unknown(event, id, args);
363 }
364
365 void syscall_entry_probe(void *__data, struct pt_regs *regs, long id)
366 {
367 struct lttng_channel *chan = __data;
368 struct lttng_event *event, *unknown_event;
369 const struct trace_syscall_entry *table, *entry;
370 size_t table_len;
371
372 if (unlikely(is_compat_task())) {
373 struct lttng_syscall_filter *filter;
374
375 filter = rcu_dereference(chan->sc_filter);
376 if (filter) {
377 if (id >= NR_compat_syscalls
378 || !test_bit(id, filter->sc_compat)) {
379 /* System call filtered out. */
380 return;
381 }
382 }
383 table = compat_sc_table;
384 table_len = ARRAY_SIZE(compat_sc_table);
385 unknown_event = chan->sc_compat_unknown;
386 } else {
387 struct lttng_syscall_filter *filter;
388
389 filter = rcu_dereference(chan->sc_filter);
390 if (filter) {
391 if (id >= NR_syscalls
392 || !test_bit(id, filter->sc)) {
393 /* System call filtered out. */
394 return;
395 }
396 }
397 table = sc_table;
398 table_len = ARRAY_SIZE(sc_table);
399 unknown_event = chan->sc_unknown;
400 }
401 if (unlikely(id >= table_len)) {
402 syscall_entry_unknown(unknown_event, regs, id);
403 return;
404 }
405 if (unlikely(is_compat_task()))
406 event = chan->compat_sc_table[id];
407 else
408 event = chan->sc_table[id];
409 if (unlikely(!event)) {
410 syscall_entry_unknown(unknown_event, regs, id);
411 return;
412 }
413 entry = &table[id];
414 WARN_ON_ONCE(!entry);
415
416 switch (entry->nrargs) {
417 case 0:
418 {
419 void (*fptr)(void *__data) = entry->func;
420
421 fptr(event);
422 break;
423 }
424 case 1:
425 {
426 void (*fptr)(void *__data, unsigned long arg0) = entry->func;
427 unsigned long args[1];
428
429 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
430 fptr(event, args[0]);
431 break;
432 }
433 case 2:
434 {
435 void (*fptr)(void *__data,
436 unsigned long arg0,
437 unsigned long arg1) = entry->func;
438 unsigned long args[2];
439
440 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
441 fptr(event, args[0], args[1]);
442 break;
443 }
444 case 3:
445 {
446 void (*fptr)(void *__data,
447 unsigned long arg0,
448 unsigned long arg1,
449 unsigned long arg2) = entry->func;
450 unsigned long args[3];
451
452 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
453 fptr(event, args[0], args[1], args[2]);
454 break;
455 }
456 case 4:
457 {
458 void (*fptr)(void *__data,
459 unsigned long arg0,
460 unsigned long arg1,
461 unsigned long arg2,
462 unsigned long arg3) = entry->func;
463 unsigned long args[4];
464
465 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
466 fptr(event, args[0], args[1], args[2], args[3]);
467 break;
468 }
469 case 5:
470 {
471 void (*fptr)(void *__data,
472 unsigned long arg0,
473 unsigned long arg1,
474 unsigned long arg2,
475 unsigned long arg3,
476 unsigned long arg4) = entry->func;
477 unsigned long args[5];
478
479 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
480 fptr(event, args[0], args[1], args[2], args[3], args[4]);
481 break;
482 }
483 case 6:
484 {
485 void (*fptr)(void *__data,
486 unsigned long arg0,
487 unsigned long arg1,
488 unsigned long arg2,
489 unsigned long arg3,
490 unsigned long arg4,
491 unsigned long arg5) = entry->func;
492 unsigned long args[6];
493
494 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
495 fptr(event, args[0], args[1], args[2],
496 args[3], args[4], args[5]);
497 break;
498 }
499 default:
500 break;
501 }
502 }
503
504 static void syscall_exit_unknown(struct lttng_event *event,
505 struct pt_regs *regs, unsigned int id, long ret)
506 {
507 unsigned long args[UNKNOWN_SYSCALL_NRARGS];
508
509 syscall_get_arguments(current, regs, 0, UNKNOWN_SYSCALL_NRARGS, args);
510 if (unlikely(is_compat_task()))
511 __event_probe__compat_syscall_exit_unknown(event, id, ret,
512 args);
513 else
514 __event_probe__syscall_exit_unknown(event, id, ret, args);
515 }
516
517 void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret)
518 {
519 struct lttng_channel *chan = __data;
520 struct lttng_event *event, *unknown_event;
521 const struct trace_syscall_entry *table, *entry;
522 size_t table_len;
523 long id;
524
525 id = syscall_get_nr(current, regs);
526 if (unlikely(is_compat_task())) {
527 struct lttng_syscall_filter *filter;
528
529 filter = rcu_dereference(chan->sc_filter);
530 if (filter) {
531 if (id >= NR_compat_syscalls
532 || !test_bit(id, filter->sc_compat)) {
533 /* System call filtered out. */
534 return;
535 }
536 }
537 table = compat_sc_exit_table;
538 table_len = ARRAY_SIZE(compat_sc_exit_table);
539 unknown_event = chan->compat_sc_exit_unknown;
540 } else {
541 struct lttng_syscall_filter *filter;
542
543 filter = rcu_dereference(chan->sc_filter);
544 if (filter) {
545 if (id >= NR_syscalls
546 || !test_bit(id, filter->sc)) {
547 /* System call filtered out. */
548 return;
549 }
550 }
551 table = sc_exit_table;
552 table_len = ARRAY_SIZE(sc_exit_table);
553 unknown_event = chan->sc_exit_unknown;
554 }
555 if (unlikely(id >= table_len)) {
556 syscall_exit_unknown(unknown_event, regs, id, ret);
557 return;
558 }
559 if (unlikely(is_compat_task()))
560 event = chan->compat_sc_exit_table[id];
561 else
562 event = chan->sc_exit_table[id];
563 if (unlikely(!event)) {
564 syscall_exit_unknown(unknown_event, regs, id, ret);
565 return;
566 }
567 entry = &table[id];
568 WARN_ON_ONCE(!entry);
569
570 switch (entry->nrargs) {
571 case 0:
572 {
573 void (*fptr)(void *__data, long ret) = entry->func;
574
575 fptr(event, ret);
576 break;
577 }
578 case 1:
579 {
580 void (*fptr)(void *__data,
581 long ret,
582 unsigned long arg0) = entry->func;
583 unsigned long args[1];
584
585 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
586 fptr(event, ret, args[0]);
587 break;
588 }
589 case 2:
590 {
591 void (*fptr)(void *__data,
592 long ret,
593 unsigned long arg0,
594 unsigned long arg1) = entry->func;
595 unsigned long args[2];
596
597 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
598 fptr(event, ret, args[0], args[1]);
599 break;
600 }
601 case 3:
602 {
603 void (*fptr)(void *__data,
604 long ret,
605 unsigned long arg0,
606 unsigned long arg1,
607 unsigned long arg2) = entry->func;
608 unsigned long args[3];
609
610 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
611 fptr(event, ret, args[0], args[1], args[2]);
612 break;
613 }
614 case 4:
615 {
616 void (*fptr)(void *__data,
617 long ret,
618 unsigned long arg0,
619 unsigned long arg1,
620 unsigned long arg2,
621 unsigned long arg3) = entry->func;
622 unsigned long args[4];
623
624 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
625 fptr(event, ret, args[0], args[1], args[2], args[3]);
626 break;
627 }
628 case 5:
629 {
630 void (*fptr)(void *__data,
631 long ret,
632 unsigned long arg0,
633 unsigned long arg1,
634 unsigned long arg2,
635 unsigned long arg3,
636 unsigned long arg4) = entry->func;
637 unsigned long args[5];
638
639 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
640 fptr(event, ret, args[0], args[1], args[2], args[3], args[4]);
641 break;
642 }
643 case 6:
644 {
645 void (*fptr)(void *__data,
646 long ret,
647 unsigned long arg0,
648 unsigned long arg1,
649 unsigned long arg2,
650 unsigned long arg3,
651 unsigned long arg4,
652 unsigned long arg5) = entry->func;
653 unsigned long args[6];
654
655 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
656 fptr(event, ret, args[0], args[1], args[2],
657 args[3], args[4], args[5]);
658 break;
659 }
660 default:
661 break;
662 }
663 }
664
665 /* noinline to diminish caller stack size */
666 static
667 int fill_table(const struct trace_syscall_entry *table, size_t table_len,
668 struct lttng_event **chan_table, struct lttng_channel *chan,
669 void *filter, enum sc_type type)
670 {
671 const struct lttng_event_desc *desc;
672 unsigned int i;
673
674 /* Allocate events for each syscall, insert into table */
675 for (i = 0; i < table_len; i++) {
676 struct lttng_kernel_event ev;
677 desc = table[i].desc;
678
679 if (!desc) {
680 /* Unknown syscall */
681 continue;
682 }
683 /*
684 * Skip those already populated by previous failed
685 * register for this channel.
686 */
687 if (chan_table[i])
688 continue;
689 memset(&ev, 0, sizeof(ev));
690 switch (type) {
691 case SC_TYPE_ENTRY:
692 strncpy(ev.name, SYSCALL_ENTRY_STR,
693 LTTNG_KERNEL_SYM_NAME_LEN);
694 break;
695 case SC_TYPE_EXIT:
696 strncpy(ev.name, SYSCALL_EXIT_STR,
697 LTTNG_KERNEL_SYM_NAME_LEN);
698 break;
699 case SC_TYPE_COMPAT_ENTRY:
700 strncpy(ev.name, COMPAT_SYSCALL_ENTRY_STR,
701 LTTNG_KERNEL_SYM_NAME_LEN);
702 break;
703 case SC_TYPE_COMPAT_EXIT:
704 strncpy(ev.name, COMPAT_SYSCALL_EXIT_STR,
705 LTTNG_KERNEL_SYM_NAME_LEN);
706 break;
707 default:
708 BUG_ON(1);
709 break;
710 }
711 strncat(ev.name, desc->name,
712 LTTNG_KERNEL_SYM_NAME_LEN - strlen(ev.name) - 1);
713 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
714 ev.instrumentation = LTTNG_KERNEL_NOOP;
715 chan_table[i] = lttng_event_create(chan, &ev, filter,
716 desc);
717 WARN_ON_ONCE(!chan_table[i]);
718 if (IS_ERR(chan_table[i])) {
719 /*
720 * If something goes wrong in event registration
721 * after the first one, we have no choice but to
722 * leave the previous events in there, until
723 * deleted by session teardown.
724 */
725 return PTR_ERR(chan_table[i]);
726 }
727 }
728 return 0;
729 }
730
731 int lttng_syscalls_register(struct lttng_channel *chan, void *filter)
732 {
733 struct lttng_kernel_event ev;
734 int ret;
735
736 wrapper_vmalloc_sync_all();
737
738 if (!chan->sc_table) {
739 /* create syscall table mapping syscall to events */
740 chan->sc_table = kzalloc(sizeof(struct lttng_event *)
741 * ARRAY_SIZE(sc_table), GFP_KERNEL);
742 if (!chan->sc_table)
743 return -ENOMEM;
744 }
745 if (!chan->sc_exit_table) {
746 /* create syscall table mapping syscall to events */
747 chan->sc_exit_table = kzalloc(sizeof(struct lttng_event *)
748 * ARRAY_SIZE(sc_exit_table), GFP_KERNEL);
749 if (!chan->sc_exit_table)
750 return -ENOMEM;
751 }
752
753
754 #ifdef CONFIG_COMPAT
755 if (!chan->compat_sc_table) {
756 /* create syscall table mapping compat syscall to events */
757 chan->compat_sc_table = kzalloc(sizeof(struct lttng_event *)
758 * ARRAY_SIZE(compat_sc_table), GFP_KERNEL);
759 if (!chan->compat_sc_table)
760 return -ENOMEM;
761 }
762
763 if (!chan->compat_sc_exit_table) {
764 /* create syscall table mapping compat syscall to events */
765 chan->compat_sc_exit_table = kzalloc(sizeof(struct lttng_event *)
766 * ARRAY_SIZE(compat_sc_exit_table), GFP_KERNEL);
767 if (!chan->compat_sc_exit_table)
768 return -ENOMEM;
769 }
770 #endif
771 if (!chan->sc_unknown) {
772 const struct lttng_event_desc *desc =
773 &__event_desc___syscall_entry_unknown;
774
775 memset(&ev, 0, sizeof(ev));
776 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
777 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
778 ev.instrumentation = LTTNG_KERNEL_NOOP;
779 chan->sc_unknown = lttng_event_create(chan, &ev, filter,
780 desc);
781 WARN_ON_ONCE(!chan->sc_unknown);
782 if (IS_ERR(chan->sc_unknown)) {
783 return PTR_ERR(chan->sc_unknown);
784 }
785 }
786
787 if (!chan->sc_compat_unknown) {
788 const struct lttng_event_desc *desc =
789 &__event_desc___compat_syscall_entry_unknown;
790
791 memset(&ev, 0, sizeof(ev));
792 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
793 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
794 ev.instrumentation = LTTNG_KERNEL_NOOP;
795 chan->sc_compat_unknown = lttng_event_create(chan, &ev, filter,
796 desc);
797 WARN_ON_ONCE(!chan->sc_unknown);
798 if (IS_ERR(chan->sc_compat_unknown)) {
799 return PTR_ERR(chan->sc_compat_unknown);
800 }
801 }
802
803 if (!chan->compat_sc_exit_unknown) {
804 const struct lttng_event_desc *desc =
805 &__event_desc___compat_syscall_exit_unknown;
806
807 memset(&ev, 0, sizeof(ev));
808 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
809 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
810 ev.instrumentation = LTTNG_KERNEL_NOOP;
811 chan->compat_sc_exit_unknown = lttng_event_create(chan, &ev,
812 filter, desc);
813 WARN_ON_ONCE(!chan->compat_sc_exit_unknown);
814 if (IS_ERR(chan->compat_sc_exit_unknown)) {
815 return PTR_ERR(chan->compat_sc_exit_unknown);
816 }
817 }
818
819 if (!chan->sc_exit_unknown) {
820 const struct lttng_event_desc *desc =
821 &__event_desc___syscall_exit_unknown;
822
823 memset(&ev, 0, sizeof(ev));
824 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
825 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
826 ev.instrumentation = LTTNG_KERNEL_NOOP;
827 chan->sc_exit_unknown = lttng_event_create(chan, &ev, filter,
828 desc);
829 WARN_ON_ONCE(!chan->sc_exit_unknown);
830 if (IS_ERR(chan->sc_exit_unknown)) {
831 return PTR_ERR(chan->sc_exit_unknown);
832 }
833 }
834
835 ret = fill_table(sc_table, ARRAY_SIZE(sc_table),
836 chan->sc_table, chan, filter, SC_TYPE_ENTRY);
837 if (ret)
838 return ret;
839 ret = fill_table(sc_exit_table, ARRAY_SIZE(sc_exit_table),
840 chan->sc_exit_table, chan, filter, SC_TYPE_EXIT);
841 if (ret)
842 return ret;
843
844 #ifdef CONFIG_COMPAT
845 ret = fill_table(compat_sc_table, ARRAY_SIZE(compat_sc_table),
846 chan->compat_sc_table, chan, filter,
847 SC_TYPE_COMPAT_ENTRY);
848 if (ret)
849 return ret;
850 ret = fill_table(compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
851 chan->compat_sc_exit_table, chan, filter,
852 SC_TYPE_COMPAT_EXIT);
853 if (ret)
854 return ret;
855 #endif
856 if (!chan->sys_enter_registered) {
857 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
858 (void *) syscall_entry_probe, chan);
859 if (ret)
860 return ret;
861 chan->sys_enter_registered = 1;
862 }
863 /*
864 * We change the name of sys_exit tracepoint due to namespace
865 * conflict with sys_exit syscall entry.
866 */
867 if (!chan->sys_exit_registered) {
868 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
869 (void *) syscall_exit_probe, chan);
870 if (ret) {
871 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
872 (void *) syscall_entry_probe, chan));
873 return ret;
874 }
875 chan->sys_exit_registered = 1;
876 }
877 return ret;
878 }
879
880 /*
881 * Only called at session destruction.
882 */
883 int lttng_syscalls_unregister(struct lttng_channel *chan)
884 {
885 int ret;
886
887 if (!chan->sc_table)
888 return 0;
889 if (chan->sys_enter_registered) {
890 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
891 (void *) syscall_exit_probe, chan);
892 if (ret)
893 return ret;
894 chan->sys_enter_registered = 0;
895 }
896 if (chan->sys_exit_registered) {
897 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
898 (void *) syscall_entry_probe, chan);
899 if (ret)
900 return ret;
901 chan->sys_exit_registered = 0;
902 }
903 /* lttng_event destroy will be performed by lttng_session_destroy() */
904 kfree(chan->sc_table);
905 kfree(chan->sc_exit_table);
906 #ifdef CONFIG_COMPAT
907 kfree(chan->compat_sc_table);
908 kfree(chan->compat_sc_exit_table);
909 #endif
910 kfree(chan->sc_filter);
911 return 0;
912 }
913
914 static
915 int get_syscall_nr(const char *syscall_name)
916 {
917 int syscall_nr = -1;
918 int i;
919
920 for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
921 const struct trace_syscall_entry *entry;
922 const char *it_name;
923
924 entry = &sc_table[i];
925 if (!entry->desc)
926 continue;
927 it_name = entry->desc->name;
928 it_name += strlen(SYSCALL_ENTRY_STR);
929 if (!strcmp(syscall_name, it_name)) {
930 syscall_nr = i;
931 break;
932 }
933 }
934 return syscall_nr;
935 }
936
937 static
938 int get_compat_syscall_nr(const char *syscall_name)
939 {
940 int syscall_nr = -1;
941 int i;
942
943 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++) {
944 const struct trace_syscall_entry *entry;
945 const char *it_name;
946
947 entry = &compat_sc_table[i];
948 if (!entry->desc)
949 continue;
950 it_name = entry->desc->name;
951 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
952 if (!strcmp(syscall_name, it_name)) {
953 syscall_nr = i;
954 break;
955 }
956 }
957 return syscall_nr;
958 }
959
960 static
961 uint32_t get_sc_tables_len(void)
962 {
963 return ARRAY_SIZE(sc_table) + ARRAY_SIZE(compat_sc_table);
964 }
965
966 int lttng_syscall_filter_enable(struct lttng_channel *chan,
967 const char *name)
968 {
969 int syscall_nr, compat_syscall_nr, ret;
970 struct lttng_syscall_filter *filter;
971
972 WARN_ON_ONCE(!chan->sc_table);
973
974 if (!name) {
975 /* Enable all system calls by removing filter */
976 if (chan->sc_filter) {
977 filter = chan->sc_filter;
978 rcu_assign_pointer(chan->sc_filter, NULL);
979 synchronize_trace();
980 kfree(filter);
981 }
982 chan->syscall_all = 1;
983 return 0;
984 }
985
986 if (!chan->sc_filter) {
987 if (chan->syscall_all) {
988 /*
989 * All syscalls are already enabled.
990 */
991 return -EEXIST;
992 }
993 filter = kzalloc(sizeof(struct lttng_syscall_filter),
994 GFP_KERNEL);
995 if (!filter)
996 return -ENOMEM;
997 } else {
998 filter = chan->sc_filter;
999 }
1000 syscall_nr = get_syscall_nr(name);
1001 compat_syscall_nr = get_compat_syscall_nr(name);
1002 if (syscall_nr < 0 && compat_syscall_nr < 0) {
1003 ret = -ENOENT;
1004 goto error;
1005 }
1006 if (syscall_nr >= 0) {
1007 if (test_bit(syscall_nr, filter->sc)) {
1008 ret = -EEXIST;
1009 goto error;
1010 }
1011 bitmap_set(filter->sc, syscall_nr, 1);
1012 }
1013 if (compat_syscall_nr >= 0) {
1014 if (test_bit(compat_syscall_nr, filter->sc_compat)) {
1015 ret = -EEXIST;
1016 goto error;
1017 }
1018 bitmap_set(filter->sc_compat, compat_syscall_nr, 1);
1019 }
1020 if (!chan->sc_filter)
1021 rcu_assign_pointer(chan->sc_filter, filter);
1022 return 0;
1023
1024 error:
1025 if (!chan->sc_filter)
1026 kfree(filter);
1027 return ret;
1028 }
1029
1030 int lttng_syscall_filter_disable(struct lttng_channel *chan,
1031 const char *name)
1032 {
1033 int syscall_nr, compat_syscall_nr, ret;
1034 struct lttng_syscall_filter *filter;
1035
1036 WARN_ON_ONCE(!chan->sc_table);
1037
1038 if (!chan->sc_filter) {
1039 filter = kzalloc(sizeof(struct lttng_syscall_filter),
1040 GFP_KERNEL);
1041 if (!filter)
1042 return -ENOMEM;
1043 /* Trace all system calls, then apply disable. */
1044 bitmap_set(filter->sc, 0, NR_syscalls);
1045 bitmap_set(filter->sc_compat, 0, NR_compat_syscalls);
1046 } else {
1047 filter = chan->sc_filter;
1048 }
1049
1050 if (!name) {
1051 /* Disable all system calls */
1052 bitmap_clear(filter->sc, 0, NR_syscalls);
1053 bitmap_clear(filter->sc_compat, 0, NR_compat_syscalls);
1054 goto apply_filter;
1055 }
1056 syscall_nr = get_syscall_nr(name);
1057 compat_syscall_nr = get_compat_syscall_nr(name);
1058 if (syscall_nr < 0 && compat_syscall_nr < 0) {
1059 ret = -ENOENT;
1060 goto error;
1061 }
1062 if (syscall_nr >= 0) {
1063 if (!test_bit(syscall_nr, filter->sc)) {
1064 ret = -EEXIST;
1065 goto error;
1066 }
1067 bitmap_clear(filter->sc, syscall_nr, 1);
1068 }
1069 if (compat_syscall_nr >= 0) {
1070 if (!test_bit(compat_syscall_nr, filter->sc_compat)) {
1071 ret = -EEXIST;
1072 goto error;
1073 }
1074 bitmap_clear(filter->sc_compat, compat_syscall_nr, 1);
1075 }
1076 apply_filter:
1077 if (!chan->sc_filter)
1078 rcu_assign_pointer(chan->sc_filter, filter);
1079 chan->syscall_all = 0;
1080 return 0;
1081
1082 error:
1083 if (!chan->sc_filter)
1084 kfree(filter);
1085 return ret;
1086 }
1087
1088 static
1089 const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1090 {
1091 const struct trace_syscall_entry *entry;
1092 int iter = 0;
1093
1094 for (entry = sc_table;
1095 entry < sc_table + ARRAY_SIZE(sc_table);
1096 entry++) {
1097 if (iter++ >= *pos)
1098 return entry;
1099 }
1100 for (entry = compat_sc_table;
1101 entry < compat_sc_table + ARRAY_SIZE(compat_sc_table);
1102 entry++) {
1103 if (iter++ >= *pos)
1104 return entry;
1105 }
1106 /* End of list */
1107 return NULL;
1108 }
1109
1110 static
1111 void *syscall_list_start(struct seq_file *m, loff_t *pos)
1112 {
1113 return (void *) syscall_list_get_entry(pos);
1114 }
1115
1116 static
1117 void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
1118 {
1119 (*ppos)++;
1120 return (void *) syscall_list_get_entry(ppos);
1121 }
1122
1123 static
1124 void syscall_list_stop(struct seq_file *m, void *p)
1125 {
1126 }
1127
1128 static
1129 int get_sc_table(const struct trace_syscall_entry *entry,
1130 const struct trace_syscall_entry **table,
1131 unsigned int *bitness)
1132 {
1133 if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) {
1134 if (bitness)
1135 *bitness = BITS_PER_LONG;
1136 if (table)
1137 *table = sc_table;
1138 return 0;
1139 }
1140 if (!(entry >= compat_sc_table
1141 && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table))) {
1142 return -EINVAL;
1143 }
1144 if (bitness)
1145 *bitness = 32;
1146 if (table)
1147 *table = compat_sc_table;
1148 return 0;
1149 }
1150
1151 static
1152 int syscall_list_show(struct seq_file *m, void *p)
1153 {
1154 const struct trace_syscall_entry *table, *entry = p;
1155 unsigned int bitness;
1156 unsigned long index;
1157 int ret;
1158 const char *name;
1159
1160 ret = get_sc_table(entry, &table, &bitness);
1161 if (ret)
1162 return ret;
1163 if (!entry->desc)
1164 return 0;
1165 if (table == sc_table) {
1166 index = entry - table;
1167 name = &entry->desc->name[strlen(SYSCALL_ENTRY_STR)];
1168 } else {
1169 index = (entry - table) + ARRAY_SIZE(sc_table);
1170 name = &entry->desc->name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
1171 }
1172 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
1173 index, name, bitness);
1174 return 0;
1175 }
1176
1177 static
1178 const struct seq_operations lttng_syscall_list_seq_ops = {
1179 .start = syscall_list_start,
1180 .next = syscall_list_next,
1181 .stop = syscall_list_stop,
1182 .show = syscall_list_show,
1183 };
1184
1185 static
1186 int lttng_syscall_list_open(struct inode *inode, struct file *file)
1187 {
1188 return seq_open(file, &lttng_syscall_list_seq_ops);
1189 }
1190
1191 const struct file_operations lttng_syscall_list_fops = {
1192 .owner = THIS_MODULE,
1193 .open = lttng_syscall_list_open,
1194 .read = seq_read,
1195 .llseek = seq_lseek,
1196 .release = seq_release,
1197 };
1198
1199 long lttng_channel_syscall_mask(struct lttng_channel *channel,
1200 struct lttng_kernel_syscall_mask __user *usyscall_mask)
1201 {
1202 uint32_t len, sc_tables_len, bitmask_len;
1203 int ret = 0, bit;
1204 char *tmp_mask;
1205 struct lttng_syscall_filter *filter;
1206
1207 ret = get_user(len, &usyscall_mask->len);
1208 if (ret)
1209 return ret;
1210 sc_tables_len = get_sc_tables_len();
1211 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
1212 if (len < sc_tables_len) {
1213 return put_user(sc_tables_len, &usyscall_mask->len);
1214 }
1215 /* Array is large enough, we can copy array to user-space. */
1216 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
1217 if (!tmp_mask)
1218 return -ENOMEM;
1219 filter = channel->sc_filter;
1220
1221 for (bit = 0; bit < ARRAY_SIZE(sc_table); bit++) {
1222 bt_bitfield_write_be(tmp_mask, char, bit, 1,
1223 test_bit(bit, filter->sc));
1224 }
1225 for (; bit < sc_tables_len; bit++) {
1226 bt_bitfield_write_be(tmp_mask, char, bit, 1,
1227 test_bit(bit - ARRAY_SIZE(sc_table),
1228 filter->sc_compat));
1229 }
1230 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
1231 ret = -EFAULT;
1232 kfree(tmp_mask);
1233 return ret;
1234 }
This page took 0.067286 seconds and 5 git commands to generate.