From 4047d1fe8edbe5ae952fef17fc09a4105d0de14b Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Sat, 9 May 2020 18:01:22 -0700 Subject: [PATCH] su.c: implement --exec It's now possible to run commands as other users without shell interpolation by using "--exec": Read /etc/shadow as root without specifying user: ``` su --exec /bin/cat -- /etc/shadow ``` Or specify user: ``` su --exec /bin/cat root -- /etc/shadow ``` --- src/su.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/su.c b/src/su.c index 578361a7..08a28861 100644 --- a/src/su.c +++ b/src/su.c @@ -94,6 +94,7 @@ static bool do_interactive_shell = false; static bool fakelogin = false; static /*@observer@*/const char *shellstr; static /*@null@*/char *command = NULL; +static /*@null@*/char *exec_command = NULL; static int optidx; @@ -440,12 +441,14 @@ static void usage (int status) "\n" "Options:\n" " -c, --command COMMAND pass COMMAND to the invoked shell\n" + " -e, --exec PATH run PATH without shell, follow -- with args\n" " -h, --help display this help message and exit\n" " -, -l, --login make the shell a login shell\n" " -m, -p,\n" " --preserve-environment do not reset environment variables, and\n" " keep the same shell\n" " -s, --shell SHELL use SHELL instead of the default in passwd\n" + " -- pass all subsequent arguments on as-is\n" "\n" "If no username is given, assume root.\n"), (E_SUCCESS != status) ? stderr : stdout); exit (status); @@ -820,6 +823,12 @@ static void process_flags (int argc, char **argv) } command = argv[++optidx]; + } else if (flags_match (arg, "--exec", "-e", NULL)) { + if (optidx == argc - 1) { + flag_arg_required (arg); + } + + exec_command = argv[++optidx]; } else if (flags_match (arg, "--help", "-h", NULL)) { usage (E_SUCCESS); } else if (flags_match (arg, "--login", "-l", "-")) { @@ -843,6 +852,17 @@ static void process_flags (int argc, char **argv) } } + if (NULL != exec_command && NULL != command) { + fprintf (stderr, + _("%s: COMMAND and PATH are mutually exclusive\n"), + argv[0]); + usage (E_USAGE); + } + + if (NULL != exec_command) { + command = exec_command; + } + /* if next arg is not "--", treat as USER */ if (optidx < argc && strcmp (argv[optidx], "--")) { STRFCPY (name, argv[optidx++]); /* use this login id */ @@ -1226,10 +1246,18 @@ int main (int argc, char **argv) * with the rest of the command line included. */ argv[-1] = cp; - execve_shell (shellstr, &argv[-1], environ); - err = errno; - (void) fprintf (stderr, - _("Cannot execute %s\n"), shellstr); + + if (NULL != exec_command) { + (void) execve (command, &argv[1], environ); + err = errno; + (void) fprintf (stderr, + _("Cannot execute \'%s\'\n"), command); + } else { + execve_shell (shellstr, &argv[-1], environ); + err = errno; + (void) fprintf (stderr, + _("Cannot execute \'%s\'\n"), shellstr); + } errno = err; } else { (void) shell (shellstr, cp, environ);