From af0f4926da918604124f6394d14060ed9fd50210 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Thu, 7 Jul 2011 14:37:24 -0400 Subject: [PATCH] Change seunshare to send kill signals to the childs session. Also add signal handler to catch sigint, so if user enters ctrl-C sandbox will shutdown. --- policycoreutils-rhat.patch | 199 +++++++++++++++++++++++++++---------- policycoreutils.spec | 14 ++- 2 files changed, 158 insertions(+), 55 deletions(-) diff --git a/policycoreutils-rhat.patch b/policycoreutils-rhat.patch index aa5b05c..986eff0 100644 --- a/policycoreutils-rhat.patch +++ b/policycoreutils-rhat.patch @@ -1664,7 +1664,7 @@ index ff0ee7c..0c8a085 100644 test: @python test_sandbox.py -v diff --git a/policycoreutils/sandbox/sandbox b/policycoreutils/sandbox/sandbox -index 48a26c2..41a3204 100644 +index 48a26c2..4d17385 100644 --- a/policycoreutils/sandbox/sandbox +++ b/policycoreutils/sandbox/sandbox @@ -1,5 +1,6 @@ @@ -1869,7 +1869,7 @@ index 48a26c2..41a3204 100644 if len(cmds) == 0: self.usage(_("Command required")) cmds[0] = fullpath(cmds[0]) -@@ -329,44 +374,45 @@ sandbox [-h] [-[X|M] [-l level ] [-H homedir] [-T tempdir]] [-I includefile ] [- +@@ -329,44 +374,47 @@ sandbox [-h] [-[X|M] [-l level ] [-H homedir] [-T tempdir]] [-I includefile ] [- def __setup_dir(self): if self.__options.level or self.__options.session: return @@ -1910,10 +1910,12 @@ index 48a26c2..41a3204 100644 - return rc - + cmds = [ SEUNSHARE, "-Z", self.__execcon ] -+ if self.__options.usecgroup == True: ++ if self.__options.usecgroup: + cmds.append('-c') -+ if self.__options.usecaps == True: ++ if self.__options.usecaps: + cmds.append('-C') ++ if not self.__options.level: ++ cmds.append('-k') if self.__mount: - cmds = [ '/usr/sbin/seunshare', "-t", self.__tmpdir, "-h", self.__homedir, "--", self.__execcon ] + self.__paths - rc = subprocess.Popen(cmds).wait() @@ -1935,7 +1937,7 @@ index 48a26c2..41a3204 100644 selinux.setexeccon(self.__execcon) rc = subprocess.Popen(self.__cmds).wait() -@@ -404,7 +450,7 @@ if __name__ == '__main__': +@@ -404,7 +452,7 @@ if __name__ == '__main__': sandbox = Sandbox() rc = sandbox.main() except OSError, error: @@ -2104,11 +2106,12 @@ index ff8b3ef..66aadfd 100644 } diff --git a/policycoreutils/sandbox/sandboxX.sh b/policycoreutils/sandbox/sandboxX.sh -index 8338203..9648100 100644 +index 8338203..0b0239c 100644 --- a/policycoreutils/sandbox/sandboxX.sh +++ b/policycoreutils/sandbox/sandboxX.sh -@@ -1,13 +1,18 @@ +@@ -1,15 +1,21 @@ #!/bin/bash ++trap "" TERM context=`id -Z | secon -t -l -P` export TITLE="Sandbox $context -- `grep ^#TITLE: ~/.sandboxrc | /usr/bin/cut -b8-80`" -export SCREENSIZE="1000x700" @@ -2128,20 +2131,23 @@ index 8338203..9648100 100644 + chmod +x ~/seremote + /usr/share/sandbox/start $HOME/.sandboxrc export EXITCODE=$? - kill -HUP 0 +- kill -HUP 0 ++ kill -TERM 0 break + done + exit 0 diff --git a/policycoreutils/sandbox/seunshare.8 b/policycoreutils/sandbox/seunshare.8 new file mode 100644 -index 0000000..eeb2218 +index 0000000..c69ceda --- /dev/null +++ b/policycoreutils/sandbox/seunshare.8 -@@ -0,0 +1,40 @@ +@@ -0,0 +1,43 @@ +.TH SEUNSHARE "8" "May 2010" "seunshare" "User Commands" +.SH NAME +seunshare \- Run cmd with alternate homedir, tmpdir and/or SELinux context +.SH SYNOPSIS +.B seunshare -+[ -v ] [-c] [-C] [ -t tmpdir ] [ -h homedir ] [ -Z context ] -- executable [args] ++[-v] [-c] [-C] [-k] [ -t tmpdir ] [ -h homedir ] [ -Z context ] -- executable [args] +.br +.SH DESCRIPTION +.PP @@ -2162,6 +2168,9 @@ index 0000000..eeb2218 +\fB\-C --capabilities\fR +Allow apps executed within the namespace to use capabilities. Default is no capabilities. +.TP ++\fB\-k --kill\fR ++Kill all processes with matching MCS level. ++.TP +\fB\-Z\ context +Use alternate SELinux context while runing the executable. +.TP @@ -2177,10 +2186,10 @@ index 0000000..eeb2218 +and +.I Thomas Liu diff --git a/policycoreutils/sandbox/seunshare.c b/policycoreutils/sandbox/seunshare.c -index ec692e7..e3fa6bd 100644 +index ec692e7..431271f 100644 --- a/policycoreutils/sandbox/seunshare.c +++ b/policycoreutils/sandbox/seunshare.c -@@ -1,28 +1,35 @@ +@@ -1,27 +1,35 @@ +/* + * Authors: Dan Walsh + * Authors: Thomas Liu @@ -2213,15 +2222,15 @@ index ec692e7..e3fa6bd 100644 #include #include /* for context-mangling functions */ - +- -#include -#include -#include -- ++#include + #ifdef USE_NLS #include /* for setlocale() */ - #include /* for gettext() */ -@@ -39,29 +46,48 @@ +@@ -39,29 +47,56 @@ #define MS_PRIVATE 1<<18 #endif @@ -2235,6 +2244,7 @@ index ec692e7..e3fa6bd 100644 +#define USAGE_STRING _("USAGE: seunshare [ -v ] [ -c ] -C -t tmpdir -h homedir [-Z context] -- executable [args]") + +static int verbose = 0; ++static int child = 0; + +static capng_select_t cap_set = CAPNG_SELECT_BOTH; + @@ -2249,16 +2259,27 @@ index ec692e7..e3fa6bd 100644 - capng_clear(CAPNG_SELECT_BOTH); - - if (capng_lock() < 0) -- return -1; -- /* Change uid */ -- if (setresuid(uid, uid, uid)) { -- fprintf(stderr, _("Error changing uid, aborting.\n")); + if (capng_have_capabilities(cap_set) == CAPNG_NONE) + return 0; + capng_clear(cap_set); + if (capng_lock() == -1 || capng_apply(cap_set) == -1) { + fprintf(stderr, _("Failed to drop all capabilities\n")); return -1; +- /* Change uid */ +- if (setresuid(uid, uid, uid)) { +- fprintf(stderr, _("Error changing uid, aborting.\n")); ++ } ++ return 0; ++} ++ ++/** ++ * This function will drop all privileges. ++ */ ++static int drop_privs(uid_t uid) ++{ ++ if (drop_caps() == -1 || setresuid(uid, uid, uid) == -1) { ++ fprintf(stderr, _("Failed to drop privileges\n")); + return -1; } - return capng_apply(CAPNG_SELECT_BOTH); + return 0; @@ -2267,15 +2288,10 @@ index ec692e7..e3fa6bd 100644 -#define DEFAULT_PATH "/usr/bin:/bin" -static int verbose = 0; +/** -+ * This function will drop all privileges. ++ * If the user sends a siginto to seunshare, kill the child's session + */ -+static int drop_privs(uid_t uid) -+{ -+ if (drop_caps() == -1 || setresuid(uid, uid, uid) == -1) { -+ fprintf(stderr, _("Failed to drop privileges\n")); -+ return -1; -+ } -+ return 0; ++void handler(int sig) { ++ if (child > 0) kill(-child,sig); +} /** @@ -2284,21 +2300,25 @@ index ec692e7..e3fa6bd 100644 */ static int set_signal_handles(void) { -@@ -75,8 +101,8 @@ static int set_signal_handles(void) +@@ -75,32 +110,117 @@ static int set_signal_handles(void) (void)sigprocmask(SIG_SETMASK, &empty, NULL); - /* Terminate on SIGHUP. */ -- if (signal(SIGHUP, SIG_DFL) == SIG_ERR) { + /* Terminate on SIGHUP */ -+ if (signal(SIGHUP, SIG_IGN) == SIG_ERR) { + if (signal(SIGHUP, SIG_DFL) == SIG_ERR) { perror("Unable to set SIGHUP handler"); return -1; } -@@ -84,23 +110,103 @@ static int set_signal_handles(void) - return 0; - } ++ if (signal(SIGINT, handler) == SIG_ERR) { ++ perror("Unable to set SIGHUP handler"); ++ return -1; ++ } ++ ++ return 0; ++} ++ +#define status_to_retval(status,retval) do { \ + if ((status) == -1) \ + retval = -1; \ @@ -2365,9 +2385,9 @@ index ec692e7..e3fa6bd 100644 + fprintf(stderr, _("Error: %s not owned by GID %d\n"), file, gid); + return -1; + } -+ return 0; -+} -+ + return 0; + } + +#define equal_stats(one,two) \ + ((one)->st_dev == (two)->st_dev && (one)->st_ino == (two)->st_ino && \ + (one)->st_uid == (two)->st_uid && (one)->st_gid == (two)->st_gid && \ @@ -2409,7 +2429,7 @@ index ec692e7..e3fa6bd 100644 return 0; } -@@ -123,7 +229,7 @@ static int verify_shell(const char *shell_name) +@@ -123,7 +243,7 @@ static int verify_shell(const char *shell_name) /* check the shell skipping newline char */ if (!strcmp(shell_name, buf)) { @@ -2418,7 +2438,7 @@ index ec692e7..e3fa6bd 100644 break; } } -@@ -131,45 +237,530 @@ static int verify_shell(const char *shell_name) +@@ -131,45 +251,594 @@ static int verify_shell(const char *shell_name) return rc; } @@ -2817,9 +2837,8 @@ index ec692e7..e3fa6bd 100644 + setfsuid(pwd->pw_uid); + + return 0; - } - --#define USAGE_STRING _("USAGE: seunshare [ -v ] [ -t tmpdir ] [ -h homedir ] -- CONTEXT executable [args] ") ++} ++ +/** + * seunshare will create a tmpdir in /tmp, with root ownership. The parent + * process waits for it child to exit to attempt to remove the directory. If @@ -2931,6 +2950,69 @@ index ec692e7..e3fa6bd 100644 + if (fd_t >= 0) close(fd_t); + if (fd_s >= 0) close(fd_s); + return tmpdir; + } + +-#define USAGE_STRING _("USAGE: seunshare [ -v ] [ -t tmpdir ] [ -h homedir ] -- CONTEXT executable [args] ") ++#define PROC_BASE "/proc" ++ ++static int ++killall (security_context_t execcon) ++{ ++ DIR *dir; ++ security_context_t scon; ++ struct dirent *de; ++ pid_t *pid_table, pid, self; ++ int i; ++ int pids, max_pids; ++ int running = 0; ++ self = getpid(); ++ if (!(dir = opendir(PROC_BASE))) { ++ return -1; ++ } ++ max_pids = 256; ++ pid_table = malloc(max_pids * sizeof (pid_t)); ++ if (!pid_table) { ++ return -1; ++ } ++ pids = 0; ++ context_t con; ++ con = context_new(execcon); ++ const char *mcs = context_range_get(con); ++ printf("mcs=%s\n", mcs); ++ while ((de = readdir (dir)) != NULL) { ++ if (!(pid = (pid_t)atoi(de->d_name)) || pid == self) ++ continue; ++ ++ if (pids == max_pids) { ++ if (!(pid_table = realloc(pid_table, 2*pids*sizeof(pid_t)))) { ++ return -1; ++ } ++ max_pids *= 2; ++ } ++ pid_table[pids++] = pid; ++ } ++ ++ (void)closedir(dir); ++ ++ for (i = 0; i < pids; i++) { ++ pid_t id = pid_table[i]; ++ ++ if (getpidcon(id, &scon) == 0) { ++ ++ context_t pidcon = context_new(scon); ++ /* Attempt to kill remaining processes */ ++ if (strcmp(context_range_get(pidcon), mcs) == 0) ++ kill(id, SIGKILL); ++ ++ context_free(pidcon); ++ freecon(scon); ++ } ++ running++; ++ } ++ ++ context_free(con); ++ free(pid_table); ++ return running; +} int main(int argc, char **argv) { @@ -2944,6 +3026,7 @@ index ec692e7..e3fa6bd 100644 int clflag; /* holds codes for command line flags */ - char *tmpdir_s = NULL; /* tmpdir spec'd by user in argv[] */ + int usecgroups = 0; ++ int kill_all = 0; + char *homedir_s = NULL; /* homedir spec'd by user in argv[] */ + char *tmpdir_s = NULL; /* tmpdir spec'd by user in argv[] */ @@ -2956,6 +3039,7 @@ index ec692e7..e3fa6bd 100644 const struct option long_options[] = { {"homedir", 1, 0, 'h'}, {"tmpdir", 1, 0, 't'}, ++ {"kill", 1, 0, 'k'}, {"verbose", 1, 0, 'v'}, + {"cgroups", 1, 0, 'c'}, + {"context", 1, 0, 'Z'}, @@ -2963,7 +3047,7 @@ index ec692e7..e3fa6bd 100644 {NULL, 0, 0, 0} }; -@@ -180,6 +771,12 @@ int main(int argc, char **argv) { +@@ -180,6 +849,12 @@ int main(int argc, char **argv) { return -1; } @@ -2976,7 +3060,7 @@ index ec692e7..e3fa6bd 100644 struct passwd *pwd=getpwuid(uid); if (!pwd) { perror(_("getpwduid failed")); -@@ -187,34 +784,33 @@ int main(int argc, char **argv) { +@@ -187,34 +862,36 @@ int main(int argc, char **argv) { } if (verify_shell(pwd->pw_shell) < 0) { @@ -3000,6 +3084,9 @@ index ec692e7..e3fa6bd 100644 - } - if (verify_mount(tmpdir_s, pwd) < 0) return -1; + tmpdir_s = optarg; ++ break; ++ case 'k': ++ kill_all = 1; break; case 'h': - if (!(homedir_s = realpath(optarg, NULL))) { @@ -3025,7 +3112,7 @@ index ec692e7..e3fa6bd 100644 break; default: fprintf(stderr, "%s\n", USAGE_STRING); -@@ -223,76 +819,84 @@ int main(int argc, char **argv) { +@@ -223,76 +900,84 @@ int main(int argc, char **argv) { } if (! homedir_s && ! tmpdir_s) { @@ -3067,9 +3154,6 @@ index ec692e7..e3fa6bd 100644 - if (tmpdir_s && seunshare_mount(tmpdir_s, "/tmp", pwd) < 0) - return -1; - } -- -- if (drop_capabilities(uid)) { -- perror(_("Failed to drop all capabilities")); + if (set_signal_handles()) return -1; + + if (usecgroups && setup_cgroups() < 0) return -1; @@ -3088,7 +3172,9 @@ index ec692e7..e3fa6bd 100644 + verify_directory(tmpdir_s, NULL, &st_tmpdir_s) < 0 || + check_owner_uid(uid, tmpdir_s, &st_tmpdir_s))) return -1; + setfsuid(0); -+ + +- if (drop_capabilities(uid)) { +- perror(_("Failed to drop all capabilities")); + /* create runtime tmpdir */ + if (tmpdir_s && (tmpdir_r = create_tmpdir(tmpdir_s, &st_tmpdir_s, + &st_tmpdir_r, pwd, execcon)) == NULL) { @@ -3096,8 +3182,9 @@ index ec692e7..e3fa6bd 100644 return -1; } +- int child = fork(); + /* spawn child process */ - int child = fork(); ++ child = fork(); if (child == -1) { perror(_("Unable to fork")); - return -1; @@ -3159,7 +3246,7 @@ index ec692e7..e3fa6bd 100644 if (display) rc |= setenv("DISPLAY", display, 1); rc |= setenv("HOME", pwd->pw_dir, 1); -@@ -300,22 +904,41 @@ int main(int argc, char **argv) { +@@ -300,22 +985,47 @@ int main(int argc, char **argv) { rc |= setenv("USER", pwd->pw_name, 1); rc |= setenv("LOGNAME", pwd->pw_name, 1); rc |= setenv("PATH", DEFAULT_PATH, 1); @@ -3195,10 +3282,16 @@ index ec692e7..e3fa6bd 100644 - free(tmpdir_s); - free(homedir_s); + drop_caps(); - ++ + /* parent waits for child exit to do the cleanup */ + waitpid(child, &status, 0); + status_to_retval(status, status); + ++ /* Make sure all child processes exit */ ++ kill(-child,SIGTERM); ++ ++ if (execcon && kill) ++ killall(execcon); + + if (tmpdir_r) cleanup_tmpdir(tmpdir_r, tmpdir_s, pwd, 1); + diff --git a/policycoreutils.spec b/policycoreutils.spec index 944a90b..365c37e 100644 --- a/policycoreutils.spec +++ b/policycoreutils.spec @@ -7,7 +7,7 @@ Summary: SELinux policy core utilities Name: policycoreutils Version: 2.0.86 -Release: 15%{?dist} +Release: 18%{?dist} License: GPLv2 Group: System Environment/Base # Based on git repository with tag 20101221 @@ -349,7 +349,17 @@ fi /bin/systemctl try-restart restorecond.service >/dev/null 2>&1 || : %changelog -* Mon Jul 5 2011 Dan Walsh 2.0.86-16 +* Thu Jul 7 2011 Dan Walsh 2.0.86-18 +- Change seunshare to send kill signals to the childs session. +- Also add signal handler to catch sigint, so if user enters ctrl-C sandbox will shutdown. + +* Wed Jul 6 2011 Dan Walsh 2.0.86-17 +- Add -k qualifier to seunshare to have it attempt to kill all processes with +the matching MCS label. +sandbox will default to using the -k, if the level was not specified. +This is added to make sure all processes are killed with the sandbox exits. + +* Tue Jul 5 2011 Dan Walsh 2.0.86-16 - Add -C option to sandbox and seunshare to maintain capabilities, otherwise the bounding set will be dropped. - Change --cgroups short name -c rather then -C for consistancy