From 704f9c4e582ed3286f009d34a6a1c51158d0300c Mon Sep 17 00:00:00 2001 From: Oscar Bonilla <6f6231@gmail.com> Date: Mon, 3 Dec 2018 08:59:38 -0800 Subject: [PATCH] trace-cmd-record: Add option to run command as a different user This is useful when the traced command should not be run as root. --- Documentation/trace-cmd-record.1.txt | 4 ++++ tracecmd/trace-record.c | 19 +++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Documentation/trace-cmd-record.1.txt b/Documentation/trace-cmd-record.1.txt index 68afa161..5f8d006e 100644 --- a/Documentation/trace-cmd-record.1.txt +++ b/Documentation/trace-cmd-record.1.txt @@ -326,6 +326,10 @@ OPTIONS executed will not be changed. This is useful if you want to monitor the output of the command being executed, but not see the output from trace-cmd. +*--user*:: + Run the command as the specified user. Useful to avoid running the + traced command as root. + EXAMPLES -------- diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 038b2313..634ea50d 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "trace-local.h" #include "trace-msg.h" @@ -1191,7 +1192,7 @@ static void trace_or_sleep(enum trace_type type) sleep(10); } -static void run_cmd(enum trace_type type, int argc, char **argv) +static void run_cmd(enum trace_type type, uid_t euid, int argc, char **argv) { int status; int pid; @@ -1212,6 +1213,10 @@ static void run_cmd(enum trace_type type, int argc, char **argv) dup2(save_stdout, 1); close(save_stdout); } + if (setuid(euid)) + die("Failed to setuid to %d: %s", euid, strerror(errno)); + if (seteuid(euid)) + die("Failed to seteuid to %d: %s", euid, strerror(errno)); if (execvp(argv[0], argv)) { fprintf(stderr, "\n********************\n"); fprintf(stderr, " Unable to exec %s\n", argv[0]); @@ -4298,6 +4303,7 @@ enum { OPT_funcstack = 254, OPT_date = 255, OPT_module = 256, + OPT_euid = 257, }; void trace_stop(int argc, char **argv) @@ -4485,6 +4491,7 @@ struct common_record_context { int manual; int topt; int do_child; + uid_t euid; int run_command; }; @@ -4518,6 +4525,7 @@ static void parse_record_options(int argc, char *pid; char *sav; int neg_event = 0; + struct passwd *pw; init_common_record_context(ctx, curr_cmd); @@ -4539,6 +4547,7 @@ static void parse_record_options(int argc, {"quiet", no_argument, NULL, OPT_quiet}, {"help", no_argument, NULL, '?'}, {"module", required_argument, NULL, OPT_module}, + {"user", required_argument, NULL, OPT_euid}, {NULL, 0, NULL, 0} }; @@ -4819,6 +4828,12 @@ static void parse_record_options(int argc, ctx->instance->filter_mod = optarg; ctx->filtered = 0; break; + case OPT_euid: + pw = getpwnam(optarg); + if (!pw) + die("Can not find user %s", optarg); + ctx->euid = pw->pw_uid; + break; case OPT_quiet: case 'q': quiet = 1; @@ -4984,7 +4999,7 @@ static void record_trace(int argc, char **argv, } if (ctx->run_command) - run_cmd(type, (argc - optind) - 1, &argv[optind + 1]); + run_cmd(type, ctx->euid, (argc - optind) - 1, &argv[optind + 1]); else { update_task_filter(); tracecmd_enable_tracing();