diff -up policycoreutils-2.0.86/restorecond/restorecond_user.conf.sandbox policycoreutils-2.0.86/restorecond/restorecond_user.conf --- policycoreutils-2.0.86/restorecond/restorecond_user.conf.sandbox 2011-06-13 13:47:06.552590955 -0400 +++ policycoreutils-2.0.86/restorecond/restorecond_user.conf 2011-06-13 13:47:27.757820459 -0400 @@ -4,4 +4,4 @@ ~/local/* ~/.fonts/* ~/.cache/* - +~/.config/* diff -up policycoreutils-2.0.86/sandbox/sandbox.8.sandbox policycoreutils-2.0.86/sandbox/sandbox.8 --- policycoreutils-2.0.86/sandbox/sandbox.8.sandbox 2011-07-07 14:42:18.298415909 -0400 +++ policycoreutils-2.0.86/sandbox/sandbox.8 2011-07-07 14:42:30.567508958 -0400 @@ -3,11 +3,11 @@ sandbox \- Run cmd under an SELinux sandbox .SH SYNOPSIS .B sandbox -[-l level ] [[-M | -X] -H homedir -T tempdir ] [-I includefile ] [ -W windowmanager ] [ -w windowsize ] [[-i file ]...] [ -t type ] cmd +[-C] [-c] [-l level ] [[-M | -X] -H homedir -T tempdir ] [-I includefile ] [ -W windowmanager ] [ -w windowsize ] [[-i file ]...] [ -t type ] cmd .br .B sandbox -[-l level ] [[-M | -X] -H homedir -T tempdir ] [-I includefile ] [ -W windowmanager ] [ -w windowsize ] [[-i file ]...] [ -t type ] -S +[-C] [-c] [-l level ] [[-M | -X] -H homedir -T tempdir ] [-I includefile ] [ -W windowmanager ] [ -w windowsize ] [[-i file ]...] [ -t type ] -S .br .SH DESCRIPTION .PP @@ -60,8 +60,11 @@ Default to /usr/bin/matchbox-window-mana Create an X based Sandbox for gui apps, temporary files for $HOME and /tmp, secondary Xserver, defaults to sandbox_x_t .TP -\fB\-C\fR +\fB\-c\fR Use control groups to control this copy of sandbox. Specify parameters in /etc/sysconfig/sandbox. Max memory usage and cpu usage are to be specified in percent. You can specify which CPUs to use by numbering them 0,1,2... etc. +.TP +\fB\-C\fR +Use capabilities within the sandbox. By default applications executed within the sandbox will not be allowed to use capabilities (setuid apps), with the -C flag, you can use programs requiring capabilities. .PP .SH "SEE ALSO" .TP diff -up policycoreutils-2.0.86/sandbox/sandbox.sandbox policycoreutils-2.0.86/sandbox/sandbox --- policycoreutils-2.0.86/sandbox/sandbox.sandbox 2011-06-13 13:44:44.678086035 -0400 +++ policycoreutils-2.0.86/sandbox/sandbox 2011-07-07 14:42:50.587660702 -0400 @@ -88,9 +88,7 @@ def copyfile(file, srcdir, dest): except shutil.Error, elist: for e in elist.message: - # ignore files that are missing - if not e[2].startswith("[Errno 2]"): - sys.stderr.write(e[2]) + sys.stderr.write(e[2]) SAVE_FILES[file] = (dest, os.path.getmtime(dest)) @@ -311,17 +309,21 @@ sandbox [-h] [-l level ] [-[X|M] [-H hom parser.add_option("-l", "--level", dest="level", help=_("MCS/MLS level for the sandbox")) - parser.add_option("-C", "--cgroups", + parser.add_option("-c", "--cgroups", action="store_true", dest="usecgroup", default=False, help="Use cgroups to limit this sandbox.") + parser.add_option("-C", "--capabilities", + action="store_true", dest="usecaps", default=False, + help="Allow apps requiring capabilities to run within the sandbox.") + self.__parser=parser self.__options, cmds = parser.parse_args() if self.__options.X_ind: self.setype = DEFAULT_X_TYPE - + self.dpi=commands.getoutput("xrdb -query | grep dpi | /bin/cut -f 2") if self.__options.setype: self.setype = self.__options.setype @@ -392,8 +394,12 @@ sandbox [-h] [-l level ] [-[X|M] [-H hom def __execute(self): try: cmds = [ SEUNSHARE, "-Z", self.__execcon ] - if self.__options.usecgroup == True: + if self.__options.usecgroup: cmds.append('-c') + if self.__options.usecaps: + cmds.append('-C') + if not self.__options.level: + cmds.append('-k') if self.__mount: cmds += [ "-t", self.__tmpdir, "-h", self.__homedir ] @@ -405,7 +411,7 @@ sandbox [-h] [-l level ] [-[X|M] [-H hom self.__setup_sandboxrc(self.__options.wm) - cmds += [ "--", SANDBOXSH, self.__options.windowsize ] + cmds += [ "--", SANDBOXSH, self.__options.windowsize, self.dpi ] else: cmds += [ "--" ] + self.__paths return subprocess.Popen(cmds).wait() diff -up policycoreutils-2.0.86/sandbox/sandboxX.sh.sandbox policycoreutils-2.0.86/sandbox/sandboxX.sh --- policycoreutils-2.0.86/sandbox/sandboxX.sh.sandbox 2011-06-13 13:44:44.684086096 -0400 +++ policycoreutils-2.0.86/sandbox/sandboxX.sh 2011-07-07 14:41:50.536205201 -0400 @@ -1,10 +1,12 @@ #!/bin/bash -context=`id -Z | secon -t ` -export TITLE="`grep ^#TITLE: ~/.sandboxrc | /usr/bin/cut -b8-80` ($context)" -[ $# -eq 1 ] && export SCREENSIZE="$1" || export SCREENSIZE="1000x700" +trap "" TERM +context=`id -Z | secon -t -l -P` +export TITLE="Sandbox $context -- `grep ^#TITLE: ~/.sandboxrc | /usr/bin/cut -b8-80`" +[ -z $1 ] && export SCREENSIZE="1000x700" || export SCREENSIZE="$1" +[ -z $2 ] && export DPI="96" || export DPI="$2" trap "exit 0" HUP -(/usr/bin/Xephyr -nolisten tcp -title "$TITLE" -terminate -screen $SCREENSIZE -displayfd 5 5>&1 2>/dev/null) | while read D; do +(/usr/bin/Xephyr -title "$TITLE" -terminate -screen $SCREENSIZE -dpi $DPI -displayfd 5 5>&1 2>/dev/null) | while read D; do export DISPLAY=:$D cat > ~/seremote << __EOF #!/bin/sh @@ -13,7 +15,7 @@ __EOF chmod +x ~/seremote /usr/share/sandbox/start $HOME/.sandboxrc export EXITCODE=$? - kill -HUP 0 + kill -TERM 0 break done exit 0 diff -up policycoreutils-2.0.86/sandbox/seunshare.8.sandbox policycoreutils-2.0.86/sandbox/seunshare.8 --- policycoreutils-2.0.86/sandbox/seunshare.8.sandbox 2011-07-07 14:41:16.065943281 -0400 +++ policycoreutils-2.0.86/sandbox/seunshare.8 2011-07-07 14:41:26.300021079 -0400 @@ -3,7 +3,7 @@ seunshare \- Run cmd with alternate homedir, tmpdir and/or SELinux context .SH SYNOPSIS .B seunshare -[ -v ] [ -t tmpdir ] [ -h homedir ] [ -Z context ] -- executable [args] +[-v] [-c] [-C] [-k] [ -t tmpdir ] [ -h homedir ] [ -Z context ] -- executable [args] .br .SH DESCRIPTION .PP @@ -18,9 +18,15 @@ Alternate homedir to be used by the appl \fB\-t\ tmpdir Use alternate tempory directory to mount on /tmp. tmpdir must be owned by the user. .TP -\fB\-c cgroups\fR +\fB\-c --cgroups\fR Use cgroups to control this copy of seunshare. Specify parameters in /etc/sysconfig/sandbox. Max memory usage and cpu usage are to be specified in percent. You can specify which CPUs to use by numbering them 0,1,2... etc. .TP +\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 diff -up policycoreutils-2.0.86/sandbox/seunshare.c.sandbox policycoreutils-2.0.86/sandbox/seunshare.c --- policycoreutils-2.0.86/sandbox/seunshare.c.sandbox 2011-06-13 13:44:44.687086129 -0400 +++ policycoreutils-2.0.86/sandbox/seunshare.c 2011-07-07 14:41:08.038882237 -0400 @@ -29,6 +29,7 @@ #include #include /* for context-mangling functions */ +#include #ifdef USE_NLS #include /* for setlocale() */ @@ -53,20 +54,22 @@ #define BUF_SIZE 1024 #define DEFAULT_PATH "/usr/bin:/bin" -#define USAGE_STRING _("USAGE: seunshare [ -v ] [ -c ] -t tmpdir -h homedir [-Z context] -- executable [args]") +#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; /** * This function will drop all capabilities. */ static int drop_caps() { - if (capng_have_capabilities(CAPNG_SELECT_BOTH) == CAPNG_NONE) + if (capng_have_capabilities(cap_set) == CAPNG_NONE) return 0; - capng_clear(CAPNG_SELECT_BOTH); - if (capng_lock() == -1 || capng_apply(CAPNG_SELECT_BOTH) == -1) { + capng_clear(cap_set); + if (capng_lock() == -1 || capng_apply(cap_set) == -1) { fprintf(stderr, _("Failed to drop all capabilities\n")); return -1; } @@ -86,6 +89,13 @@ static int drop_privs(uid_t uid) } /** + * If the user sends a siginto to seunshare, kill the child's session + */ +void handler(int sig) { + if (child > 0) kill(-child,sig); +} + +/** * Take care of any signal setup. */ static int set_signal_handles(void) @@ -101,7 +111,12 @@ static int set_signal_handles(void) (void)sigprocmask(SIG_SETMASK, &empty, NULL); /* 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; + } + + if (signal(SIGINT, handler) == SIG_ERR) { perror("Unable to set SIGHUP handler"); return -1; } @@ -334,6 +349,7 @@ static int setup_cgroups() char buf[BUF_SIZE]; char *tok = NULL; int rc = -1; + char *str = NULL; const char* fname = "/etc/sysconfig/sandbox"; if ((fp = fopen(fname, "rt")) == NULL) { @@ -346,7 +362,8 @@ static int setup_cgroups() /* Copy the string, ignoring whitespace */ int len = strlen(buf); - char *str = malloc((len + 1) * sizeof(char)); + free(str); + str = malloc((len + 1) * sizeof(char)); int ind = 0; int i; @@ -487,6 +504,8 @@ static int setup_cgroups() rc = 0; err: + fclose(fp); + free(str); free(mem); free(cgroupname); free(cpus); @@ -734,12 +753,75 @@ good: return tmpdir; } +#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) { int status = -1; security_context_t execcon = NULL; int clflag; /* holds codes for command line flags */ 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[] */ @@ -752,9 +834,11 @@ int main(int argc, char **argv) { 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'}, + {"capabilities", 1, 0, 'C'}, {NULL, 0, 0, 0} }; @@ -783,7 +867,7 @@ int main(int argc, char **argv) { } while (1) { - clflag = getopt_long(argc, argv, "cvh:t:Z:", long_options, NULL); + clflag = getopt_long(argc, argv, "Ccvh:t:Z:", long_options, NULL); if (clflag == -1) break; @@ -791,6 +875,9 @@ int main(int argc, char **argv) { case 't': tmpdir_s = optarg; break; + case 'k': + kill_all = 1; + break; case 'h': homedir_s = optarg; break; @@ -800,6 +887,9 @@ int main(int argc, char **argv) { case 'c': usecgroups = 1; break; + case 'C': + cap_set = CAPNG_SELECT_CAPS; + break; case 'Z': execcon = optarg; break; @@ -851,7 +941,7 @@ int main(int argc, char **argv) { } /* spawn child process */ - int child = fork(); + child = fork(); if (child == -1) { perror(_("Unable to fork")); goto err; @@ -926,6 +1016,12 @@ childerr: 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); err: