diff options
author | Beau Belgrave <beaub@linux.microsoft.com> | 2022-03-08 14:28:07 -0800 |
---|---|---|
committer | Steven Rostedt (Google) <rostedt@goodmis.org> | 2022-03-15 14:33:20 -0400 |
commit | 089331d47325d3f55016ed3d1f79ffd2754fb19e (patch) | |
tree | be7460b7e6171017a3a0806cf0d46510d33f0e3f | |
parent | bc47ee4844d6b7d7351536cd99d35848c4449689 (diff) | |
download | linux-089331d47325d3f55016ed3d1f79ffd2754fb19e.tar.bz2 |
user_events: Add trace event call as root for low permission cases
Tracefs by default is locked down heavily. System operators can open up
some files, such as user_events to a broader set of users. These users
do not have access within tracefs beyond just the user_event files. Due
to this restriction the trace_add_event_call/remove calls will silently
fail since the caller does not have permissions to create directories.
To fix this trace_add_event_call/remove calls will be issued with
override creds of the global root UID. Creds are reverted immediately
afterward.
Link: https://lkml.kernel.org/r/20220308222807.2040-1-beaub@linux.microsoft.com
Signed-off-by: Beau Belgrave <beaub@linux.microsoft.com>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
-rw-r--r-- | kernel/trace/trace_events_user.c | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c index e10ad057e797..8b3d241a31c2 100644 --- a/kernel/trace/trace_events_user.c +++ b/kernel/trace/trace_events_user.c @@ -562,6 +562,41 @@ static struct trace_event_functions user_event_funcs = { .trace = user_event_print_trace, }; +static int user_event_set_call_visible(struct user_event *user, bool visible) +{ + int ret; + const struct cred *old_cred; + struct cred *cred; + + cred = prepare_creds(); + + if (!cred) + return -ENOMEM; + + /* + * While by default tracefs is locked down, systems can be configured + * to allow user_event files to be less locked down. The extreme case + * being "other" has read/write access to user_events_data/status. + * + * When not locked down, processes may not have have permissions to + * add/remove calls themselves to tracefs. We need to temporarily + * switch to root file permission to allow for this scenario. + */ + cred->fsuid = GLOBAL_ROOT_UID; + + old_cred = override_creds(cred); + + if (visible) + ret = trace_add_event_call(&user->call); + else + ret = trace_remove_event_call(&user->call); + + revert_creds(old_cred); + put_cred(cred); + + return ret; +} + static int destroy_user_event(struct user_event *user) { int ret = 0; @@ -569,7 +604,7 @@ static int destroy_user_event(struct user_event *user) /* Must destroy fields before call removal */ user_event_destroy_fields(user); - ret = trace_remove_event_call(&user->call); + ret = user_event_set_call_visible(user, false); if (ret) return ret; @@ -1049,7 +1084,7 @@ static int user_event_trace_register(struct user_event *user) if (!ret) return -ENODEV; - ret = trace_add_event_call(&user->call); + ret = user_event_set_call_visible(user, true); if (ret) unregister_trace_event(&user->call.event); |