f415a12
diff -up policycoreutils-2.0.86/restorecond/restorecond_user.conf.sandbox policycoreutils-2.0.86/restorecond/restorecond_user.conf
72a4d21
--- policycoreutils-2.0.86/restorecond/restorecond_user.conf.sandbox	2011-06-13 13:47:06.000000000 -0400
72a4d21
+++ policycoreutils-2.0.86/restorecond/restorecond_user.conf	2011-06-13 13:47:27.000000000 -0400
f415a12
@@ -4,4 +4,4 @@
f415a12
 ~/local/*
f415a12
 ~/.fonts/*
f415a12
 ~/.cache/*
f415a12
-
f415a12
+~/.config/*
9f197b5
diff -up policycoreutils-2.0.86/sandbox/sandbox.8.sandbox policycoreutils-2.0.86/sandbox/sandbox.8
72a4d21
--- policycoreutils-2.0.86/sandbox/sandbox.8.sandbox	2011-07-07 14:42:18.000000000 -0400
72a4d21
+++ policycoreutils-2.0.86/sandbox/sandbox.8	2012-01-03 11:09:22.391519370 -0500
9f197b5
@@ -3,11 +3,11 @@
9f197b5
 sandbox \- Run cmd under an SELinux sandbox
9f197b5
 .SH SYNOPSIS
9f197b5
 .B sandbox
9f197b5
-[-l level ] [[-M | -X]  -H homedir -T tempdir ] [-I includefile ] [ -W windowmanager ] [ -w windowsize ] [[-i file ]...] [ -t type ] cmd
72a4d21
+[-C] [-c] [ -d DPI ] [-l level ] [[-M | -X]  -H homedir -T tempdir ] [-I includefile ] [ -W windowmanager ] [ -w windowsize ] [[-i file ]...] [ -t type ] cmd
9f197b5
 
9f197b5
 .br
9f197b5
 .B sandbox
9f197b5
-[-l level ] [[-M | -X]  -H homedir -T tempdir ] [-I includefile ] [ -W windowmanager ] [ -w windowsize ] [[-i file ]...] [ -t type ] -S
72a4d21
+[-C] [-c] [ -d DPI ] [-l level ] [[-M | -X]  -H homedir -T tempdir ] [-I includefile ] [ -W windowmanager ] [ -w windowsize ] [[-i file ]...] [ -t type ] -S
9f197b5
 .br
9f197b5
 .SH DESCRIPTION
9f197b5
 .PP
72a4d21
@@ -49,7 +49,7 @@ Use alternate tempory directory to mount
72a4d21
 Run a full desktop session, Requires level, and home and tmpdir.
72a4d21
 .TP
72a4d21
 \fB\-w windowsize\fR
72a4d21
-Specifies the windowsize when creating an X based Sandbox. The default windowsize is 1000x700. 
72a4d21
+Specifies the windowsize when creating an X based Sandbox. The default windowsize is 1000x700.
72a4d21
 .TP
72a4d21
 \fB\-W windowmanager\fR
72a4d21
 Select alternative window manager to run within 
72a4d21
@@ -60,8 +60,14 @@ Default to /usr/bin/matchbox-window-mana
9f197b5
 Create an X based Sandbox for gui apps, temporary files for
9f197b5
 $HOME and /tmp, secondary Xserver, defaults to sandbox_x_t
9f197b5
 .TP
9f197b5
-\fB\-C\fR
72a4d21
+\fB\-d\fR
72a4d21
+Set the DPI value for the sanbox X Server. Defaults to the current X Sever DPI.
72a4d21
+.TP
9f197b5
+\fB\-c\fR
9f197b5
 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.
9f197b5
+.TP
9f197b5
+\fB\-C\fR
9f197b5
+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.
9f197b5
 .PP
9f197b5
 .SH "SEE ALSO"
9f197b5
 .TP
72a4d21
@@ -69,7 +75,7 @@ runcon(1), seunshare(8), selinux(8)
72a4d21
 .PP
72a4d21
 
72a4d21
 .SH AUTHOR
72a4d21
-This manual page was written by 
72a4d21
+This manual page was written by
72a4d21
 .I Dan Walsh <dwalsh@redhat.com>
72a4d21
 and
72a4d21
 .I Thomas Liu <tliu@fedoraproject.org>
f415a12
diff -up policycoreutils-2.0.86/sandbox/sandbox.sandbox policycoreutils-2.0.86/sandbox/sandbox
72a4d21
--- policycoreutils-2.0.86/sandbox/sandbox.sandbox	2011-06-13 13:44:44.000000000 -0400
72a4d21
+++ policycoreutils-2.0.86/sandbox/sandbox	2012-01-03 11:08:43.619495043 -0500
72a4d21
@@ -25,7 +25,7 @@ import selinux
72a4d21
 import signal
72a4d21
 from tempfile import mkdtemp
72a4d21
 import pwd
72a4d21
-import commands 
72a4d21
+import commands
72a4d21
 import setools
72a4d21
 
72a4d21
 PROGNAME = "policycoreutils"
f415a12
@@ -88,9 +88,7 @@ def copyfile(file, srcdir, dest):
f415a12
 
f415a12
               except shutil.Error, elist:
f415a12
                      for e in elist.message:
f415a12
-                            # ignore files that are missing 
f415a12
-                            if not e[2].startswith("[Errno 2]"):
f415a12
-                                   sys.stderr.write(e[2])
f415a12
+                            sys.stderr.write(e[2])
f415a12
                      
f415a12
               SAVE_FILES[file] = (dest, os.path.getmtime(dest))
f415a12
 
72a4d21
@@ -120,10 +118,30 @@ def reserve(level):
72a4d21
     sock.bind("\0%s" % level)
72a4d21
     fcntl.fcntl(sock.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC)
72a4d21
 
72a4d21
+def get_range():
72a4d21
+       try:
72a4d21
+              level =selinux.getcon_raw()[1].split(":")[4]
72a4d21
+              lowc,highc = level.split(".")
72a4d21
+              low = int(lowc[1:])
72a4d21
+              high = int(highc[1:])+1
72a4d21
+              if high - low == 0:
72a4d21
+                     raise IndexError
72a4d21
+
72a4d21
+              return low,high
72a4d21
+       except IndexError:
72a4d21
+              raise ValueError(_("User account must be setup with an MCS Range"))
72a4d21
+
72a4d21
 def gen_mcs():
72a4d21
-       while True:
72a4d21
-              i1 = random.randrange(0, 1024)
72a4d21
-              i2 = random.randrange(0, 1024)
72a4d21
+       low, high = get_range()
72a4d21
+
72a4d21
+       level = None
72a4d21
+       ctr = 0
72a4d21
+       total = high-low
72a4d21
+       total = (total * (total - 1))/2
72a4d21
+       while ctr < total:
72a4d21
+              ctr += 1
72a4d21
+              i1 = random.randrange(low, high)
72a4d21
+              i2 = random.randrange(low, high)
72a4d21
               if i1 == i2:
72a4d21
                      continue
72a4d21
               if i1 > i2:
72a4d21
@@ -136,7 +154,10 @@ def gen_mcs():
72a4d21
               except socket.error:
72a4d21
                      continue
72a4d21
               break
72a4d21
-       return level
72a4d21
+       if level:
72a4d21
+              return level
72a4d21
+       raise ValueError(_("Failed to find any unused category sets.  Consider a larger MCS range for this user."))
72a4d21
+
72a4d21
 
72a4d21
 def fullpath(cmd):
72a4d21
        for i in [ "/", "./", "../" ]:
72a4d21
@@ -170,7 +191,7 @@ class Sandbox:
72a4d21
 
72a4d21
            if not os.path.exists(SEUNSHARE):
72a4d21
                   raise ValueError(_("""
72a4d21
-%s is required for the action you want to perform.  
72a4d21
+%s is required for the action you want to perform.
72a4d21
 """) % SEUNSHARE)
72a4d21
 
72a4d21
     def __mount_callback(self, option, opt, value, parser):
72a4d21
@@ -181,12 +202,12 @@ class Sandbox:
72a4d21
            setattr(parser.values, option.dest, True)
72a4d21
            if not os.path.exists(SEUNSHARE):
72a4d21
                   raise ValueError(_("""
72a4d21
-%s is required for the action you want to perform.  
72a4d21
+%s is required for the action you want to perform.
72a4d21
 """) % SEUNSHARE)
72a4d21
 
72a4d21
            if not os.path.exists(SANDBOXSH):
72a4d21
                   raise ValueError(_("""
72a4d21
-%s is required for the action you want to perform.  
72a4d21
+%s is required for the action you want to perform.
72a4d21
 """) % SANDBOXSH)
72a4d21
 
72a4d21
     def __validdir(self, option, opt, value, parser):
72a4d21
@@ -246,26 +267,25 @@ kill -TERM $WM_PID  2> /dev/null
72a4d21
 
72a4d21
     def usage(self, message = ""):
72a4d21
            error_exit("%s\n%s" % (self.__parser.usage, message))
72a4d21
-           
72a4d21
+
72a4d21
     def __parse_options(self):
72a4d21
         from optparse import OptionParser
72a4d21
         types = ""
72a4d21
         try:
72a4d21
                types = _("""
72a4d21
-Policy defines the following types for use with the -t: 
72a4d21
+Policy defines the following types for use with the -t:
72a4d21
 \t%s
72a4d21
 """) % "\n\t".join(setools.seinfo(setools.ATTRIBUTE, "sandbox_type")[0]['types'])
72a4d21
         except RuntimeError:
72a4d21
                pass
72a4d21
 
72a4d21
         usage = _("""
72a4d21
-sandbox [-h] [-l level ] [-[X|M] [-H homedir] [-T tempdir]] [-I includefile ] [-W windowmanager ] [ -w windowsize ] [[-i file ] ...] [ -t type ] command
72a4d21
+sandbox [-h] [-c] [-l level ] [-[X|M] [-H homedir] [-T tempdir]] [-I includefile ] [-W windowmanager ] [ -w windowsize ] [[-i file ] ...] [ -t type ] command
72a4d21
 
72a4d21
-sandbox [-h] [-l level ] [-[X|M] [-H homedir] [-T tempdir]] [-I includefile ] [-W windowmanager ] [ -w windowsize ] [[-i file ] ...] [ -t type ] -S
72a4d21
+sandbox [-h] [-c] [-l level ] [-[X|M] [-H homedir] [-T tempdir]] [-I includefile ] [-W windowmanager ] [ -w windowsize ] [[-i file ] ...] [ -t type ] -S
72a4d21
 %s
72a4d21
 """) % types
72a4d21
 
72a4d21
-        
72a4d21
         parser = OptionParser(version=self.VERSION, usage=usage)
72a4d21
         parser.disable_interspersed_args()
72a4d21
         parser.add_option("-i", "--include", 
72a4d21
@@ -281,6 +301,10 @@ sandbox [-h] [-l level ] [-[X|M] [-H hom
72a4d21
                           action="callback", callback=self.__mount_callback, 
72a4d21
                           help=_("mount new home and/or tmp directory"))
72a4d21
 
72a4d21
+        parser.add_option("-d", "--dpi",
72a4d21
+                          dest="dpi", action="store",
72a4d21
+                          help=_("dots per inch for X display"))
72a4d21
+
72a4d21
         parser.add_option("-S", "--session", action="store_true",  dest="session", 
72a4d21
                           default=False,  help=_("run complete desktop session within sandbox"))
72a4d21
 
72a4d21
@@ -291,17 +315,17 @@ sandbox [-h] [-l level ] [-[X|M] [-H hom
72a4d21
         parser.add_option("-H", "--homedir", 
72a4d21
                           action="callback", callback=self.__validdir,
72a4d21
                           type="string",
72a4d21
-                          dest="homedir",  
72a4d21
+                          dest="homedir",
72a4d21
                           help=_("alternate home directory to use for mounting"))
72a4d21
 
72a4d21
-        parser.add_option("-T", "--tmpdir", dest="tmpdir",  
72a4d21
+        parser.add_option("-T", "--tmpdir", dest="tmpdir",
72a4d21
                           type="string",
72a4d21
                           action="callback", callback=self.__validdir,
72a4d21
                           help=_("alternate /tmp directory to use for mounting"))
72a4d21
 
72a4d21
         parser.add_option("-w", "--windowsize", dest="windowsize",
72a4d21
                           type="string", default=DEFAULT_WINDOWSIZE,
72a4d21
-                          help="size of the sandbox window")		
72a4d21
+                          help="size of the sandbox window")
72a4d21
 
72a4d21
         parser.add_option("-W", "--windowmanager", dest="wm",  
72a4d21
                           type="string",
72a4d21
@@ -311,9 +335,13 @@ sandbox [-h] [-l level ] [-[X|M] [-H hom
9f197b5
         parser.add_option("-l", "--level", dest="level", 
9f197b5
                           help=_("MCS/MLS level for the sandbox"))
9f197b5
 
9f197b5
-        parser.add_option("-C", "--cgroups",
72a4d21
-                         action="store_true", dest="usecgroup", default=False,
72a4d21
-                         help="Use cgroups to limit this sandbox.")
9f197b5
+        parser.add_option("-c", "--cgroups",
72a4d21
+                          action="store_true", dest="usecgroup", default=False,
72a4d21
+                          help=_("Use cgroups to limit this sandbox."))
72a4d21
+
9f197b5
+        parser.add_option("-C", "--capabilities",
9f197b5
+                         action="store_true", dest="usecaps", default=False,
9f197b5
+                         help="Allow apps requiring capabilities to run within the sandbox.")
9f197b5
 
72a4d21
         self.__parser=parser
f415a12
 
72a4d21
@@ -366,8 +394,8 @@ sandbox [-h] [-l level ] [-[X|M] [-H hom
f415a12
 
72a4d21
            con = selinux.getcon()[1].split(":")
72a4d21
            self.__execcon = "%s:%s:%s:%s" % (con[0], con[1], self.setype, level)
72a4d21
-           self.__filecon = "%s:%s:%s:%s" % (con[0], "object_r", 
72a4d21
-                                             "%s_file_t" % self.setype[:-2], 
72a4d21
+           self.__filecon = "%s:%s:%s:%s" % (con[0], "object_r",
72a4d21
+                                             "%s_file_t" % self.setype[:-2],
72a4d21
                                              level)
72a4d21
     def __setup_dir(self):
72a4d21
            if self.__options.level or self.__options.session:
72a4d21
@@ -392,12 +420,20 @@ sandbox [-h] [-l level ] [-[X|M] [-H hom
9f197b5
     def __execute(self):
9f197b5
            try:
9f197b5
                   cmds = [ SEUNSHARE,  "-Z", self.__execcon ]
9f197b5
-                  if self.__options.usecgroup == True:
9f197b5
+                  if self.__options.usecgroup:
9f197b5
                          cmds.append('-c')
9f197b5
+                  if self.__options.usecaps:
9f197b5
+                         cmds.append('-C')
9f197b5
                   if self.__mount:
9f197b5
                          cmds +=  [ "-t", self.__tmpdir, "-h", self.__homedir ]
9f197b5
 
72a4d21
                          if self.__options.X_ind:
72a4d21
+                                if self.__options.dpi:
72a4d21
+                                       dpi = self.__options.dpi
72a4d21
+                                else:
72a4d21
+                                       import gtk
72a4d21
+                                       dpi = str(gtk.settings_get_default().props.gtk_xft_dpi/1024)
72a4d21
+
72a4d21
                                 xmodmapfile = self.__homedir + "/.xmodmap"
72a4d21
                                 xd = open(xmodmapfile,"w")
72a4d21
                                 subprocess.Popen(["/usr/bin/xmodmap","-pke"],stdout=xd).wait()
72a4d21
@@ -405,7 +441,7 @@ sandbox [-h] [-l level ] [-[X|M] [-H hom
f415a12
 
f415a12
                                 self.__setup_sandboxrc(self.__options.wm)
f415a12
 
f415a12
-                                cmds += [ "--", SANDBOXSH, self.__options.windowsize ]
72a4d21
+                                cmds += [ "--", SANDBOXSH, self.__options.windowsize, dpi ]
f415a12
                          else:
f415a12
                                 cmds += [ "--" ] + self.__paths
f415a12
                          return subprocess.Popen(cmds).wait()
f415a12
diff -up policycoreutils-2.0.86/sandbox/sandboxX.sh.sandbox policycoreutils-2.0.86/sandbox/sandboxX.sh
72a4d21
--- policycoreutils-2.0.86/sandbox/sandboxX.sh.sandbox	2011-06-13 13:44:44.000000000 -0400
72a4d21
+++ policycoreutils-2.0.86/sandbox/sandboxX.sh	2012-01-03 11:10:04.985546365 -0500
9f197b5
@@ -1,10 +1,12 @@
72a4d21
-#!/bin/bash 
f415a12
-context=`id -Z | secon -t `
f415a12
-export TITLE="`grep ^#TITLE: ~/.sandboxrc | /usr/bin/cut -b8-80` ($context)"
f415a12
-[ $# -eq 1 ] && export SCREENSIZE="$1" || export SCREENSIZE="1000x700"
72a4d21
+#!/bin/bash
9f197b5
+trap "" TERM
f415a12
+context=`id -Z | secon -t -l -P`
f415a12
+export TITLE="Sandbox $context -- `grep ^#TITLE: ~/.sandboxrc | /usr/bin/cut -b8-80`"
72a4d21
+[ -z $1 ] && export SCREENSIZE="1000x700" || export SCREENSIZE="$1"
72a4d21
+[ -z $2 ] && export DPI="96" || export DPI="$2"
f415a12
 trap "exit 0" HUP
f415a12
 
f415a12
-(/usr/bin/Xephyr -nolisten tcp -title "$TITLE" -terminate -screen $SCREENSIZE -displayfd 5 5>&1 2>/dev/null) | while read D; do 
72a4d21
+(/usr/bin/Xephyr -title "$TITLE" -terminate -screen $SCREENSIZE -dpi $DPI -displayfd 5 5>&1 2>/dev/null) | while read D; do
f415a12
     export DISPLAY=:$D
f415a12
     cat > ~/seremote << __EOF
f415a12
 #!/bin/sh
9f197b5
@@ -13,7 +15,7 @@ __EOF
9f197b5
     chmod +x ~/seremote
9f197b5
     /usr/share/sandbox/start $HOME/.sandboxrc
9f197b5
     export EXITCODE=$?
9f197b5
-    kill -HUP 0
9f197b5
+    kill -TERM 0
9f197b5
     break
9f197b5
 done
9f197b5
 exit 0
9f197b5
diff -up policycoreutils-2.0.86/sandbox/seunshare.8.sandbox policycoreutils-2.0.86/sandbox/seunshare.8
72a4d21
--- policycoreutils-2.0.86/sandbox/seunshare.8.sandbox	2011-07-07 14:41:16.000000000 -0400
72a4d21
+++ policycoreutils-2.0.86/sandbox/seunshare.8	2012-01-03 11:10:36.498566587 -0500
72a4d21
@@ -3,11 +3,11 @@
9f197b5
 seunshare \- Run cmd with alternate homedir, tmpdir and/or SELinux context
9f197b5
 .SH SYNOPSIS
9f197b5
 .B seunshare
9f197b5
-[ -v ] [ -t tmpdir ] [ -h homedir ] [ -Z context ] -- executable [args]
72a4d21
+[ -v ] [ -c ] [ -C ] [ -k ] [ -t tmpdir ] [ -h homedir ] [ -Z context ] -- executable [args]
9f197b5
 .br
9f197b5
 .SH DESCRIPTION
9f197b5
 .PP
72a4d21
-Run the 
72a4d21
+Run the
72a4d21
 .I executable
72a4d21
 within the specified context, using the alternate home directory and /tmp directory.  The seunshare command unshares from the default namespace, then mounts the specified homedir and tmpdir over the default homedir and /tmp. Finally it tells the kernel to execute the application under the specified SELinux context.
72a4d21
 
9f197b5
@@ -18,9 +18,15 @@ Alternate homedir to be used by the appl
9f197b5
 \fB\-t\ tmpdir
9f197b5
 Use alternate tempory directory to mount on /tmp.  tmpdir must be owned by the user.
9f197b5
 .TP
9f197b5
-\fB\-c cgroups\fR
9f197b5
+\fB\-c --cgroups\fR
9f197b5
 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.
9f197b5
 .TP
9f197b5
+\fB\-C --capabilities\fR
9f197b5
+Allow apps executed within the namespace to use capabilities.  Default is no capabilities.
9f197b5
+.TP
9f197b5
+\fB\-k --kill\fR
9f197b5
+Kill all processes with matching MCS level.
9f197b5
+.TP
9f197b5
 \fB\-Z\ context
9f197b5
 Use alternate SELinux context while runing the executable.
9f197b5
 .TP
72a4d21
@@ -28,10 +34,10 @@ Use alternate SELinux context while runi
72a4d21
 Verbose output
72a4d21
 .SH "SEE ALSO"
72a4d21
 .TP
72a4d21
-runcon(1), sandbox(8), selinux(8)	
72a4d21
+runcon(1), sandbox(8), selinux(8)
72a4d21
 .PP
72a4d21
 .SH AUTHOR
72a4d21
-This manual page was written by 
72a4d21
+This manual page was written by
72a4d21
 .I Dan Walsh <dwalsh@redhat.com>
72a4d21
 and
72a4d21
 .I Thomas Liu <tliu@fedoraproject.org>
f415a12
diff -up policycoreutils-2.0.86/sandbox/seunshare.c.sandbox policycoreutils-2.0.86/sandbox/seunshare.c
72a4d21
--- policycoreutils-2.0.86/sandbox/seunshare.c.sandbox	2011-06-13 13:44:44.000000000 -0400
72a4d21
+++ policycoreutils-2.0.86/sandbox/seunshare.c	2012-01-03 11:08:59.081504712 -0500
72a4d21
@@ -5,8 +5,9 @@
72a4d21
 
72a4d21
 #define _GNU_SOURCE
72a4d21
 #include <signal.h>
72a4d21
-#include <sys/types.h>
72a4d21
+#include <sys/fsuid.h>
72a4d21
 #include <sys/stat.h>
72a4d21
+#include <sys/types.h>
72a4d21
 #include <sys/wait.h>
72a4d21
 #include <syslog.h>
72a4d21
 #include <sys/mount.h>
72a4d21
@@ -18,7 +19,6 @@
72a4d21
 #include <stdio.h>
72a4d21
 #include <regex.h>
72a4d21
 #include <unistd.h>
72a4d21
-#include <sys/fsuid.h>
72a4d21
 #include <stdlib.h>
72a4d21
 #include <cap-ng.h>
72a4d21
 #include <getopt.h>		/* for getopt_long() form of getopt() */
