void selinux_execve(const char *path, char *const argv[], char *const envp[], int noexec) { char **nargv; const char *sesh; int argc, serrno; debug_decl(selinux_execve, SUDO_DEBUG_SELINUX) sesh = sudo_conf_sesh_path(); if (sesh == NULL) { sudo_warnx("internal error: sesh path not set"); errno = EINVAL; debug_return; } if (setexeccon(se_state.new_context)) { sudo_warn(U_("unable to set exec context to %s"), se_state.new_context); if (se_state.enforcing) debug_return; } #ifdef HAVE_SETKEYCREATECON if (setkeycreatecon(se_state.new_context)) { sudo_warn(U_("unable to set key creation context to %s"), se_state.new_context); if (se_state.enforcing) debug_return; } #endif /* HAVE_SETKEYCREATECON */ /* * Build new argv with sesh as argv[0]. * If argv[0] ends in -noexec, sesh will disable execute * for the command it runs. */ for (argc = 0; argv[argc] != NULL; argc++) continue; nargv = sudo_emallocarray(argc + 2, sizeof(char *)); if (noexec) nargv[0] = *argv[0] == '-' ? "-sesh-noexec" : "sesh-noexec"; else nargv[0] = *argv[0] == '-' ? "-sesh" : "sesh"; nargv[1] = (char *)path; memcpy(&nargv[2], &argv[1], argc * sizeof(char *)); /* copies NULL */ /* sesh will handle noexec for us. */ sudo_execve(sesh, nargv, envp, false); serrno = errno; free(nargv); errno = serrno; debug_return; }
/* * Exit codes defined in sudo_exec.h: * SESH_SUCCESS (0) ... successful operation * SESH_ERR_FAILURE (1) ... unspecified error * SESH_ERR_INVALID (30) ... invalid -e arg value * SESH_ERR_BAD_PATHS (31) ... odd number of paths * SESH_ERR_NO_FILES (32) ... copy error, no files copied * SESH_ERR_SOME_FILES (33) ... copy error, no files copied */ int main(int argc, char *argv[], char *envp[]) { int ret; debug_decl(main, SUDO_DEBUG_MAIN) initprogname(argc > 0 ? argv[0] : "sesh"); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE_NAME, LOCALEDIR); textdomain(PACKAGE_NAME); if (argc < 2) sudo_fatalx(U_("requires at least one argument")); /* Read sudo.conf and initialize the debug subsystem. */ if (sudo_conf_read(NULL, SUDO_CONF_DEBUG) == -1) exit(EXIT_FAILURE); sudo_debug_register(getprogname(), NULL, NULL, sudo_conf_debug_files(getprogname())); if (strcmp(argv[1], "-e") == 0) { ret = sesh_sudoedit(argc, argv); } else { bool login_shell, noexec = false; char *cp, *cmnd; int fd = -1; /* If the first char of argv[0] is '-', we are running a login shell. */ login_shell = argv[0][0] == '-'; /* If argv[0] ends in -noexec, pass the flag to sudo_execve() */ if ((cp = strrchr(argv[0], '-')) != NULL && cp != argv[0]) noexec = strcmp(cp, "-noexec") == 0; /* If argv[1] is --execfd=%d, extract the fd to exec with. */ if (strncmp(argv[1], "--execfd=", 9) == 0) { const char *errstr; cp = argv[1] + 9; fd = strtonum(cp, 0, INT_MAX, &errstr); if (errstr != NULL) sudo_fatalx(U_("invalid file descriptor number: %s"), cp); argv++; argc--; } /* Shift argv and make a copy of the command to execute. */ argv++; argc--; if ((cmnd = strdup(argv[0])) == NULL) sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); /* If invoked as a login shell, modify argv[0] accordingly. */ if (login_shell) { if ((cp = strrchr(argv[0], '/')) == NULL) sudo_fatal(U_("unable to run %s as a login shell"), argv[0]); *cp = '-'; argv[0] = cp; } sudo_execve(fd, cmnd, argv, envp, noexec); sudo_warn(U_("unable to execute %s"), cmnd); ret = SESH_ERR_FAILURE; } sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, ret); _exit(ret); }