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