9f197b5
@@ -29,6 +29,7 @@
9f197b5
 
9f197b5
 #include <selinux/selinux.h>
9f197b5
 #include <selinux/context.h>	/* for context-mangling functions */
9f197b5
+#include <dirent.h>
9f197b5
 
9f197b5
 #ifdef USE_NLS
9f197b5
 #include <locale.h>		/* for setlocale() */
72a4d21
@@ -42,8 +43,8 @@
72a4d21
 #define MS_REC 1<<14
72a4d21
 #endif
72a4d21
 
72a4d21
-#ifndef MS_PRIVATE
72a4d21
-#define MS_PRIVATE 1<<18
72a4d21
+#ifndef MS_SLAVE
72a4d21
+#define MS_SLAVE 1<<19
72a4d21
 #endif
72a4d21
 
72a4d21
 #ifndef PACKAGE
72a4d21
@@ -52,21 +53,22 @@
72a4d21
 
9f197b5
 #define BUF_SIZE 1024
9f197b5
 #define DEFAULT_PATH "/usr/bin:/bin"
72a4d21
-
9f197b5
-#define USAGE_STRING _("USAGE: seunshare [ -v ] [ -c ] -t tmpdir -h homedir [-Z context] -- executable [args]")
72a4d21
+#define USAGE_STRING _("USAGE: seunshare [ -v ] [ -C ] [ -c ] [ -k ] [ -t tmpdir ] [ -h homedir ] [ -Z CONTEXT ] -- executable [args] ")
9f197b5
 
