Skip to content

Commit 089331d

Browse files
beaubelgraverostedt
authored andcommitted
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>
1 parent bc47ee4 commit 089331d

1 file changed

Lines changed: 37 additions & 2 deletions

File tree

kernel/trace/trace_events_user.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,14 +562,49 @@ static struct trace_event_functions user_event_funcs = {
562562
.trace = user_event_print_trace,
563563
};
564564

565+
static int user_event_set_call_visible(struct user_event *user, bool visible)
566+
{
567+
int ret;
568+
const struct cred *old_cred;
569+
struct cred *cred;
570+
571+
cred = prepare_creds();
572+
573+
if (!cred)
574+
return -ENOMEM;
575+
576+
/*
577+
* While by default tracefs is locked down, systems can be configured
578+
* to allow user_event files to be less locked down. The extreme case
579+
* being "other" has read/write access to user_events_data/status.
580+
*
581+
* When not locked down, processes may not have have permissions to
582+
* add/remove calls themselves to tracefs. We need to temporarily
583+
* switch to root file permission to allow for this scenario.
584+
*/
585+
cred->fsuid = GLOBAL_ROOT_UID;
586+
587+
old_cred = override_creds(cred);
588+
589+
if (visible)
590+
ret = trace_add_event_call(&user->call);
591+
else
592+
ret = trace_remove_event_call(&user->call);
593+
594+
revert_creds(old_cred);
595+
put_cred(cred);
596+
597+
return ret;
598+
}
599+
565600
static int destroy_user_event(struct user_event *user)
566601
{
567602
int ret = 0;
568603

569604
/* Must destroy fields before call removal */
570605
user_event_destroy_fields(user);
571606

572-
ret = trace_remove_event_call(&user->call);
607+
ret = user_event_set_call_visible(user, false);
573608

574609
if (ret)
575610
return ret;
@@ -1049,7 +1084,7 @@ static int user_event_trace_register(struct user_event *user)
10491084
if (!ret)
10501085
return -ENODEV;
10511086

1052-
ret = trace_add_event_call(&user->call);
1087+
ret = user_event_set_call_visible(user, true);
10531088

10541089
if (ret)
10551090
unregister_trace_event(&user->call.event);

0 commit comments

Comments
 (0)