diff options
5 files changed, 353 insertions, 0 deletions
diff --git a/meta/recipes-kernel/lttng/lttng-modules/0001-Fix-memory-leaks-on-event-destroy.patch b/meta/recipes-kernel/lttng/lttng-modules/0001-Fix-memory-leaks-on-event-destroy.patch new file mode 100644 index 0000000000..21da932a75 --- /dev/null +++ b/meta/recipes-kernel/lttng/lttng-modules/0001-Fix-memory-leaks-on-event-destroy.patch | |||
@@ -0,0 +1,58 @@ | |||
1 | From b3fdf78b15beb940918da1e41eb68e24ba31bb87 Mon Sep 17 00:00:00 2001 | ||
2 | From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | ||
3 | Date: Wed, 3 Mar 2021 10:10:16 -0500 | ||
4 | Subject: [PATCH 1/4] Fix: memory leaks on event destroy | ||
5 | |||
6 | Both filter runtime and event enabler ref objects are owned by the | ||
7 | event, but are not freed upon destruction of the event object, thus | ||
8 | leaking memory. | ||
9 | |||
10 | Upstream-status: backport | ||
11 | |||
12 | Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | ||
13 | Change-Id: Ice9b1c18b47584838aea2b965494d3c8391f4c84 | ||
14 | --- | ||
15 | lttng-events.c | 7 +++++++ | ||
16 | lttng-events.h | 1 + | ||
17 | 2 files changed, 8 insertions(+) | ||
18 | |||
19 | diff --git a/lttng-events.c b/lttng-events.c | ||
20 | index f3398adc..984bd341 100644 | ||
21 | --- a/lttng-events.c | ||
22 | +++ b/lttng-events.c | ||
23 | @@ -919,6 +919,8 @@ int _lttng_event_unregister(struct lttng_event *event) | ||
24 | static | ||
25 | void _lttng_event_destroy(struct lttng_event *event) | ||
26 | { | ||
27 | + struct lttng_enabler_ref *enabler_ref, *tmp_enabler_ref; | ||
28 | + | ||
29 | switch (event->instrumentation) { | ||
30 | case LTTNG_KERNEL_TRACEPOINT: | ||
31 | lttng_event_put(event->desc); | ||
32 | @@ -944,6 +946,11 @@ void _lttng_event_destroy(struct lttng_event *event) | ||
33 | } | ||
34 | list_del(&event->list); | ||
35 | lttng_destroy_context(event->ctx); | ||
36 | + lttng_free_event_filter_runtime(event); | ||
37 | + /* Free event enabler refs */ | ||
38 | + list_for_each_entry_safe(enabler_ref, tmp_enabler_ref, | ||
39 | + &event->enablers_ref_head, node) | ||
40 | + kfree(enabler_ref); | ||
41 | kmem_cache_free(event_cache, event); | ||
42 | } | ||
43 | |||
44 | diff --git a/lttng-events.h b/lttng-events.h | ||
45 | index 1b9ab167..13b6abf5 100644 | ||
46 | --- a/lttng-events.h | ||
47 | +++ b/lttng-events.h | ||
48 | @@ -716,6 +716,7 @@ int lttng_enabler_attach_bytecode(struct lttng_enabler *enabler, | ||
49 | struct lttng_kernel_filter_bytecode __user *bytecode); | ||
50 | void lttng_enabler_event_link_bytecode(struct lttng_event *event, | ||
51 | struct lttng_enabler *enabler); | ||
52 | +void lttng_free_event_filter_runtime(struct lttng_event *event); | ||
53 | |||
54 | int lttng_probes_init(void); | ||
55 | |||
56 | -- | ||
57 | 2.19.1 | ||
58 | |||
diff --git a/meta/recipes-kernel/lttng/lttng-modules/0002-Fix-filter-interpreter-early-exits-on-uninitialized-.patch b/meta/recipes-kernel/lttng/lttng-modules/0002-Fix-filter-interpreter-early-exits-on-uninitialized-.patch new file mode 100644 index 0000000000..609690f05c --- /dev/null +++ b/meta/recipes-kernel/lttng/lttng-modules/0002-Fix-filter-interpreter-early-exits-on-uninitialized-.patch | |||
@@ -0,0 +1,159 @@ | |||
1 | From 23a2f61ffc6a656f136fa2044c0c3b8f79766779 Mon Sep 17 00:00:00 2001 | ||
2 | From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Galarneau?= | ||
3 | <jeremie.galarneau@efficios.com> | ||
4 | Date: Wed, 3 Mar 2021 18:52:19 -0500 | ||
5 | Subject: [PATCH 2/4] Fix: filter interpreter early-exits on uninitialized | ||
6 | value | ||
7 | MIME-Version: 1.0 | ||
8 | Content-Type: text/plain; charset=UTF-8 | ||
9 | Content-Transfer-Encoding: 8bit | ||
10 | |||
11 | I observed that syscall filtering on string arguments wouldn't work on | ||
12 | my development machines, both running 5.11.2-arch1-1 (Arch Linux). | ||
13 | |||
14 | For instance, enabling the tracing of the `openat()` syscall with the | ||
15 | 'filename == "/proc/cpuinfo"' filter would not produce events even | ||
16 | though matching events were present in another session that had no | ||
17 | filtering active. The same problem occurred with `execve()`. | ||
18 | |||
19 | I tried a couple of kernel versions before (5.11.1 and 5.10.13, if | ||
20 | memory serves me well) and I had the same problem. Meanwhile, I couldn't | ||
21 | reproduce the problem on various Debian machines (the LTTng CI) nor on a | ||
22 | fresh Ubuntu 20.04 with both the stock kernel and with an updated 5.11.2 | ||
23 | kernel. | ||
24 | |||
25 | I built the lttng-modules with the interpreter debugging printout and | ||
26 | saw the following warning: | ||
27 | LTTng: [debug bytecode in /home/jgalar/EfficiOS/src/lttng-modules/src/lttng-bytecode-interpreter.c:bytecode_interpret@1508] Bytecode warning: loading a NULL string. | ||
28 | |||
29 | After a shedload (yes, a _shed_load) of digging, I figured that the | ||
30 | problem was hidden in plain sight near that logging statement. | ||
31 | |||
32 | In the `BYTECODE_OP_LOAD_FIELD_REF_USER_STRING` operation, the 'ax' | ||
33 | register's 'user_str' is initialized with the stack value (the user | ||
34 | space string's address in our case). However, a NULL check is performed | ||
35 | against the register's 'str' member. | ||
36 | |||
37 | I initialy suspected that both members would be part of the same union | ||
38 | and alias each-other, but they are actually contiguous in a structure. | ||
39 | |||
40 | On the unaffected machines, I could confirm that the `str` member was | ||
41 | uninitialized to a non-zero value causing the condition to evaluate to | ||
42 | false. | ||
43 | |||
44 | Francis Deslauriers reproduced the problem by initializing the | ||
45 | interpreter stack to zero. | ||
46 | |||
47 | I am unsure of the exact kernel configuration option that reveals this | ||
48 | issue on Arch Linux, but my kernel has the following option enabled: | ||
49 | |||
50 | CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL: | ||
51 | Zero-initialize any stack variables that may be passed by reference | ||
52 | and had not already been explicitly initialized. This is intended to | ||
53 | eliminate all classes of uninitialized stack variable exploits and | ||
54 | information exposures. | ||
55 | |||
56 | I have not tried to build without this enabled as, anyhow, this seems | ||
57 | to be a legitimate issue. | ||
58 | |||
59 | I have spotted what appears to be an identical problem in | ||
60 | `BYTECODE_OP_LOAD_FIELD_REF_USER_SEQUENCE` and corrected it. However, | ||
61 | I have not exercised that code path. | ||
62 | |||
63 | The commit that introduced this problem is 5b4ad89. | ||
64 | |||
65 | The debug print-out of the `BYTECODE_OP_LOAD_FIELD_REF_USER_STRING` | ||
66 | operation is modified to print the user string (truncated to 31 chars). | ||
67 | |||
68 | Upstream-status: backport | ||
69 | |||
70 | Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com> | ||
71 | Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | ||
72 | Change-Id: I2da3c31b9e3ce0e1b164cf3d2711c0893cbec273 | ||
73 | --- | ||
74 | lttng-filter-interpreter.c | 41 ++++++++++++++++++++++++++++++++++---- | ||
75 | 1 file changed, 37 insertions(+), 4 deletions(-) | ||
76 | |||
77 | diff --git a/lttng-filter-interpreter.c b/lttng-filter-interpreter.c | ||
78 | index 5d572437..6e5a5139 100644 | ||
79 | --- a/lttng-filter-interpreter.c | ||
80 | +++ b/lttng-filter-interpreter.c | ||
81 | @@ -22,7 +22,7 @@ LTTNG_STACK_FRAME_NON_STANDARD(lttng_filter_interpret_bytecode); | ||
82 | * to handle user-space read. | ||
83 | */ | ||
84 | static | ||
85 | -char get_char(struct estack_entry *reg, size_t offset) | ||
86 | +char get_char(const struct estack_entry *reg, size_t offset) | ||
87 | { | ||
88 | if (unlikely(offset >= reg->u.s.seq_len)) | ||
89 | return '\0'; | ||
90 | @@ -593,6 +593,39 @@ end: | ||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | +#ifdef DEBUG | ||
95 | + | ||
96 | +#define DBG_USER_STR_CUTOFF 32 | ||
97 | + | ||
98 | +/* | ||
99 | + * In debug mode, print user string (truncated, if necessary). | ||
100 | + */ | ||
101 | +static inline | ||
102 | +void dbg_load_ref_user_str_printk(const struct estack_entry *user_str_reg) | ||
103 | +{ | ||
104 | + size_t pos = 0; | ||
105 | + char last_char; | ||
106 | + char user_str[DBG_USER_STR_CUTOFF]; | ||
107 | + | ||
108 | + pagefault_disable(); | ||
109 | + do { | ||
110 | + last_char = get_char(user_str_reg, pos); | ||
111 | + user_str[pos] = last_char; | ||
112 | + pos++; | ||
113 | + } while (last_char != '\0' && pos < sizeof(user_str)); | ||
114 | + pagefault_enable(); | ||
115 | + | ||
116 | + user_str[sizeof(user_str) - 1] = '\0'; | ||
117 | + dbg_printk("load field ref user string: '%s%s'\n", user_str, | ||
118 | + last_char != '\0' ? "[...]" : ""); | ||
119 | +} | ||
120 | +#else | ||
121 | +static inline | ||
122 | +void dbg_load_ref_user_str_printk(const struct estack_entry *user_str_reg) | ||
123 | +{ | ||
124 | +} | ||
125 | +#endif | ||
126 | + | ||
127 | /* | ||
128 | * Return 0 (discard), or raise the 0x1 flag (log event). | ||
129 | * Currently, other flags are kept for future extensions and have no | ||
130 | @@ -1313,7 +1346,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, | ||
131 | estack_push(stack, top, ax, bx); | ||
132 | estack_ax(stack, top)->u.s.user_str = | ||
133 | *(const char * const *) &filter_stack_data[ref->offset]; | ||
134 | - if (unlikely(!estack_ax(stack, top)->u.s.str)) { | ||
135 | + if (unlikely(!estack_ax(stack, top)->u.s.user_str)) { | ||
136 | dbg_printk("Filter warning: loading a NULL string.\n"); | ||
137 | ret = -EINVAL; | ||
138 | goto end; | ||
139 | @@ -1322,7 +1355,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, | ||
140 | estack_ax(stack, top)->u.s.literal_type = | ||
141 | ESTACK_STRING_LITERAL_TYPE_NONE; | ||
142 | estack_ax(stack, top)->u.s.user = 1; | ||
143 | - dbg_printk("ref load string %s\n", estack_ax(stack, top)->u.s.str); | ||
144 | + dbg_load_ref_user_str_printk(estack_ax(stack, top)); | ||
145 | next_pc += sizeof(struct load_op) + sizeof(struct field_ref); | ||
146 | PO; | ||
147 | } | ||
148 | @@ -1340,7 +1373,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, | ||
149 | estack_ax(stack, top)->u.s.user_str = | ||
150 | *(const char **) (&filter_stack_data[ref->offset | ||
151 | + sizeof(unsigned long)]); | ||
152 | - if (unlikely(!estack_ax(stack, top)->u.s.str)) { | ||
153 | + if (unlikely(!estack_ax(stack, top)->u.s.user_str)) { | ||
154 | dbg_printk("Filter warning: loading a NULL sequence.\n"); | ||
155 | ret = -EINVAL; | ||
156 | goto end; | ||
157 | -- | ||
158 | 2.19.1 | ||
159 | |||
diff --git a/meta/recipes-kernel/lttng/lttng-modules/0003-fix-mm-tracing-record-slab-name-for-kmem_cache_free-.patch b/meta/recipes-kernel/lttng/lttng-modules/0003-fix-mm-tracing-record-slab-name-for-kmem_cache_free-.patch new file mode 100644 index 0000000000..71f99b80a3 --- /dev/null +++ b/meta/recipes-kernel/lttng/lttng-modules/0003-fix-mm-tracing-record-slab-name-for-kmem_cache_free-.patch | |||
@@ -0,0 +1,91 @@ | |||
1 | From 49c603ef2dc6969f4454f0d849af00ee24bb7f04 Mon Sep 17 00:00:00 2001 | ||
2 | From: Michael Jeanson <mjeanson@efficios.com> | ||
3 | Date: Thu, 4 Mar 2021 16:50:12 -0500 | ||
4 | Subject: [PATCH 3/4] fix: mm, tracing: record slab name for kmem_cache_free() | ||
5 | (v5.12) | ||
6 | |||
7 | See upstream commit: | ||
8 | |||
9 | commit 3544de8ee6e4817278b15fe08658de49abf58954 | ||
10 | Author: Jacob Wen <jian.w.wen@oracle.com> | ||
11 | Date: Wed Feb 24 12:00:55 2021 -0800 | ||
12 | |||
13 | mm, tracing: record slab name for kmem_cache_free() | ||
14 | |||
15 | Currently, a trace record generated by the RCU core is as below. | ||
16 | |||
17 | ... kmem_cache_free: call_site=rcu_core+0x1fd/0x610 ptr=00000000f3b49a66 | ||
18 | |||
19 | It doesn't tell us what the RCU core has freed. | ||
20 | |||
21 | This patch adds the slab name to trace_kmem_cache_free(). | ||
22 | The new format is as follows. | ||
23 | |||
24 | ... kmem_cache_free: call_site=rcu_core+0x1fd/0x610 ptr=0000000037f79c8d name=dentry | ||
25 | ... kmem_cache_free: call_site=rcu_core+0x1fd/0x610 ptr=00000000f78cb7b5 name=sock_inode_cache | ||
26 | ... kmem_cache_free: call_site=rcu_core+0x1fd/0x610 ptr=0000000018768985 name=pool_workqueue | ||
27 | ... kmem_cache_free: call_site=rcu_core+0x1fd/0x610 ptr=000000006a6cb484 name=radix_tree_node | ||
28 | |||
29 | We can use it to understand what the RCU core is going to free. For | ||
30 | example, some users maybe interested in when the RCU core starts | ||
31 | freeing reclaimable slabs like dentry to reduce memory pressure. | ||
32 | |||
33 | Link: https://lkml.kernel.org/r/20201216072804.8838-1-jian.w.wen@oracle.com | ||
34 | |||
35 | Upstream-status: backport | ||
36 | |||
37 | Signed-off-by: Michael Jeanson <mjeanson@efficios.com> | ||
38 | Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | ||
39 | Change-Id: I1ee2fc476614cadcc8d3ac5d8feddc7910e1aa3a | ||
40 | --- | ||
41 | instrumentation/events/lttng-module/kmem.h | 27 ++++++++++++++++++++++ | ||
42 | 1 file changed, 27 insertions(+) | ||
43 | |||
44 | diff --git a/instrumentation/events/lttng-module/kmem.h b/instrumentation/events/lttng-module/kmem.h | ||
45 | index b134620a..d787ea54 100644 | ||
46 | --- a/instrumentation/events/lttng-module/kmem.h | ||
47 | +++ b/instrumentation/events/lttng-module/kmem.h | ||
48 | @@ -87,6 +87,32 @@ LTTNG_TRACEPOINT_EVENT_INSTANCE(kmem_alloc_node, kmem_cache_alloc_node, | ||
49 | TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags, node) | ||
50 | ) | ||
51 | |||
52 | +#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,12,0)) | ||
53 | +LTTNG_TRACEPOINT_EVENT(kfree, | ||
54 | + | ||
55 | + TP_PROTO(unsigned long call_site, const void *ptr), | ||
56 | + | ||
57 | + TP_ARGS(call_site, ptr), | ||
58 | + | ||
59 | + TP_FIELDS( | ||
60 | + ctf_integer_hex(unsigned long, call_site, call_site) | ||
61 | + ctf_integer_hex(const void *, ptr, ptr) | ||
62 | + ) | ||
63 | +) | ||
64 | + | ||
65 | +LTTNG_TRACEPOINT_EVENT(kmem_cache_free, | ||
66 | + | ||
67 | + TP_PROTO(unsigned long call_site, const void *ptr, const char *name), | ||
68 | + | ||
69 | + TP_ARGS(call_site, ptr, name), | ||
70 | + | ||
71 | + TP_FIELDS( | ||
72 | + ctf_integer_hex(unsigned long, call_site, call_site) | ||
73 | + ctf_integer_hex(const void *, ptr, ptr) | ||
74 | + ctf_string(name, name) | ||
75 | + ) | ||
76 | +) | ||
77 | +#else | ||
78 | LTTNG_TRACEPOINT_EVENT_CLASS(kmem_free, | ||
79 | |||
80 | TP_PROTO(unsigned long call_site, const void *ptr), | ||
81 | @@ -114,6 +140,7 @@ LTTNG_TRACEPOINT_EVENT_INSTANCE(kmem_free, kmem_cache_free, | ||
82 | |||
83 | TP_ARGS(call_site, ptr) | ||
84 | ) | ||
85 | +#endif | ||
86 | |||
87 | #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(3,3,0)) | ||
88 | LTTNG_TRACEPOINT_EVENT_MAP(mm_page_free, kmem_mm_page_free, | ||
89 | -- | ||
90 | 2.19.1 | ||
91 | |||
diff --git a/meta/recipes-kernel/lttng/lttng-modules/0004-Fix-kretprobe-null-ptr-deref-on-session-destroy.patch b/meta/recipes-kernel/lttng/lttng-modules/0004-Fix-kretprobe-null-ptr-deref-on-session-destroy.patch new file mode 100644 index 0000000000..8a839c2b43 --- /dev/null +++ b/meta/recipes-kernel/lttng/lttng-modules/0004-Fix-kretprobe-null-ptr-deref-on-session-destroy.patch | |||
@@ -0,0 +1,41 @@ | |||
1 | From 92cc3e7f76a545a2cd4828576971f1eea83f4e68 Mon Sep 17 00:00:00 2001 | ||
2 | From: Francis Deslauriers <francis.deslauriers@efficios.com> | ||
3 | Date: Wed, 17 Mar 2021 10:40:56 -0400 | ||
4 | Subject: [PATCH 4/4] Fix: kretprobe: null ptr deref on session destroy | ||
5 | |||
6 | The `filter_bytecode_runtime_head` list is currently not initialized for | ||
7 | the return event of the kretprobe. This caused a kernel null ptr | ||
8 | dereference when destroying a session. It can reproduced with the | ||
9 | following commands: | ||
10 | |||
11 | lttng create | ||
12 | lttng enable-event -k --function=lttng_test_filter_event_write my_event | ||
13 | lttng start | ||
14 | lttng stop | ||
15 | lttng destroy | ||
16 | |||
17 | Upstream-status: backport | ||
18 | |||
19 | Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com> | ||
20 | Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | ||
21 | Change-Id: I1162ce8b10dd7237a26331531f048346b984eee7 | ||
22 | --- | ||
23 | lttng-events.c | 2 ++ | ||
24 | 1 file changed, 2 insertions(+) | ||
25 | |||
26 | diff --git a/lttng-events.c b/lttng-events.c | ||
27 | index 984bd341..3450fa40 100644 | ||
28 | --- a/lttng-events.c | ||
29 | +++ b/lttng-events.c | ||
30 | @@ -704,6 +704,8 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, | ||
31 | event_return->enabled = 0; | ||
32 | event_return->registered = 1; | ||
33 | event_return->instrumentation = itype; | ||
34 | + INIT_LIST_HEAD(&event_return->bytecode_runtime_head); | ||
35 | + INIT_LIST_HEAD(&event_return->enablers_ref_head); | ||
36 | /* | ||
37 | * Populate lttng_event structure before kretprobe registration. | ||
38 | */ | ||
39 | -- | ||
40 | 2.19.1 | ||
41 | |||
diff --git a/meta/recipes-kernel/lttng/lttng-modules_2.12.5.bb b/meta/recipes-kernel/lttng/lttng-modules_2.12.5.bb index ea36a3464b..5b05c644a6 100644 --- a/meta/recipes-kernel/lttng/lttng-modules_2.12.5.bb +++ b/meta/recipes-kernel/lttng/lttng-modules_2.12.5.bb | |||
@@ -11,6 +11,10 @@ include lttng-platforms.inc | |||
11 | 11 | ||
12 | SRC_URI = "https://lttng.org/files/${BPN}/${BPN}-${PV}.tar.bz2 \ | 12 | SRC_URI = "https://lttng.org/files/${BPN}/${BPN}-${PV}.tar.bz2 \ |
13 | file://Makefile-Do-not-fail-if-CONFIG_TRACEPOINTS-is-not-en.patch \ | 13 | file://Makefile-Do-not-fail-if-CONFIG_TRACEPOINTS-is-not-en.patch \ |
14 | file://0001-Fix-memory-leaks-on-event-destroy.patch \ | ||
15 | file://0002-Fix-filter-interpreter-early-exits-on-uninitialized-.patch \ | ||
16 | file://0003-fix-mm-tracing-record-slab-name-for-kmem_cache_free-.patch \ | ||
17 | file://0004-Fix-kretprobe-null-ptr-deref-on-session-destroy.patch \ | ||
14 | " | 18 | " |
15 | 19 | ||
16 | SRC_URI[sha256sum] = "c4d1a1b42c728e37b6b7947ae16563a011c4b297311aa04d56f9a1791fb5a30a" | 20 | SRC_URI[sha256sum] = "c4d1a1b42c728e37b6b7947ae16563a011c4b297311aa04d56f9a1791fb5a30a" |