History

Merge tag 'trace-v5.16-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull tracing fixes from Steven Rostedt: "Tracing, ftrace and tracefs fixes: - Have tracefs honor the gid mount option - Have new files in tracefs inherit the parent ownership - Have direct_ops unregister when it has no more functions - Properly clean up the ops when unregistering multi direct ops - Add a sample module to test the multiple direct ops - Fix memory leak in error path of __create_synth_event()" * tag 'trace-v5.16-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: tracing: Fix possible memory leak in __create_synth_event() error path ftrace/samples: Add module to test multi direct modify interface ftrace: Add cleanup to unregister_ftrace_direct_multi ftrace: Use direct_ops hash in unregister_ftrace_direct tracefs: Set all files to the same group ownership as the mount option tracefs: Have new files inherit the ownership of their parent

Linus Torvalds committed 4 years ago

Commit 257dcf22 parents 0d21e66 c24be245 files · +242 −6Browse files

Unified · Split

5 files
  1. fs/tracefs/inode.c +76 −0
  2. kernel/trace/ftrace.c +7 −1
  3. kernel/trace/trace_events_synth.c +6 −5
  4. samples/ftrace/Makefile +1 −0
  5. samples/ftrace/ftrace-direct-multi-modify.c +152 −0
fs/tracefs/inode.c+76−0
@@ -161,6 +161,77 @@ struct tracefs_fs_info { · 160 unmodified lines
161161 struct tracefs_mount_opts mount_opts;
162162 };
163163
164+static void change_gid(struct dentry *dentry, kgid_t gid)
165+{
166+ if (!dentry->d_inode)
167+ return;
168+ dentry->d_inode->i_gid = gid;
169+}
170+
171+/*
172+ * Taken from d_walk, but without he need for handling renames.
173+ * Nothing can be renamed while walking the list, as tracefs
174+ * does not support renames. This is only called when mounting
175+ * or remounting the file system, to set all the files to
176+ * the given gid.
177+ */
178+static void set_gid(struct dentry *parent, kgid_t gid)
179+{
180+ struct dentry *this_parent;
181+ struct list_head *next;
182+
183+ this_parent = parent;
184+ spin_lock(&this_parent->d_lock);
185+
186+ change_gid(this_parent, gid);
187+repeat:
188+ next = this_parent->d_subdirs.next;
189+resume:
190+ while (next != &this_parent->d_subdirs) {
191+ struct list_head *tmp = next;
192+ struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
193+ next = tmp->next;
194+
195+ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
196+
197+ change_gid(dentry, gid);
198+
199+ if (!list_empty(&dentry->d_subdirs)) {
200+ spin_unlock(&this_parent->d_lock);
201+ spin_release(&dentry->d_lock.dep_map, _RET_IP_);
202+ this_parent = dentry;
203+ spin_acquire(&this_parent->d_lock.dep_map, 0, 1, _RET_IP_);
204+ goto repeat;
205+ }
206+ spin_unlock(&dentry->d_lock);
207+ }
208+ /*
209+ * All done at this level ... ascend and resume the search.
210+ */
211+ rcu_read_lock();
212+ascend:
213+ if (this_parent != parent) {
214+ struct dentry *child = this_parent;
215+ this_parent = child->d_parent;
216+
217+ spin_unlock(&child->d_lock);
218+ spin_lock(&this_parent->d_lock);
219+
220+ /* go into the first sibling still alive */
221+ do {
222+ next = child->d_child.next;
223+ if (next == &this_parent->d_subdirs)
224+ goto ascend;
225+ child = list_entry(next, struct dentry, d_child);
226+ } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED));
227+ rcu_read_unlock();
228+ goto resume;
229+ }
230+ rcu_read_unlock();
231+ spin_unlock(&this_parent->d_lock);
232+ return;
233+}
234+
164235 static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts)
165236 {
166237 substring_t args[MAX_OPT_ARGS];
@@ -193,6 +264,7 @@ static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts) · 26 unmodified lines
193264 if (!gid_valid(gid))
194265 return -EINVAL;
195266 opts->gid = gid;
267+ set_gid(tracefs_mount->mnt_root, gid);
196268 break;
197269 case Opt_mode:
198270 if (match_octal(&args[0], &option))
@@ -414,6 +486,8 @@ struct dentry *tracefs_create_file(const char *name, umode_t mode, · 215 unmodified lines
414486 inode->i_mode = mode;
415487 inode->i_fop = fops ? fops : &tracefs_file_operations;
416488 inode->i_private = data;
489+ inode->i_uid = d_inode(dentry->d_parent)->i_uid;
490+ inode->i_gid = d_inode(dentry->d_parent)->i_gid;
417491 d_instantiate(dentry, inode);
418492 fsnotify_create(dentry->d_parent->d_inode, dentry);
419493 return end_creating(dentry);
@@ -436,6 +510,8 @@ static struct dentry *__create_dir(const char *name, struct dentry *parent, · 16 unmodified lines
436510 inode->i_mode = S_IFDIR | S_IRWXU | S_IRUSR| S_IRGRP | S_IXUSR | S_IXGRP;
437511 inode->i_op = ops;
438512 inode->i_fop = &simple_dir_operations;
513+ inode->i_uid = d_inode(dentry->d_parent)->i_uid;
514+ inode->i_gid = d_inode(dentry->d_parent)->i_gid;
439515
440516 /* directory inodes start off with i_nlink == 2 (for "." entry) */
441517 inc_nlink(inode);
kernel/trace/ftrace.c+7−1
@@ -5217,6 +5217,7 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr) · 5216 unmodified lines
52175217 {
52185218 struct ftrace_direct_func *direct;
52195219 struct ftrace_func_entry *entry;
5220+ struct ftrace_hash *hash;
52205221 int ret = -ENODEV;
52215222
52225223 mutex_lock(&direct_mutex);
@@ -5225,7 +5226,8 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr) · 2 unmodified lines
52255226 if (!entry)
52265227 goto out_unlock;
52275228
5228− if (direct_functions->count == 1)
5229+ hash = direct_ops.func_hash->filter_hash;
5230+ if (hash->count == 1)
52295231 unregister_ftrace_function(&direct_ops);
52305232
52315233 ret = ftrace_set_filter_ip(&direct_ops, ip, 1, 0);
@@ -5540,6 +5542,10 @@ int unregister_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr) · 308 unmodified lines
55405542 err = unregister_ftrace_function(ops);
55415543 remove_direct_functions_hash(hash, addr);
55425544 mutex_unlock(&direct_mutex);
5545+
5546+ /* cleanup for possible another register call */
5547+ ops->func = NULL;
5548+ ops->trampoline = 0;
55435549 return err;
55445550 }
55455551 EXPORT_SYMBOL_GPL(unregister_ftrace_direct_multi);
kernel/trace/trace_events_synth.c+6−5
@@ -1237,9 +1237,8 @@ static int __create_synth_event(const char *name, const char *raw_fields) · 1236 unmodified lines
12371237 argv + consumed, &consumed,
12381238 &field_version);
12391239 if (IS_ERR(field)) {
1240− argv_free(argv);
12411240 ret = PTR_ERR(field);
1242− goto err;
1241+ goto err_free_arg;
12431242 }
12441243
12451244 /*
@@ -1262,18 +1261,19 @@ static int __create_synth_event(const char *name, const char *raw_fields) · 16 unmodified lines
12621261 if (cmd_version > 1 && n_fields_this_loop >= 1) {
12631262 synth_err(SYNTH_ERR_INVALID_CMD, errpos(field_str));
12641263 ret = -EINVAL;
1265− goto err;
1264+ goto err_free_arg;
12661265 }
12671266
12681267 fields[n_fields++] = field;
12691268 if (n_fields == SYNTH_FIELDS_MAX) {
12701269 synth_err(SYNTH_ERR_TOO_MANY_FIELDS, 0);
12711270 ret = -EINVAL;
1272− goto err;
1271+ goto err_free_arg;
12731272 }
12741273
12751274 n_fields_this_loop++;
12761275 }
1276+ argv_free(argv);
12771277
12781278 if (consumed < argc) {
12791279 synth_err(SYNTH_ERR_INVALID_CMD, 0);
@@ -1281,7 +1281,6 @@ static int __create_synth_event(const char *name, const char *raw_fields) · 1 unmodified line
12811281 goto err;
12821282 }
12831283
1284− argv_free(argv);
12851284 }
12861285
12871286 if (n_fields == 0) {
@@ -1307,6 +1306,8 @@ static int __create_synth_event(const char *name, const char *raw_fields) · 19 unmodified lines
13071306 kfree(saved_fields);
13081307
13091308 return ret;
1309+ err_free_arg:
1310+ argv_free(argv);
13101311 err:
13111312 for (i = 0; i < n_fields; i++)
13121313 free_synth_field(fields[i]);
samples/ftrace/Makefile+1−0
@@ -4,6 +4,7 @@ obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct.o · 3 unmodified lines
44 obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-too.o
55 obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-modify.o
66 obj-$(CONFIG_SAMPLE_FTRACE_DIRECT_MULTI) += ftrace-direct-multi.o
7+obj-$(CONFIG_SAMPLE_FTRACE_DIRECT_MULTI) += ftrace-direct-multi-modify.o
78
89 CFLAGS_sample-trace-array.o := -I$(src)
910 obj-$(CONFIG_SAMPLE_TRACE_ARRAY) += sample-trace-array.o
samples/ftrace/ftrace-direct-multi-modify.c+152−0
@@ -0,0 +1,152 @@
1+// SPDX-License-Identifier: GPL-2.0-only
2+#include <linux/module.h>
3+#include <linux/kthread.h>
4+#include <linux/ftrace.h>
5+#include <asm/asm-offsets.h>
6+
7+void my_direct_func1(unsigned long ip)
8+{
9+ trace_printk("my direct func1 ip %lx\n", ip);
10+}
11+
12+void my_direct_func2(unsigned long ip)
13+{
14+ trace_printk("my direct func2 ip %lx\n", ip);
15+}
16+
17+extern void my_tramp1(void *);
18+extern void my_tramp2(void *);
19+
20+#ifdef CONFIG_X86_64
21+
22+asm (
23+" .pushsection .text, \"ax\", @progbits\n"
24+" .type my_tramp1, @function\n"
25+" .globl my_tramp1\n"
26+" my_tramp1:"
27+" pushq %rbp\n"
28+" movq %rsp, %rbp\n"
29+" pushq %rdi\n"
30+" movq 8(%rbp), %rdi\n"
31+" call my_direct_func1\n"
32+" popq %rdi\n"
33+" leave\n"
34+" ret\n"
35+" .size my_tramp1, .-my_tramp1\n"
36+" .type my_tramp2, @function\n"
37+"\n"
38+" .globl my_tramp2\n"
39+" my_tramp2:"
40+" pushq %rbp\n"
41+" movq %rsp, %rbp\n"
42+" pushq %rdi\n"
43+" movq 8(%rbp), %rdi\n"
44+" call my_direct_func2\n"
45+" popq %rdi\n"
46+" leave\n"
47+" ret\n"
48+" .size my_tramp2, .-my_tramp2\n"
49+" .popsection\n"
50+);
51+
52+#endif /* CONFIG_X86_64 */
53+
54+#ifdef CONFIG_S390
55+
56+asm (
57+" .pushsection .text, \"ax\", @progbits\n"
58+" .type my_tramp1, @function\n"
59+" .globl my_tramp1\n"
60+" my_tramp1:"
61+" lgr %r1,%r15\n"
62+" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
63+" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
64+" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n"
65+" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n"
66+" lgr %r2,%r0\n"
67+" brasl %r14,my_direct_func1\n"
68+" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n"
69+" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
70+" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
71+" lgr %r1,%r0\n"
72+" br %r1\n"
73+" .size my_tramp1, .-my_tramp1\n"
74+"\n"
75+" .type my_tramp2, @function\n"
76+" .globl my_tramp2\n"
77+" my_tramp2:"
78+" lgr %r1,%r15\n"
79+" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
80+" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
81+" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n"
82+" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n"
83+" lgr %r2,%r0\n"
84+" brasl %r14,my_direct_func2\n"
85+" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n"
86+" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
87+" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
88+" lgr %r1,%r0\n"
89+" br %r1\n"
90+" .size my_tramp2, .-my_tramp2\n"
91+" .popsection\n"
92+);
93+
94+#endif /* CONFIG_S390 */
95+
96+static unsigned long my_tramp = (unsigned long)my_tramp1;
97+static unsigned long tramps[2] = {
98+ (unsigned long)my_tramp1,
99+ (unsigned long)my_tramp2,
100+};
101+
102+static struct ftrace_ops direct;
103+
104+static int simple_thread(void *arg)
105+{
106+ static int t;
107+ int ret = 0;
108+
109+ while (!kthread_should_stop()) {
110+ set_current_state(TASK_INTERRUPTIBLE);
111+ schedule_timeout(2 * HZ);
112+
113+ if (ret)
114+ continue;
115+ t ^= 1;
116+ ret = modify_ftrace_direct_multi(&direct, tramps[t]);
117+ if (!ret)
118+ my_tramp = tramps[t];
119+ WARN_ON_ONCE(ret);
120+ }
121+
122+ return 0;
123+}
124+
125+static struct task_struct *simple_tsk;
126+
127+static int __init ftrace_direct_multi_init(void)
128+{
129+ int ret;
130+
131+ ftrace_set_filter_ip(&direct, (unsigned long) wake_up_process, 0, 0);
132+ ftrace_set_filter_ip(&direct, (unsigned long) schedule, 0, 0);
133+
134+ ret = register_ftrace_direct_multi(&direct, my_tramp);
135+
136+ if (!ret)
137+ simple_tsk = kthread_run(simple_thread, NULL, "event-sample-fn");
138+ return ret;
139+}
140+
141+static void __exit ftrace_direct_multi_exit(void)
142+{
143+ kthread_stop(simple_tsk);
144+ unregister_ftrace_direct_multi(&direct, my_tramp);
145+}
146+
147+module_init(ftrace_direct_multi_init);
148+module_exit(ftrace_direct_multi_exit);
149+
150+MODULE_AUTHOR("Jiri Olsa");
151+MODULE_DESCRIPTION("Example use case of using modify_ftrace_direct_multi()");
152+MODULE_LICENSE("GPL");

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t