blob: a16750ddb35b8fd52cf5bde3f7748c194bbee080 [file] [log] [blame]
Andrew Geisslerc9f78652020-09-18 14:11:35 -05001From ad594e3a953db1b0c3c059fde45b5a5494f6be78 Mon Sep 17 00:00:00 2001
2From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3Date: Tue, 28 Jan 2020 16:02:44 -0500
4Subject: [PATCH 10/10] Fix: system call filter table
5
6The system call filter table has effectively been unused for a long
7time due to system call name prefix mismatch. This means the overhead of
8selective system call tracing was larger than it should have been because
9the event payload preparation would be done for all system calls as soon
10as a single system call is traced.
11
12However, fixing this underlying issue unearths several issues that crept
13unnoticed when the "enabler" concept was introduced (after the original
14implementation of the system call filter table).
15
16Here is a list of the issues which are resolved here:
17
18- Split lttng_syscalls_unregister into an unregister and destroy
19 function, thus awaiting for a grace period (and therefore quiescence
20 of the users) after unregistering the system call tracepoints before
21 freeing the system call filter data structures. This effectively fixes
22 a use-after-free.
23
24- The state for enabling "all" system calls vs enabling specific system
25 calls (and sequences of enable-disable) was incorrect with respect to
26 the "enablers" semantic. This is solved by always tracking the
27 bitmap of enabled system calls, and keeping this bitmap even when
28 enabling all system calls. The sc_filter is now always allocated
29 before system call tracing is registered to tracepoints, which means
30 it does not need to be RCU dereferenced anymore.
31
32Padding fields in the ABI are reserved to select whether to:
33
34- Trace either native or compat system call (or both, which is the
35 behavior currently implemented),
36- Trace either system call entry or exit (or both, which is the
37 behavior currently implemented),
38- Select the system call to trace by name (behavior currently
39 implemented) or by system call number,
40
41Upstream-Status: Backport
42
43Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
44---
45 lttng-abi.c | 43 ++++++
46 lttng-abi.h | 26 ++++
47 lttng-events.c | 112 +++++++++++++--
48 lttng-events.h | 31 ++++-
49 lttng-syscalls.c | 348 +++++++++++++++++++++++++----------------------
50 5 files changed, 380 insertions(+), 180 deletions(-)
51
52diff --git a/lttng-abi.c b/lttng-abi.c
53index 64ea99d..b33879d 100644
54--- a/lttng-abi.c
55+++ b/lttng-abi.c
56@@ -1264,6 +1264,46 @@ nomem:
57 return ret;
58 }
59
60+static
61+int lttng_abi_validate_event_param(struct lttng_kernel_event *event_param)
62+{
63+ /* Limit ABI to implemented features. */
64+ switch (event_param->instrumentation) {
65+ case LTTNG_KERNEL_SYSCALL:
66+ switch (event_param->u.syscall.entryexit) {
67+ case LTTNG_KERNEL_SYSCALL_ENTRYEXIT:
68+ break;
69+ default:
70+ return -EINVAL;
71+ }
72+ switch (event_param->u.syscall.abi) {
73+ case LTTNG_KERNEL_SYSCALL_ABI_ALL:
74+ break;
75+ default:
76+ return -EINVAL;
77+ }
78+ switch (event_param->u.syscall.match) {
79+ case LTTNG_SYSCALL_MATCH_NAME:
80+ break;
81+ default:
82+ return -EINVAL;
83+ }
84+ break;
85+
86+ case LTTNG_KERNEL_TRACEPOINT: /* Fallthrough */
87+ case LTTNG_KERNEL_KPROBE: /* Fallthrough */
88+ case LTTNG_KERNEL_KRETPROBE: /* Fallthrough */
89+ case LTTNG_KERNEL_NOOP: /* Fallthrough */
90+ case LTTNG_KERNEL_UPROBE:
91+ break;
92+
93+ case LTTNG_KERNEL_FUNCTION: /* Fallthrough */
94+ default:
95+ return -EINVAL;
96+ }
97+ return 0;
98+}
99+
100 static
101 int lttng_abi_create_event(struct file *channel_file,
102 struct lttng_kernel_event *event_param)
103@@ -1305,6 +1345,9 @@ int lttng_abi_create_event(struct file *channel_file,
104 ret = -EOVERFLOW;
105 goto refcount_error;
106 }
107+ ret = lttng_abi_validate_event_param(event_param);
108+ if (ret)
109+ goto event_error;
110 if (event_param->instrumentation == LTTNG_KERNEL_TRACEPOINT
111 || event_param->instrumentation == LTTNG_KERNEL_SYSCALL) {
112 struct lttng_enabler *enabler;
113diff --git a/lttng-abi.h b/lttng-abi.h
114index 1d356ab..51d60e5 100644
115--- a/lttng-abi.h
116+++ b/lttng-abi.h
117@@ -90,6 +90,31 @@ struct lttng_kernel_event_callsite {
118 } u;
119 } __attribute__((packed));
120
121+enum lttng_kernel_syscall_entryexit {
122+ LTTNG_KERNEL_SYSCALL_ENTRYEXIT = 0,
123+ LTTNG_KERNEL_SYSCALL_ENTRY = 1, /* Not implemented. */
124+ LTTNG_KERNEL_SYSCALL_EXIT = 2, /* Not implemented. */
125+};
126+
127+enum lttng_kernel_syscall_abi {
128+ LTTNG_KERNEL_SYSCALL_ABI_ALL = 0,
129+ LTTNG_KERNEL_SYSCALL_ABI_NATIVE = 1, /* Not implemented. */
130+ LTTNG_KERNEL_SYSCALL_ABI_COMPAT = 2, /* Not implemented. */
131+};
132+
133+enum lttng_kernel_syscall_match {
134+ LTTNG_SYSCALL_MATCH_NAME = 0,
135+ LTTNG_SYSCALL_MATCH_NR = 1, /* Not implemented. */
136+};
137+
138+struct lttng_kernel_syscall {
139+ uint8_t entryexit; /* enum lttng_kernel_syscall_entryexit */
140+ uint8_t abi; /* enum lttng_kernel_syscall_abi */
141+ uint8_t match; /* enum lttng_kernel_syscall_match */
142+ uint8_t padding;
143+ uint32_t nr; /* For LTTNG_SYSCALL_MATCH_NR */
144+} __attribute__((packed));
145+
146 /*
147 * For syscall tracing, name = "*" means "enable all".
148 */
149@@ -106,6 +131,7 @@ struct lttng_kernel_event {
150 struct lttng_kernel_kprobe kprobe;
151 struct lttng_kernel_function_tracer ftrace;
152 struct lttng_kernel_uprobe uprobe;
153+ struct lttng_kernel_syscall syscall;
154 char padding[LTTNG_KERNEL_EVENT_PADDING2];
155 } u;
156 } __attribute__((packed));
157diff --git a/lttng-events.c b/lttng-events.c
158index d719294..4c0b04a 100644
159--- a/lttng-events.c
160+++ b/lttng-events.c
161@@ -201,6 +201,10 @@ void lttng_session_destroy(struct lttng_session *session)
162 WARN_ON(ret);
163 }
164 synchronize_trace(); /* Wait for in-flight events to complete */
165+ list_for_each_entry(chan, &session->chan, list) {
166+ ret = lttng_syscalls_destroy(chan);
167+ WARN_ON(ret);
168+ }
169 list_for_each_entry_safe(enabler, tmpenabler,
170 &session->enablers_head, node)
171 lttng_enabler_destroy(enabler);
172@@ -740,6 +744,28 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan,
173 event->enabled = 0;
174 event->registered = 0;
175 event->desc = event_desc;
176+ switch (event_param->u.syscall.entryexit) {
177+ case LTTNG_KERNEL_SYSCALL_ENTRYEXIT:
178+ ret = -EINVAL;
179+ goto register_error;
180+ case LTTNG_KERNEL_SYSCALL_ENTRY:
181+ event->u.syscall.entryexit = LTTNG_SYSCALL_ENTRY;
182+ break;
183+ case LTTNG_KERNEL_SYSCALL_EXIT:
184+ event->u.syscall.entryexit = LTTNG_SYSCALL_EXIT;
185+ break;
186+ }
187+ switch (event_param->u.syscall.abi) {
188+ case LTTNG_KERNEL_SYSCALL_ABI_ALL:
189+ ret = -EINVAL;
190+ goto register_error;
191+ case LTTNG_KERNEL_SYSCALL_ABI_NATIVE:
192+ event->u.syscall.abi = LTTNG_SYSCALL_ABI_NATIVE;
193+ break;
194+ case LTTNG_KERNEL_SYSCALL_ABI_COMPAT:
195+ event->u.syscall.abi = LTTNG_SYSCALL_ABI_COMPAT;
196+ break;
197+ }
198 if (!event->desc) {
199 ret = -EINVAL;
200 goto register_error;
201@@ -826,8 +852,7 @@ void register_event(struct lttng_event *event)
202 event);
203 break;
204 case LTTNG_KERNEL_SYSCALL:
205- ret = lttng_syscall_filter_enable(event->chan,
206- desc->name);
207+ ret = lttng_syscall_filter_enable(event->chan, event);
208 break;
209 case LTTNG_KERNEL_KPROBE:
210 case LTTNG_KERNEL_UPROBE:
211@@ -870,8 +895,7 @@ int _lttng_event_unregister(struct lttng_event *event)
212 ret = 0;
213 break;
214 case LTTNG_KERNEL_SYSCALL:
215- ret = lttng_syscall_filter_disable(event->chan,
216- desc->name);
217+ ret = lttng_syscall_filter_disable(event->chan, event);
218 break;
219 case LTTNG_KERNEL_NOOP:
220 ret = 0;
221@@ -1203,39 +1227,87 @@ int lttng_desc_match_enabler(const struct lttng_event_desc *desc,
222 struct lttng_enabler *enabler)
223 {
224 const char *desc_name, *enabler_name;
225+ bool compat = false, entry = false;
226
227 enabler_name = enabler->event_param.name;
228 switch (enabler->event_param.instrumentation) {
229 case LTTNG_KERNEL_TRACEPOINT:
230 desc_name = desc->name;
231+ switch (enabler->type) {
232+ case LTTNG_ENABLER_STAR_GLOB:
233+ return lttng_match_enabler_star_glob(desc_name, enabler_name);
234+ case LTTNG_ENABLER_NAME:
235+ return lttng_match_enabler_name(desc_name, enabler_name);
236+ default:
237+ return -EINVAL;
238+ }
239 break;
240 case LTTNG_KERNEL_SYSCALL:
241 desc_name = desc->name;
242- if (!strncmp(desc_name, "compat_", strlen("compat_")))
243+ if (!strncmp(desc_name, "compat_", strlen("compat_"))) {
244 desc_name += strlen("compat_");
245+ compat = true;
246+ }
247 if (!strncmp(desc_name, "syscall_exit_",
248 strlen("syscall_exit_"))) {
249 desc_name += strlen("syscall_exit_");
250 } else if (!strncmp(desc_name, "syscall_entry_",
251 strlen("syscall_entry_"))) {
252 desc_name += strlen("syscall_entry_");
253+ entry = true;
254 } else {
255 WARN_ON_ONCE(1);
256 return -EINVAL;
257 }
258+ switch (enabler->event_param.u.syscall.entryexit) {
259+ case LTTNG_KERNEL_SYSCALL_ENTRYEXIT:
260+ break;
261+ case LTTNG_KERNEL_SYSCALL_ENTRY:
262+ if (!entry)
263+ return 0;
264+ break;
265+ case LTTNG_KERNEL_SYSCALL_EXIT:
266+ if (entry)
267+ return 0;
268+ break;
269+ default:
270+ return -EINVAL;
271+ }
272+ switch (enabler->event_param.u.syscall.abi) {
273+ case LTTNG_KERNEL_SYSCALL_ABI_ALL:
274+ break;
275+ case LTTNG_KERNEL_SYSCALL_ABI_NATIVE:
276+ if (compat)
277+ return 0;
278+ break;
279+ case LTTNG_KERNEL_SYSCALL_ABI_COMPAT:
280+ if (!compat)
281+ return 0;
282+ break;
283+ default:
284+ return -EINVAL;
285+ }
286+ switch (enabler->event_param.u.syscall.match) {
287+ case LTTNG_SYSCALL_MATCH_NAME:
288+ switch (enabler->type) {
289+ case LTTNG_ENABLER_STAR_GLOB:
290+ return lttng_match_enabler_star_glob(desc_name, enabler_name);
291+ case LTTNG_ENABLER_NAME:
292+ return lttng_match_enabler_name(desc_name, enabler_name);
293+ default:
294+ return -EINVAL;
295+ }
296+ break;
297+ case LTTNG_SYSCALL_MATCH_NR:
298+ return -EINVAL; /* Not implemented. */
299+ default:
300+ return -EINVAL;
301+ }
302 break;
303 default:
304 WARN_ON_ONCE(1);
305 return -EINVAL;
306 }
307- switch (enabler->type) {
308- case LTTNG_ENABLER_STAR_GLOB:
309- return lttng_match_enabler_star_glob(desc_name, enabler_name);
310- case LTTNG_ENABLER_NAME:
311- return lttng_match_enabler_name(desc_name, enabler_name);
312- default:
313- return -EINVAL;
314- }
315 }
316
317 static
318@@ -1361,9 +1433,21 @@ void lttng_create_event_if_missing(struct lttng_enabler *enabler)
319 static
320 int lttng_enabler_ref_events(struct lttng_enabler *enabler)
321 {
322- struct lttng_session *session = enabler->chan->session;
323+ struct lttng_channel *chan = enabler->chan;
324+ struct lttng_session *session = chan->session;
325 struct lttng_event *event;
326
327+ if (enabler->event_param.instrumentation == LTTNG_KERNEL_SYSCALL &&
328+ enabler->event_param.u.syscall.entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT &&
329+ enabler->event_param.u.syscall.abi == LTTNG_KERNEL_SYSCALL_ABI_ALL &&
330+ enabler->event_param.u.syscall.match == LTTNG_SYSCALL_MATCH_NAME &&
331+ !strcmp(enabler->event_param.name, "*")) {
332+ if (enabler->enabled)
333+ WRITE_ONCE(chan->syscall_all, 1);
334+ else
335+ WRITE_ONCE(chan->syscall_all, 0);
336+ }
337+
338 /* First ensure that probe events are created for this enabler. */
339 lttng_create_event_if_missing(enabler);
340
341diff --git a/lttng-events.h b/lttng-events.h
342index a36a312..d4d9976 100644
343--- a/lttng-events.h
344+++ b/lttng-events.h
345@@ -292,6 +292,16 @@ struct lttng_uprobe_handler {
346 struct list_head node;
347 };
348
349+enum lttng_syscall_entryexit {
350+ LTTNG_SYSCALL_ENTRY,
351+ LTTNG_SYSCALL_EXIT,
352+};
353+
354+enum lttng_syscall_abi {
355+ LTTNG_SYSCALL_ABI_NATIVE,
356+ LTTNG_SYSCALL_ABI_COMPAT,
357+};
358+
359 /*
360 * lttng_event structure is referred to by the tracing fast path. It must be
361 * kept small.
362@@ -318,6 +328,11 @@ struct lttng_event {
363 struct inode *inode;
364 struct list_head head;
365 } uprobe;
366+ struct {
367+ char *syscall_name;
368+ enum lttng_syscall_entryexit entryexit;
369+ enum lttng_syscall_abi abi;
370+ } syscall;
371 } u;
372 struct list_head list; /* Event list in session */
373 unsigned int metadata_dumped:1;
374@@ -457,10 +472,10 @@ struct lttng_channel {
375 struct lttng_syscall_filter *sc_filter;
376 int header_type; /* 0: unset, 1: compact, 2: large */
377 enum channel_type channel_type;
378+ int syscall_all;
379 unsigned int metadata_dumped:1,
380 sys_enter_registered:1,
381 sys_exit_registered:1,
382- syscall_all:1,
383 tstate:1; /* Transient enable state */
384 };
385
386@@ -653,10 +668,11 @@ void lttng_clock_unref(void);
387 #if defined(CONFIG_HAVE_SYSCALL_TRACEPOINTS)
388 int lttng_syscalls_register(struct lttng_channel *chan, void *filter);
389 int lttng_syscalls_unregister(struct lttng_channel *chan);
390+int lttng_syscalls_destroy(struct lttng_channel *chan);
391 int lttng_syscall_filter_enable(struct lttng_channel *chan,
392- const char *name);
393+ struct lttng_event *event);
394 int lttng_syscall_filter_disable(struct lttng_channel *chan,
395- const char *name);
396+ struct lttng_event *event);
397 long lttng_channel_syscall_mask(struct lttng_channel *channel,
398 struct lttng_kernel_syscall_mask __user *usyscall_mask);
399 #else
400@@ -670,14 +686,19 @@ static inline int lttng_syscalls_unregister(struct lttng_channel *chan)
401 return 0;
402 }
403
404+static inline int lttng_syscalls_destroy(struct lttng_channel *chan)
405+{
406+ return 0;
407+}
408+
409 static inline int lttng_syscall_filter_enable(struct lttng_channel *chan,
410- const char *name)
411+ struct lttng_event *event);
412 {
413 return -ENOSYS;
414 }
415
416 static inline int lttng_syscall_filter_disable(struct lttng_channel *chan,
417- const char *name)
418+ struct lttng_event *event);
419 {
420 return -ENOSYS;
421 }
422diff --git a/lttng-syscalls.c b/lttng-syscalls.c
423index 97f1ba9..26cead6 100644
424--- a/lttng-syscalls.c
425+++ b/lttng-syscalls.c
426@@ -367,8 +367,10 @@ const struct trace_syscall_entry compat_sc_exit_table[] = {
427 #undef CREATE_SYSCALL_TABLE
428
429 struct lttng_syscall_filter {
430- DECLARE_BITMAP(sc, NR_syscalls);
431- DECLARE_BITMAP(sc_compat, NR_compat_syscalls);
432+ DECLARE_BITMAP(sc_entry, NR_syscalls);
433+ DECLARE_BITMAP(sc_exit, NR_syscalls);
434+ DECLARE_BITMAP(sc_compat_entry, NR_compat_syscalls);
435+ DECLARE_BITMAP(sc_compat_exit, NR_compat_syscalls);
436 };
437
438 static void syscall_entry_unknown(struct lttng_event *event,
439@@ -391,29 +393,23 @@ void syscall_entry_probe(void *__data, struct pt_regs *regs, long id)
440 size_t table_len;
441
442 if (unlikely(in_compat_syscall())) {
443- struct lttng_syscall_filter *filter;
444-
445- filter = lttng_rcu_dereference(chan->sc_filter);
446- if (filter) {
447- if (id < 0 || id >= NR_compat_syscalls
448- || !test_bit(id, filter->sc_compat)) {
449- /* System call filtered out. */
450- return;
451- }
452+ struct lttng_syscall_filter *filter = chan->sc_filter;
453+
454+ if (id < 0 || id >= NR_compat_syscalls
455+ || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_compat_entry))) {
456+ /* System call filtered out. */
457+ return;
458 }
459 table = compat_sc_table;
460 table_len = ARRAY_SIZE(compat_sc_table);
461 unknown_event = chan->sc_compat_unknown;
462 } else {
463- struct lttng_syscall_filter *filter;
464-
465- filter = lttng_rcu_dereference(chan->sc_filter);
466- if (filter) {
467- if (id < 0 || id >= NR_syscalls
468- || !test_bit(id, filter->sc)) {
469- /* System call filtered out. */
470- return;
471- }
472+ struct lttng_syscall_filter *filter = chan->sc_filter;
473+
474+ if (id < 0 || id >= NR_syscalls
475+ || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_entry))) {
476+ /* System call filtered out. */
477+ return;
478 }
479 table = sc_table;
480 table_len = ARRAY_SIZE(sc_table);
481@@ -545,29 +541,23 @@ void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret)
482
483 id = syscall_get_nr(current, regs);
484 if (unlikely(in_compat_syscall())) {
485- struct lttng_syscall_filter *filter;
486-
487- filter = lttng_rcu_dereference(chan->sc_filter);
488- if (filter) {
489- if (id < 0 || id >= NR_compat_syscalls
490- || !test_bit(id, filter->sc_compat)) {
491- /* System call filtered out. */
492- return;
493- }
494+ struct lttng_syscall_filter *filter = chan->sc_filter;
495+
496+ if (id < 0 || id >= NR_compat_syscalls
497+ || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_compat_exit))) {
498+ /* System call filtered out. */
499+ return;
500 }
501 table = compat_sc_exit_table;
502 table_len = ARRAY_SIZE(compat_sc_exit_table);
503 unknown_event = chan->compat_sc_exit_unknown;
504 } else {
505- struct lttng_syscall_filter *filter;
506-
507- filter = lttng_rcu_dereference(chan->sc_filter);
508- if (filter) {
509- if (id < 0 || id >= NR_syscalls
510- || !test_bit(id, filter->sc)) {
511- /* System call filtered out. */
512- return;
513- }
514+ struct lttng_syscall_filter *filter = chan->sc_filter;
515+
516+ if (id < 0 || id >= NR_syscalls
517+ || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_exit))) {
518+ /* System call filtered out. */
519+ return;
520 }
521 table = sc_exit_table;
522 table_len = ARRAY_SIZE(sc_exit_table);
523@@ -713,27 +703,23 @@ int fill_table(const struct trace_syscall_entry *table, size_t table_len,
524 memset(&ev, 0, sizeof(ev));
525 switch (type) {
526 case SC_TYPE_ENTRY:
527- strncpy(ev.name, SYSCALL_ENTRY_STR,
528- LTTNG_KERNEL_SYM_NAME_LEN);
529+ ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
530+ ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
531 break;
532 case SC_TYPE_EXIT:
533- strncpy(ev.name, SYSCALL_EXIT_STR,
534- LTTNG_KERNEL_SYM_NAME_LEN);
535+ ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
536+ ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
537 break;
538 case SC_TYPE_COMPAT_ENTRY:
539- strncpy(ev.name, COMPAT_SYSCALL_ENTRY_STR,
540- LTTNG_KERNEL_SYM_NAME_LEN);
541+ ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
542+ ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
543 break;
544 case SC_TYPE_COMPAT_EXIT:
545- strncpy(ev.name, COMPAT_SYSCALL_EXIT_STR,
546- LTTNG_KERNEL_SYM_NAME_LEN);
547- break;
548- default:
549- BUG_ON(1);
550+ ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
551+ ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
552 break;
553 }
554- strncat(ev.name, desc->name,
555- LTTNG_KERNEL_SYM_NAME_LEN - strlen(ev.name) - 1);
556+ strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
557 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
558 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
559 chan_table[i] = _lttng_event_create(chan, &ev, filter,
560@@ -803,6 +789,8 @@ int lttng_syscalls_register(struct lttng_channel *chan, void *filter)
561 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
562 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
563 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
564+ ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
565+ ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
566 chan->sc_unknown = _lttng_event_create(chan, &ev, filter,
567 desc,
568 ev.instrumentation);
569@@ -820,6 +808,8 @@ int lttng_syscalls_register(struct lttng_channel *chan, void *filter)
570 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
571 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
572 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
573+ ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
574+ ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
575 chan->sc_compat_unknown = _lttng_event_create(chan, &ev, filter,
576 desc,
577 ev.instrumentation);
578@@ -837,6 +827,8 @@ int lttng_syscalls_register(struct lttng_channel *chan, void *filter)
579 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
580 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
581 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
582+ ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
583+ ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
584 chan->compat_sc_exit_unknown = _lttng_event_create(chan, &ev,
585 filter, desc,
586 ev.instrumentation);
587@@ -854,6 +846,8 @@ int lttng_syscalls_register(struct lttng_channel *chan, void *filter)
588 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
589 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
590 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
591+ ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
592+ ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
593 chan->sc_exit_unknown = _lttng_event_create(chan, &ev, filter,
594 desc, ev.instrumentation);
595 WARN_ON_ONCE(!chan->sc_exit_unknown);
596@@ -883,6 +877,14 @@ int lttng_syscalls_register(struct lttng_channel *chan, void *filter)
597 if (ret)
598 return ret;
599 #endif
600+
601+ if (!chan->sc_filter) {
602+ chan->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
603+ GFP_KERNEL);
604+ if (!chan->sc_filter)
605+ return -ENOMEM;
606+ }
607+
608 if (!chan->sys_enter_registered) {
609 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
610 (void *) syscall_entry_probe, chan);
611@@ -930,7 +932,11 @@ int lttng_syscalls_unregister(struct lttng_channel *chan)
612 return ret;
613 chan->sys_exit_registered = 0;
614 }
615- /* lttng_event destroy will be performed by lttng_session_destroy() */
616+ return 0;
617+}
618+
619+int lttng_syscalls_destroy(struct lttng_channel *chan)
620+{
621 kfree(chan->sc_table);
622 kfree(chan->sc_exit_table);
623 #ifdef CONFIG_COMPAT
624@@ -993,136 +999,150 @@ uint32_t get_sc_tables_len(void)
625 return ARRAY_SIZE(sc_table) + ARRAY_SIZE(compat_sc_table);
626 }
627
628-int lttng_syscall_filter_enable(struct lttng_channel *chan,
629- const char *name)
630+static
631+const char *get_syscall_name(struct lttng_event *event)
632 {
633- int syscall_nr, compat_syscall_nr, ret;
634- struct lttng_syscall_filter *filter;
635+ size_t prefix_len = 0;
636
637- WARN_ON_ONCE(!chan->sc_table);
638+ WARN_ON_ONCE(event->instrumentation != LTTNG_KERNEL_SYSCALL);
639
640- if (!name) {
641- /* Enable all system calls by removing filter */
642- if (chan->sc_filter) {
643- filter = chan->sc_filter;
644- rcu_assign_pointer(chan->sc_filter, NULL);
645- synchronize_trace();
646- kfree(filter);
647+ switch (event->u.syscall.entryexit) {
648+ case LTTNG_SYSCALL_ENTRY:
649+ switch (event->u.syscall.abi) {
650+ case LTTNG_SYSCALL_ABI_NATIVE:
651+ prefix_len = strlen(SYSCALL_ENTRY_STR);
652+ break;
653+ case LTTNG_SYSCALL_ABI_COMPAT:
654+ prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
655+ break;
656 }
657- chan->syscall_all = 1;
658- return 0;
659- }
660-
661- if (!chan->sc_filter) {
662- if (chan->syscall_all) {
663- /*
664- * All syscalls are already enabled.
665- */
666- return -EEXIST;
667+ break;
668+ case LTTNG_SYSCALL_EXIT:
669+ switch (event->u.syscall.abi) {
670+ case LTTNG_SYSCALL_ABI_NATIVE:
671+ prefix_len = strlen(SYSCALL_EXIT_STR);
672+ break;
673+ case LTTNG_SYSCALL_ABI_COMPAT:
674+ prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
675+ break;
676 }
677- filter = kzalloc(sizeof(struct lttng_syscall_filter),
678- GFP_KERNEL);
679- if (!filter)
680- return -ENOMEM;
681- } else {
682- filter = chan->sc_filter;
683+ break;
684 }
685- syscall_nr = get_syscall_nr(name);
686- compat_syscall_nr = get_compat_syscall_nr(name);
687- if (syscall_nr < 0 && compat_syscall_nr < 0) {
688- ret = -ENOENT;
689- goto error;
690+ WARN_ON_ONCE(prefix_len == 0);
691+ return event->desc->name + prefix_len;
692+}
693+
694+int lttng_syscall_filter_enable(struct lttng_channel *chan,
695+ struct lttng_event *event)
696+{
697+ struct lttng_syscall_filter *filter = chan->sc_filter;
698+ const char *syscall_name;
699+ unsigned long *bitmap;
700+ int syscall_nr;
701+
702+ WARN_ON_ONCE(!chan->sc_table);
703+
704+ syscall_name = get_syscall_name(event);
705+
706+ switch (event->u.syscall.abi) {
707+ case LTTNG_SYSCALL_ABI_NATIVE:
708+ syscall_nr = get_syscall_nr(syscall_name);
709+ break;
710+ case LTTNG_SYSCALL_ABI_COMPAT:
711+ syscall_nr = get_compat_syscall_nr(syscall_name);
712+ break;
713+ default:
714+ return -EINVAL;
715 }
716- if (syscall_nr >= 0) {
717- if (test_bit(syscall_nr, filter->sc)) {
718- ret = -EEXIST;
719- goto error;
720+ if (syscall_nr < 0)
721+ return -ENOENT;
722+
723+
724+ switch (event->u.syscall.entryexit) {
725+ case LTTNG_SYSCALL_ENTRY:
726+ switch (event->u.syscall.abi) {
727+ case LTTNG_SYSCALL_ABI_NATIVE:
728+ bitmap = filter->sc_entry;
729+ break;
730+ case LTTNG_SYSCALL_ABI_COMPAT:
731+ bitmap = filter->sc_compat_entry;
732+ break;
733 }
734- bitmap_set(filter->sc, syscall_nr, 1);
735- }
736- if (compat_syscall_nr >= 0) {
737- if (test_bit(compat_syscall_nr, filter->sc_compat)) {
738- ret = -EEXIST;
739- goto error;
740+ break;
741+ case LTTNG_SYSCALL_EXIT:
742+ switch (event->u.syscall.abi) {
743+ case LTTNG_SYSCALL_ABI_NATIVE:
744+ bitmap = filter->sc_exit;
745+ break;
746+ case LTTNG_SYSCALL_ABI_COMPAT:
747+ bitmap = filter->sc_compat_exit;
748+ break;
749 }
750- bitmap_set(filter->sc_compat, compat_syscall_nr, 1);
751+ break;
752+ default:
753+ return -EINVAL;
754 }
755- if (!chan->sc_filter)
756- rcu_assign_pointer(chan->sc_filter, filter);
757+ if (test_bit(syscall_nr, bitmap))
758+ return -EEXIST;
759+ bitmap_set(bitmap, syscall_nr, 1);
760 return 0;
761-
762-error:
763- if (!chan->sc_filter)
764- kfree(filter);
765- return ret;
766 }
767
768 int lttng_syscall_filter_disable(struct lttng_channel *chan,
769- const char *name)
770+ struct lttng_event *event)
771 {
772- int syscall_nr, compat_syscall_nr, ret;
773- struct lttng_syscall_filter *filter;
774+ struct lttng_syscall_filter *filter = chan->sc_filter;
775+ const char *syscall_name;
776+ unsigned long *bitmap;
777+ int syscall_nr;
778
779 WARN_ON_ONCE(!chan->sc_table);
780
781- if (!chan->sc_filter) {
782- if (!chan->syscall_all)
783- return -EEXIST;
784- filter = kzalloc(sizeof(struct lttng_syscall_filter),
785- GFP_KERNEL);
786- if (!filter)
787- return -ENOMEM;
788- /* Trace all system calls, then apply disable. */
789- bitmap_set(filter->sc, 0, NR_syscalls);
790- bitmap_set(filter->sc_compat, 0, NR_compat_syscalls);
791- } else {
792- filter = chan->sc_filter;
793+ syscall_name = get_syscall_name(event);
794+
795+ switch (event->u.syscall.abi) {
796+ case LTTNG_SYSCALL_ABI_NATIVE:
797+ syscall_nr = get_syscall_nr(syscall_name);
798+ break;
799+ case LTTNG_SYSCALL_ABI_COMPAT:
800+ syscall_nr = get_compat_syscall_nr(syscall_name);
801+ break;
802+ default:
803+ return -EINVAL;
804 }
805+ if (syscall_nr < 0)
806+ return -ENOENT;
807
808- if (!name) {
809- /* Fail if all syscalls are already disabled. */
810- if (bitmap_empty(filter->sc, NR_syscalls)
811- && bitmap_empty(filter->sc_compat,
812- NR_compat_syscalls)) {
813- ret = -EEXIST;
814- goto error;
815- }
816
817- /* Disable all system calls */
818- bitmap_clear(filter->sc, 0, NR_syscalls);
819- bitmap_clear(filter->sc_compat, 0, NR_compat_syscalls);
820- goto apply_filter;
821- }
822- syscall_nr = get_syscall_nr(name);
823- compat_syscall_nr = get_compat_syscall_nr(name);
824- if (syscall_nr < 0 && compat_syscall_nr < 0) {
825- ret = -ENOENT;
826- goto error;
827- }
828- if (syscall_nr >= 0) {
829- if (!test_bit(syscall_nr, filter->sc)) {
830- ret = -EEXIST;
831- goto error;
832+ switch (event->u.syscall.entryexit) {
833+ case LTTNG_SYSCALL_ENTRY:
834+ switch (event->u.syscall.abi) {
835+ case LTTNG_SYSCALL_ABI_NATIVE:
836+ bitmap = filter->sc_entry;
837+ break;
838+ case LTTNG_SYSCALL_ABI_COMPAT:
839+ bitmap = filter->sc_compat_entry;
840+ break;
841 }
842- bitmap_clear(filter->sc, syscall_nr, 1);
843- }
844- if (compat_syscall_nr >= 0) {
845- if (!test_bit(compat_syscall_nr, filter->sc_compat)) {
846- ret = -EEXIST;
847- goto error;
848+ break;
849+ case LTTNG_SYSCALL_EXIT:
850+ switch (event->u.syscall.abi) {
851+ case LTTNG_SYSCALL_ABI_NATIVE:
852+ bitmap = filter->sc_exit;
853+ break;
854+ case LTTNG_SYSCALL_ABI_COMPAT:
855+ bitmap = filter->sc_compat_exit;
856+ break;
857 }
858- bitmap_clear(filter->sc_compat, compat_syscall_nr, 1);
859+ break;
860+ default:
861+ return -EINVAL;
862 }
863-apply_filter:
864- if (!chan->sc_filter)
865- rcu_assign_pointer(chan->sc_filter, filter);
866- chan->syscall_all = 0;
867- return 0;
868+ if (!test_bit(syscall_nr, bitmap))
869+ return -EEXIST;
870+ bitmap_clear(bitmap, syscall_nr, 1);
871
872-error:
873- if (!chan->sc_filter)
874- kfree(filter);
875- return ret;
876+ return 0;
877 }
878
879 static
880@@ -1236,6 +1256,9 @@ const struct file_operations lttng_syscall_list_fops = {
881 .release = seq_release,
882 };
883
884+/*
885+ * A syscall is enabled if it is traced for either entry or exit.
886+ */
887 long lttng_channel_syscall_mask(struct lttng_channel *channel,
888 struct lttng_kernel_syscall_mask __user *usyscall_mask)
889 {
890@@ -1262,8 +1285,9 @@ long lttng_channel_syscall_mask(struct lttng_channel *channel,
891 char state;
892
893 if (channel->sc_table) {
894- if (filter)
895- state = test_bit(bit, filter->sc);
896+ if (!READ_ONCE(channel->syscall_all) && filter)
897+ state = test_bit(bit, filter->sc_entry)
898+ || test_bit(bit, filter->sc_exit);
899 else
900 state = 1;
901 } else {
902@@ -1275,9 +1299,11 @@ long lttng_channel_syscall_mask(struct lttng_channel *channel,
903 char state;
904
905 if (channel->compat_sc_table) {
906- if (filter)
907+ if (!READ_ONCE(channel->syscall_all) && filter)
908 state = test_bit(bit - ARRAY_SIZE(sc_table),
909- filter->sc_compat);
910+ filter->sc_compat_entry)
911+ || test_bit(bit - ARRAY_SIZE(sc_table),
912+ filter->sc_compat_exit);
913 else
914 state = 1;
915 } else {
916--
9172.19.1
918