9f197b5
 static int verbose = 0;
9f197b5
+static int child = 0;
9f197b5
 
9f197b5
+static capng_select_t cap_set = CAPNG_SELECT_BOTH;
9f197b5
 
9f197b5
 /**
9f197b5
  * This function will drop all capabilities.
f415a12
  */
f415a12
 static int drop_caps()
f415a12
 {
f415a12
-	if (capng_have_capabilities(CAPNG_SELECT_BOTH) == CAPNG_NONE)
9f197b5
+	if (capng_have_capabilities(cap_set) == CAPNG_NONE)
f415a12
 		return 0;
f415a12
-	capng_clear(CAPNG_SELECT_BOTH);
f415a12
-	if (capng_lock() == -1 || capng_apply(CAPNG_SELECT_BOTH) == -1) {
9f197b5
+	capng_clear(cap_set);
9f197b5
+	if (capng_lock() == -1 || capng_apply(cap_set) == -1) {
f415a12
 		fprintf(stderr, _("Failed to drop all capabilities\n"));
f415a12
 		return -1;
f415a12
 	}
72a4d21
@@ -86,6 +88,13 @@ static int drop_privs(uid_t uid)
9f197b5
 }
9f197b5
 
9f197b5
 /**
9f197b5
+ * If the user sends a siginto to seunshare, kill the child's session
9f197b5
+ */
9f197b5
+void handler(int sig) {
9f197b5
+	if (child > 0) kill(-child,sig);
9f197b5
+}
9f197b5
+
9f197b5
+/**
9f197b5
  * Take care of any signal setup.
9f197b5
  */
9f197b5
 static int set_signal_handles(void)
72a4d21
@@ -101,11 +110,16 @@ static int set_signal_handles(void)
9f197b5
 	(void)sigprocmask(SIG_SETMASK, &empty, NULL);
9f197b5
 
9f197b5
 	/* Terminate on SIGHUP */
9f197b5
-	if (signal(SIGHUP, SIG_IGN) == SIG_ERR) {
9f197b5
+	if (signal(SIGHUP, SIG_DFL) == SIG_ERR) {
72a4d21
 		perror("Unable to set SIGHUP handler");
72a4d21
 		return -1;
72a4d21
 	}
72a4d21
 
72a4d21
+	if (signal(SIGINT, handler) == SIG_ERR) {
72a4d21
+		perror("Unable to set SIGINT handler");
9f197b5
+		return -1;
9f197b5
+	}
9f197b5
+
72a4d21
 	return 0;
72a4d21
 }
72a4d21
 
72a4d21
@@ -192,7 +206,7 @@ static int verify_directory(const char *
72a4d21
 	struct stat sb;
72a4d21
 
72a4d21
 	if (st_out == NULL) st_out = &sb;
72a4d21
-	
72a4d21
+
72a4d21
 	if (lstat(dir, st_out) == -1) {
72a4d21
 		fprintf(stderr, _("Failed to stat %s: %s\n"), dir, strerror(errno));
9f197b5
 		return -1;
72a4d21
@@ -241,7 +255,7 @@ static int verify_shell(const char *shel
72a4d21
  */
72a4d21
 static int seunshare_mount(const char *src, const char *dst, struct stat *src_st)
72a4d21
 {
72a4d21
-	int flags = MS_REC;
72a4d21
+	int flags = 0;
72a4d21
 	int is_tmp = 0;
72a4d21
 
72a4d21
 	if (verbose)
72a4d21
@@ -253,14 +267,6 @@ static int seunshare_mount(const char *s
9f197b5
 	}
72a4d21
 
72a4d21
 	/* mount directory */
72a4d21
-	if (mount(dst, dst,  NULL, MS_BIND | flags, NULL) < 0) {
72a4d21
-		fprintf(stderr, _("Failed to mount %s on %s: %s\n"), dst, dst, strerror(errno));
72a4d21
-		return -1;
72a4d21
-	}
72a4d21
-	if (mount(dst, dst, NULL, MS_PRIVATE | flags, NULL) < 0) {
72a4d21
-		fprintf(stderr, _("Failed to make %s private: %s\n"), dst, strerror(errno));
72a4d21
-		return -1;
72a4d21
-	}
72a4d21
 	if (mount(src, dst, NULL, MS_BIND | flags, NULL) < 0) {
72a4d21
 		fprintf(stderr, _("Failed to mount %s on %s: %s\n"), src, dst, strerror(errno));
72a4d21
 		return -1;
72a4d21
@@ -274,14 +280,6 @@ static int seunshare_mount(const char *s
72a4d21
 		if (verbose)
72a4d21
 			printf(_("Mounting /tmp on /var/tmp\n"));
72a4d21
 
72a4d21
-		if (mount("/var/tmp", "/var/tmp",  NULL, MS_BIND | flags, NULL) < 0) {
72a4d21
-			fprintf(stderr, _("Failed to mount /var/tmp on /var/tmp: %s\n"), strerror(errno));
72a4d21
-			return -1;
72a4d21
-		}
72a4d21
-		if (mount("/var/tmp", "/var/tmp", NULL, MS_PRIVATE | flags, NULL) < 0) {
72a4d21
-			fprintf(stderr, _("Failed to make /var/tmp private: %s\n"), strerror(errno));
72a4d21
-			return -1;
72a4d21
-		}
72a4d21
 		if (mount("/tmp", "/var/tmp",  NULL, MS_BIND | flags, NULL) < 0) {
72a4d21
 			fprintf(stderr, _("Failed to mount /tmp on /var/tmp: %s\n"), strerror(errno));
72a4d21
 			return -1;
72a4d21
@@ -308,12 +306,12 @@ static int sandbox_error(const char *str
72a4d21
 static int match(const char *string, char *pattern)
72a4d21
 {
72a4d21
 	int status;
72a4d21
-	regex_t re; 
72a4d21
+	regex_t re;
72a4d21
 	if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0) {
72a4d21
 		return 0;
72a4d21
 	}
72a4d21
 	status = regexec(&re, string, (size_t)0, NULL, 0);
72a4d21
-	regfree(&re);	
72a4d21
+	regfree(&re);
72a4d21
 	if (status != 0) {
72a4d21
 		return 0;
72a4d21
 	}
72a4d21
@@ -334,8 +332,9 @@ static int setup_cgroups()
9f197b5
 	char buf[BUF_SIZE];
9f197b5
 	char *tok = NULL;
9f197b5
 	int rc = -1;
72a4d21
-	const char* fname = "/etc/sysconfig/sandbox";	
72a4d21
-	
9f197b5
+	char *str = NULL;
72a4d21
+	const char* fname = "/etc/sysconfig/sandbox";
72a4d21
+
9f197b5
 	if ((fp = fopen(fname, "rt")) == NULL) {
72a4d21
 		fprintf(stderr, "Error opening sandbox config file.");
72a4d21
 		return rc;
72a4d21
@@ -343,12 +342,15 @@ static int setup_cgroups()
72a4d21
 	while(fgets(buf, BUF_SIZE, fp) != NULL) {
72a4d21
 		/* Skip comments */
72a4d21
 		if (buf[0] == '#') continue;
72a4d21
-		
72a4d21
+
9f197b5
 		/* Copy the string, ignoring whitespace */
9f197b5
 		int len = strlen(buf);
9f197b5
-		char *str = malloc((len + 1) * sizeof(char));
72a4d21
-		
72a4d21
-		int ind = 0;	
9f197b5
+		free(str);
9f197b5
+		str = malloc((len + 1) * sizeof(char));
72a4d21
+		if (!str)
72a4d21
+			goto err;
72a4d21
+
72a4d21
+		int ind = 0;
9f197b5
 		int i;
72a4d21
 		for (i = 0; i < len; i++) {
72a4d21
 			char cur = buf[i];
72a4d21
@@ -358,7 +360,7 @@ static int setup_cgroups()
72a4d21
 			}
72a4d21
 		}
72a4d21
 		str[ind] = '\0';
72a4d21
-		
72a4d21
+
72a4d21
 		tok = strtok(str, "=\n");
72a4d21
 		if (tok != NULL) {
72a4d21
 			if (!strcmp(tok, "CPUAFFINITY")) {
72a4d21
@@ -382,7 +384,7 @@ static int setup_cgroups()
72a4d21
 					fprintf(stderr, "Error parsing config file.");
72a4d21
 					goto err;
72a4d21
 				}
72a4d21
-				
72a4d21
+
72a4d21
 			} else if (!strcmp(tok, "CPUUSAGE")) {
72a4d21
 				tok = strtok(NULL, "=\n");
72a4d21
 				if (match(tok, "^[0-9]+\%")) {
72a4d21
@@ -400,14 +402,14 @@ static int setup_cgroups()
72a4d21
 				continue;
72a4d21
 			}
72a4d21
 		}
72a4d21
-		
72a4d21
+
72a4d21
 	}
72a4d21
 	if (mem == NULL) {
72a4d21
 		long phypz = sysconf(_SC_PHYS_PAGES);
72a4d21
 		long psize = sysconf(_SC_PAGE_SIZE);
72a4d21
 		memusage = phypz * psize * (float) memusage / 100.0;
72a4d21
 	}
72a4d21
-	
72a4d21
+
72a4d21
 	cgroup_init();
72a4d21
 
72a4d21
 	int64_t current_runtime = 0;
72a4d21
@@ -423,8 +425,8 @@ static int setup_cgroups()
72a4d21
 		cgroup_get_cgroup(curr);
72a4d21
 		cgroup_get_value_int64(cgroup_get_controller(curr, "cpu"), "cpu.rt_runtime_us", &current_runtime);
72a4d21
 		cgroup_get_value_int64(cgroup_get_controller(curr, "cpu"), "cpu.rt_period_us", &current_period);
72a4d21
-	}   
72a4d21
-	
72a4d21
+	}
72a4d21
+
72a4d21
 	ret  = cgroup_get_current_controller_path(getpid(), "memory", &curr_mem_path);
72a4d21
 	if (ret) {
72a4d21
 		sandbox_error("Error while trying to get current controller path.\n");
72a4d21
@@ -432,33 +434,33 @@ static int setup_cgroups()
72a4d21
 		struct cgroup *curr = cgroup_new_cgroup(curr_mem_path);
72a4d21
 		cgroup_get_cgroup(curr);
72a4d21
 		cgroup_get_value_int64(cgroup_get_controller(curr, "memory"), "memory.limit_in_bytes", &current_mem);
72a4d21
-	}   
72a4d21
-	
72a4d21
+	}
72a4d21
+
72a4d21
 	if (((float) cpupercentage)  / 100.0> (float)current_runtime / (float) current_period) {
72a4d21
 		sandbox_error("CPU usage restricted!\n");
72a4d21
 		goto err;
72a4d21
-	}   
72a4d21
-	
72a4d21
-	if (mem == NULL) {	
72a4d21
+	}
72a4d21
+
72a4d21
+	if (mem == NULL) {
72a4d21
 		if (memusage > current_mem) {
72a4d21
 			sandbox_error("Attempting to use more memory than allowed!");
72a4d21
 			goto err;
72a4d21
 		}
72a4d21
 	}
72a4d21
-	
72a4d21
+
72a4d21
 	long nprocs = sysconf(_SC_NPROCESSORS_ONLN);
72a4d21
-	
72a4d21
-	struct sched_param sp; 
72a4d21
+
72a4d21
+	struct sched_param sp;
72a4d21
 	sp.sched_priority = sched_get_priority_min(SCHED_FIFO);
72a4d21
 	sched_setscheduler(getpid(), SCHED_FIFO, &sp);
72a4d21
 	struct cgroup *sandbox_group = cgroup_new_cgroup(cgroupname);
72a4d21
 	cgroup_add_controller(sandbox_group, "memory");
72a4d21
 	cgroup_add_controller(sandbox_group, "cpu");
72a4d21
-	
72a4d21
+
72a4d21
 	if (mem == NULL) {
72a4d21
 		if (memusage > 0) {
72a4d21
 			cgroup_set_value_uint64(cgroup_get_controller(sandbox_group, "memory"), "memory.limit_in_bytes", memusage);
72a4d21
-		}	
72a4d21
+		}
72a4d21
 	} else {
72a4d21
 		cgroup_set_value_string(cgroup_get_controller(sandbox_group, "memory"), "memory.limit_in_bytes", mem);
72a4d21
 	}
72a4d21
@@ -470,13 +472,13 @@ static int setup_cgroups()
72a4d21
 	if (cpus != NULL) {
72a4d21
 		cgroup_set_value_string(cgroup_get_controller(sandbox_group, "cpu"), "cgroup.procs",cpus);
72a4d21
 	}
72a4d21
-	
72a4d21
+
72a4d21
 	uint64_t allocated_mem;
72a4d21
 	if (cgroup_get_value_uint64(cgroup_get_controller(sandbox_group, "memory"), "memory.limit_in_bytes", &allocated_mem) > current_mem) {
72a4d21
 		sandbox_error("Attempting to use more memory than allowed!\n");
72a4d21
 		goto err;
72a4d21
 	}
72a4d21
-	
72a4d21
+
72a4d21
 	rc = cgroup_create_cgroup(sandbox_group, 1);
72a4d21
 	if (rc != 0) {
72a4d21
 		sandbox_error("Failed to create group.  Ensure that cgconfig service is running. \n");
72a4d21
@@ -487,13 +489,15 @@ static int setup_cgroups()
9f197b5
 
9f197b5
 	rc = 0;
9f197b5
 err:
9f197b5
+	fclose(fp);
9f197b5
+	free(str);
9f197b5
 	free(mem);
9f197b5
 	free(cgroupname);
9f197b5
 	free(cpus);
72a4d21
 	return rc;
72a4d21
 }
72a4d21
 
72a4d21
-/* 
72a4d21
+/*
72a4d21
    If path is empy or ends with  "/." or "/.. return -1 else return 0;
72a4d21
  */
72a4d21
 static int bad_path(const char *path) {
72a4d21
@@ -515,7 +519,7 @@ static int bad_path(const char *path) {
72a4d21
 	return 0;
72a4d21
 }
72a4d21
 
72a4d21
-static int rsynccmd(const char * src, const char *dst, char **cmdbuf) 
72a4d21
+static int rsynccmd(const char * src, const char *dst, char **cmdbuf)
72a4d21
 {
72a4d21
 	char *buf = NULL;
72a4d21
 	char *newbuf = NULL;
72a4d21
@@ -559,7 +563,7 @@ static int rsynccmd(const char * src, co
72a4d21
 		newbuf = NULL;
72a4d21
 	}
72a4d21
 
72a4d21
-	if (buf) { 
72a4d21
+	if (buf) {
72a4d21
 		if (asprintf(&newbuf, "/usr/bin/rsync -trlHDq %s '%s'", buf, dst) == -1) {
72a4d21
 			fprintf(stderr, "Out of memory\n");
72a4d21
 			goto err;
72a4d21
@@ -674,8 +678,12 @@ static char *create_tmpdir(const char *s
72a4d21
 	if (verify_directory(tmpdir, NULL, out_st) < 0) {
72a4d21
 		goto err;
72a4d21
 	}
72a4d21
-	if (check_owner_uid(0, tmpdir, out_st) < 0) goto err;
72a4d21
-	if (check_owner_gid(getgid(), tmpdir, out_st) < 0) goto err;
72a4d21
+
72a4d21
+	if (check_owner_uid(0, tmpdir, out_st) < 0)
72a4d21
+		goto err;
72a4d21
+
72a4d21
+	if (check_owner_gid(getgid(), tmpdir, out_st) < 0)
72a4d21
+		goto err;
72a4d21
 
72a4d21
 	/* change permissions of the temporary directory */
72a4d21
 	if ((fd_t = open(tmpdir, O_RDONLY)) < 0) {
72a4d21
@@ -702,7 +710,7 @@ static char *create_tmpdir(const char *s
72a4d21
 
72a4d21
 	/* copy selinux context */
72a4d21
 	if (execcon) {
72a4d21
-		if (fsetfilecon(fd_t, con) == -1) {	
72a4d21
+		if (fsetfilecon(fd_t, con) == -1) {
72a4d21
 			fprintf(stderr, _("Failed to set context of the directory %s: %s\n"), tmpdir, strerror(errno));
72a4d21
 			goto err;
72a4d21
 		}
72a4d21
@@ -734,12 +742,77 @@ good:
9f197b5
 	return tmpdir;
9f197b5
 }
9f197b5
 
9f197b5
+#define PROC_BASE "/proc"
9f197b5
+
9f197b5
+static int
9f197b5
+killall (security_context_t execcon)
9f197b5
+{
9f197b5
+	DIR *dir;
9f197b5
+	security_context_t scon;
9f197b5
+	struct dirent *de;
9f197b5
+	pid_t *pid_table, pid, self;
9f197b5
+	int i;
9f197b5
+	int pids, max_pids;
9f197b5
+	int running = 0;
9f197b5
+	self = getpid();
9f197b5
+	if (!(dir = opendir(PROC_BASE))) {
9f197b5
+		return -1;
9f197b5
+	}
9f197b5
+	max_pids = 256;
9f197b5
+	pid_table = malloc(max_pids * sizeof (pid_t));
9f197b5
+	if (!pid_table) {
72a4d21
+		(void)closedir(dir);
9f197b5
+		return -1;
9f197b5
+	}
9f197b5
+	pids = 0;
9f197b5
+	context_t con;
9f197b5
+	con = context_new(execcon);
9f197b5
+	const char *mcs = context_range_get(con);
9f197b5
+	printf("mcs=%s\n", mcs);
9f197b5
+	while ((de = readdir (dir)) != NULL) {
9f197b5
+		if (!(pid = (pid_t)atoi(de->d_name)) || pid == self)
9f197b5
+			continue;
9f197b5
+
9f197b5
+		if (pids == max_pids) {
9f197b5
+			if (!(pid_table = realloc(pid_table, 2*pids*sizeof(pid_t)))) {
72a4d21
+				(void)closedir(dir);
9f197b5
+				return -1;
9f197b5
+			}
9f197b5
+			max_pids *= 2;
9f197b5
+		}
9f197b5
+		pid_table[pids++] = pid;
9f197b5
+	}
9f197b5
+
9f197b5
+	(void)closedir(dir);
9f197b5
+
9f197b5
+	for (i = 0; i < pids; i++) {
9f197b5
+		pid_t id = pid_table[i];
9f197b5
+
9f197b5
+		if (getpidcon(id, &scon) == 0) {
72a4d21
+
9f197b5
+			context_t pidcon = context_new(scon);
9f197b5
+			/* Attempt to kill remaining processes */
9f197b5
+			if (strcmp(context_range_get(pidcon), mcs) == 0)
9f197b5
+				kill(id, SIGKILL);
9f197b5
+
9f197b5
+			context_free(pidcon);
9f197b5
+			freecon(scon);
9f197b5
+		}
9f197b5
+		running++;
9f197b5
+	}
9f197b5
+
9f197b5
+	context_free(con);
9f197b5
+	free(pid_table);
9f197b5
+	return running;
9f197b5
+}
9f197b5
+
9f197b5
 int main(int argc, char **argv) {
9f197b5
 	int status = -1;
9f197b5
 	security_context_t execcon = NULL;
9f197b5
 
9f197b5
 	int clflag;		/* holds codes for command line flags */
9f197b5
 	int usecgroups = 0;
9f197b5
+	int kill_all = 0;
9f197b5
 
9f197b5
 	char *homedir_s = NULL;	/* homedir spec'd by user in argv[] */
9f197b5
 	char *tmpdir_s = NULL;	/* tmpdir spec'd by user in argv[] */
72a4d21
@@ -752,18 +825,21 @@ int main(int argc, char **argv) {
9f197b5
 	const struct option long_options[] = {
9f197b5
 		{"homedir", 1, 0, 'h'},
9f197b5
 		{"tmpdir", 1, 0, 't'},
9f197b5
+		{"kill", 1, 0, 'k'},
9f197b5
 		{"verbose", 1, 0, 'v'},
9f197b5
 		{"cgroups", 1, 0, 'c'},
9f197b5
 		{"context", 1, 0, 'Z'},
9f197b5
+		{"capabilities", 1, 0, 'C'},
9f197b5
 		{NULL, 0, 0, 0}
9f197b5
 	};
9f197b5
 
72a4d21
 	uid_t uid = getuid();
72a4d21
-
72a4d21
+/*
72a4d21
 	if (!uid) {
72a4d21
 		fprintf(stderr, _("Must not be root"));
72a4d21
 		return -1;
72a4d21
 	}
72a4d21
+*/
72a4d21
 
72a4d21
 #ifdef USE_NLS
72a4d21
 	setlocale(LC_ALL, "");
72a4d21
@@ -783,7 +859,7 @@ int main(int argc, char **argv) {
9f197b5
 	}
9f197b5
 
9f197b5
 	while (1) {
9f197b5
-		clflag = getopt_long(argc, argv, "cvh:t:Z:", long_options, NULL);
9f197b5
+		clflag = getopt_long(argc, argv, "Ccvh:t:Z:", long_options, NULL);
9f197b5
 		if (clflag == -1)
9f197b5
 			break;
9f197b5
 
72a4d21
@@ -791,6 +867,9 @@ int main(int argc, char **argv) {
9f197b5
 		case 't':
9f197b5
 			tmpdir_s = optarg;
9f197b5
 			break;
9f197b5
+		case 'k':
9f197b5
+			kill_all = 1;
9f197b5
+			break;
9f197b5
 		case 'h':
9f197b5
 			homedir_s = optarg;
9f197b5
 			break;
72a4d21
@@ -800,6 +879,9 @@ int main(int argc, char **argv) {
9f197b5
 		case 'c':
9f197b5
 			usecgroups = 1;
9f197b5
 			break;
9f197b5
+		case 'C':
9f197b5
+			cap_set = CAPNG_SELECT_CAPS;
9f197b5
+			break;
9f197b5
 		case 'Z':
9f197b5
 			execcon = optarg;
9f197b5
 			break;
72a4d21
@@ -824,9 +906,11 @@ int main(int argc, char **argv) {
72a4d21
 		return -1;
72a4d21
 	}
72a4d21
 
72a4d21
-	if (set_signal_handles()) return -1;
72a4d21
+	if (set_signal_handles())
72a4d21
+		return -1;
72a4d21
 
72a4d21
-	if (usecgroups && setup_cgroups() < 0) return  -1;
72a4d21
+	if (usecgroups && setup_cgroups() < 0)
72a4d21
+		return  -1;
72a4d21
 
72a4d21
 	/* set fsuid to ruid */
72a4d21
 	/* Changing fsuid is usually required when user-specified directory is
72a4d21
@@ -851,7 +935,7 @@ int main(int argc, char **argv) {
9f197b5
 	}
9f197b5
 
9f197b5
 	/* spawn child process */
9f197b5
-	int child = fork();
9f197b5
+	child = fork();
9f197b5
 	if (child == -1) {
9f197b5
 		perror(_("Unable to fork"));
9f197b5
 		goto err;
72a4d21
@@ -859,6 +943,7 @@ int main(int argc, char **argv) {
72a4d21
 
72a4d21
 	if (child == 0) {
72a4d21
 		char *display = NULL;
72a4d21
+		char *LANG = NULL;
72a4d21
 		int rc = -1;
72a4d21
 
72a4d21
 		if (unshare(CLONE_NEWNS) < 0) {
72a4d21
@@ -866,6 +951,13 @@ int main(int argc, char **argv) {
72a4d21
 			goto childerr;
72a4d21
 		}
72a4d21
 
72a4d21
+		/* Remount / as SLAVE so that nothing mounted in the namespace 
72a4d21
+		   shows up in the parent */
72a4d21
+		if (mount("none", "/", NULL, MS_SLAVE | MS_REC , NULL) < 0) {
72a4d21
+			perror(_("Failed to make / a SLAVE mountpoint\n"));
72a4d21
+			goto childerr;
72a4d21
+		}
72a4d21
+
72a4d21
 		/* assume fsuid==ruid after this point */
72a4d21
 		setfsuid(uid);
72a4d21
 
72a4d21
@@ -884,12 +976,23 @@ int main(int argc, char **argv) {
72a4d21
 				goto childerr;
72a4d21
 			}
72a4d21
 		}
72a4d21
+		
72a4d21
+		/* construct a new environment */
72a4d21
+		if ((LANG = getenv("LANG")) != NULL) {
72a4d21
+			if ((LANG = strdup(LANG)) == NULL) {
72a4d21
+				perror(_("Out of memory"));
72a4d21
+				goto childerr;
72a4d21
+			}
72a4d21
+		}
72a4d21
+		
72a4d21
 		if ((rc = clearenv()) != 0) {
72a4d21
 			perror(_("Failed to clear environment"));
72a4d21
 			goto childerr;
72a4d21
 		}
72a4d21
-		if (display) 
72a4d21
+		if (display)
72a4d21
 			rc |= setenv("DISPLAY", display, 1);
72a4d21
+		if (LANG) 
72a4d21
+			rc |= setenv("LANG", LANG, 1);
72a4d21
 		rc |= setenv("HOME", pwd->pw_dir, 1);
72a4d21
 		rc |= setenv("SHELL", pwd->pw_shell, 1);
72a4d21
 		rc |= setenv("USER", pwd->pw_name, 1);
72a4d21
@@ -899,7 +1002,7 @@ int main(int argc, char **argv) {
72a4d21
 			fprintf(stderr, _("Failed to construct environment\n"));
72a4d21
 			goto childerr;
72a4d21
 		}
72a4d21
-		
72a4d21
+
72a4d21
 		/* selinux context */
72a4d21
 		if (execcon && setexeccon(execcon) != 0) {
72a4d21
 			fprintf(stderr, _("Could not set exec context to %s.\n"), execcon);
72a4d21
@@ -910,13 +1013,12 @@ int main(int argc, char **argv) {
72a4d21
 			perror(_("Failed to change dir to homedir"));
72a4d21
 			goto childerr;
72a4d21
 		}
72a4d21
-
72a4d21
 		setsid();
72a4d21
-
72a4d21
 		execv(argv[optind], argv + optind);
72a4d21
 		fprintf(stderr, _("Failed to execute command %s: %s\n"), argv[optind], strerror(errno));
72a4d21
 childerr:
72a4d21
 		free(display);
72a4d21
+		free(LANG);
72a4d21
 		exit(-1);
72a4d21
 	}
72a4d21
 
72a4d21
@@ -926,10 +1028,15 @@ childerr:
9f197b5
 	waitpid(child, &status, 0);
9f197b5
 	status_to_retval(status, status);
9f197b5
 
9f197b5
+	/* Make sure all child processes exit */
9f197b5
+	kill(-child,SIGTERM);
9f197b5
+
df86366
+	if (execcon && kill_all)
9f197b5
+		killall(execcon);
9f197b5
+
9f197b5
 	if (tmpdir_r) cleanup_tmpdir(tmpdir_r, tmpdir_s, pwd, 1);
9f197b5
 
9f197b5
 err:
72a4d21
 	free(tmpdir_r);
72a4d21
 	return status;
72a4d21
 }
72a4d21
-