capsh --user is available from f14 only
[lxc-userspace.git] / lxcsu-internal
index 894b08e..e303583 100755 (executable)
@@ -3,7 +3,6 @@
 
 import setns
 import os
-import sys
 
 from argparse import ArgumentParser
 
@@ -142,6 +141,9 @@ def main ():
 
     setns.chcontext('/proc/%s/ns/uts'%pid)
     setns.chcontext('/proc/%s/ns/ipc'%pid)
+    
+    if (not args.pidns):
+        setns.chcontext('/proc/%s/ns/pid'%pid)
 
     if (not args.netns):
         setns.chcontext('/proc/%s/ns/net'%pid)
@@ -149,12 +151,15 @@ def main ():
     if (not args.mntns):
         setns.chcontext('/proc/%s/ns/mnt'%pid)
 
-    if (not args.pidns):
-        setns.chcontext('/proc/%s/ns/pid'%pid)
+    
 
+    proc_mounted = False
     if (not os.access('/proc/self',0)):
+        proc_mounted = True
         setns.proc_mount()
 
+    
+
     # cgroups is not yet LXC-safe, so we need to use the course grained access control
     # strategy of unmounting the filesystem
 
@@ -171,20 +176,48 @@ def main ():
 
     pid = os.fork()
 
+    # capsh has a --user option starting with f14
+    # so if only for f12 we need to fake this one
+    #
+    # capsh.c does essentially the following when invoked with --user:
+    #      pwd = getpwnam(user); ...
+    #      ngroups = MAX_GROUPS; 
+    #      status = getgrouplist(user, pwd->pw_gid, groups, &ngroups); ...
+    #      status = setgroups(ngroups, groups); ...
+    #      status = setgid(pwd->pw_gid); ...
+    #      status = setuid(pwd->pw_uid); ...
+    # however we cannot simulate that ourselves because if we did in this process then
+    # capsh could not be allowed to mess with caps any more
+
+    def getuid (slicename):
+        import pwd
+        try:
+            return pwd.getpwnam(slicename).pw_uid
+        except:
+            return
+
     if (pid == 0):
         cap_arg = '--drop='+drop_capabilities
 
         if (not args.root):
-            exec_args = [arch,'/usr/sbin/capsh',cap_arg,'--','--login']+args.command_to_run
-# Thierry's suggestion:exec_args = [arch,'/usr/sbin/capsh',cap_arg,'--user=%s'%slice_name,'--','--login',]+args.command_to_run
+            uid = getuid (slice_name)
+            if not uid:
+                print "lxcsu-internal could not spot %s in /etc/passwd - exiting"%slice_name
+                exit(1)
+            exec_args = [arch,'/usr/sbin/capsh',cap_arg,'--uid=%s'%uid,'--','--login',]+args.command_to_run
+# once we can drop f12, it would be nicer to instead go for
+#            exec_args = [arch,'/usr/sbin/capsh',cap_arg,'--user=%s'%slice_name,'--','--login',]+args.command_to_run
         else:
             exec_args = [arch,'/usr/sbin/capsh','--','--login']+args.command_to_run
 
         os.environ['SHELL'] = '/bin/sh'
-# Thierry's suggestion:os.environ['HOME'] = '/home/%s'%slice_name
+        os.environ['HOME'] = '/home/%s'%slice_name
+        os.environ['LD_PRELOAD'] = '/etc/planetlab/lib/bind_public.so'
+        os.chdir("/home/%s"%(slice_name))
         if debug: print 'lxcsu-internal:execv:','/usr/bin/setarch',exec_args
         os.execv('/usr/bin/setarch',exec_args)
     else:
+        setns.proc_umount()
         _,status = os.waitpid(pid,0)
         exit(os.WEXITSTATUS(status))