Fixed captive-sandbox-server(8) regarding: captive_standalone_init()
[captive.git] / src / client / sandbox-server / main.c
index 4ade0fa..7735da7 100644 (file)
@@ -41,6 +41,7 @@
 #include <sys/file.h>
 #include <sys/resource.h>
 #include <orbit/orb-core/corba-defs.h>
+#include "captive/client.h"
 
 #ifdef HAVE_ORBIT_LINK
 char *link_get_tmpdir(void);
@@ -312,7 +313,23 @@ struct rlimit rlim;
                fatal("Unsuccessful setrlimit(%s)",resource_string);
 }
 
-static gchar *chrooted_orbit_dir;
+static void sandbox_server_mkdir_p(const gchar *dirpathname)
+{
+gchar *pathname=(/* de-const */ gchar *)captive_strdup_alloca(dirpathname);
+gchar *gs,*gs2;
+
+       /* Missing mkdir(2) of the last component path is intentional: */
+       for (gs=pathname;(gs2=strchr(gs,'/'));gs=gs2) {
+               *gs2='\0';
+               if (*pathname && mkdir(pathname,S_ISVTX|0777)) {
+                       if (errno!=EEXIST)
+                               fatal("Failed to mkdir(\"%s\"): %m",pathname);
+                       }
+               *gs2++='/';
+               }
+}
+
+static const gchar *chrooted_orbit_dir;
 
 static void chroot_setup(gboolean fragile)
 {
@@ -382,6 +399,15 @@ struct passwd *want_uid_passwd;
        g_get_home_dir();
        g_get_tmp_dir();
 
+       /* Pre-resolve "link_get_tmpdir" symbol to prevent its later failed
+        * resolving in chroot(2) mode in Debian dynamic build.
+        */
+#ifdef HAVE_ORBIT_LINK
+       g_free(link_get_tmpdir());      /* returns g_strdup()ed string */
+#else
+       g_free(linc_get_tmpdir());      /* returns g_strdup()ed string */
+#endif
+
        if (fragile && !optarg_chroot)
                fatal("Fragile setuid/root environment but no --chroot set");
        if (optarg_chroot) {
@@ -405,8 +431,10 @@ gint gi;
                        }
                g_rand_free(grand);
                *s=0;
-               if (geteuid()==0)       /* Not 'fragile' as we can be native 'root'. */
+               if (geteuid()==0) {     /* Not 'fragile' as we can be native 'root'. */
                        chrooted_cleanuplockeddirs(optarg_chroot,"s-");
+                       chrooted_cleanuplockeddirs(captive_printf_alloca("%s/tmp",optarg_chroot),"captive-orbit-");
+                       }
                chroot_pid_dir=captive_printf_alloca("%s/s-%d",optarg_chroot,(int)getpid());
                chrooted_createdir(chroot_pid_dir,(!optarg_setuid ? (uid_t)-1 : want_uid),(!optarg_setgid ? (gid_t)-1 : want_gid),
                                TRUE);  /* lock */
@@ -444,7 +472,7 @@ gint gi;
        /* Prepare /t for /t/o-$PID directories for ORBit2
         * and also for parent's hardlink to its /t/o-$pid directory. */
        if (optarg_chroot) {
-gchar *chrooted_orbit_dir_old,*gs,*gs2;
+gchar *chrooted_orbit_dir_old;
 
                if (mkdir("/t",S_ISVTX|0777)) {
                        if (errno!=EEXIST)
@@ -463,20 +491,14 @@ FILE *f;
                        }
                g_assert(chroot_pid_hashkey_dir!=NULL);
                chrooted_orbit_dir=g_strdup_printf("%s/t/o-%d",chroot_pid_hashkey_dir,getpid());
-               /* Missing mkdir(2) of the last component path is intentional: */
-               for (gs=chrooted_orbit_dir;(gs2=strchr(gs,'/'));gs=gs2) {
-                       *gs2='\0';
-                       if (*chrooted_orbit_dir && mkdir(chrooted_orbit_dir,S_ISVTX|0777)) {
-                               if (errno!=EEXIST)
-                                       fatal("Failed to mkdir(\"%s\"): %m",chrooted_orbit_dir);
-                               }
-                       *gs2++='/';
-                       }
-               /* Prepare '/tmp' for the initial CORBA_ORB_init() default path: */
-               if (mkdir("/tmp",S_ISVTX|0777)) {
-                       if (errno!=EEXIST)
-                               fatal("Failed to mkdir(\"%s\"): %m","/tmp");
-                       }
+               /* Last pathname component is not created: */
+               sandbox_server_mkdir_p(chrooted_orbit_dir);
+               /* Prepare '/tmp' for the initial CORBA_ORB_init() default path.
+                * Workaround sandbox_server_mkdir_p() does not create last component.
+                * Do not use '/tmp' directly as some distributions may set custom
+                * tmpdir pathname by $ENV{"TMPDIR"} etc.
+                */
+               sandbox_server_mkdir_p(captive_printf_alloca("%s/",g_get_tmp_dir()));
                /* Set '0700' to prevent: Wrong permissions for ...
                 * by linc-1.0.1-1/src/linc-protocols.c/make_local_tmpdir()
                 */
@@ -496,7 +518,13 @@ gchar *orb_argv[]={
                NULL};
 
                        CORBA_exception_init(&ev);
-                       orb=CORBA_ORB_init(&orb_argc,orb_argv,"orbit-local-orb",&ev);
+                       /* libcaptive is single-threaded only, caller must lock it.
+                        * If thread A spawned the sandbox while currently doing its own work
+                        * and thread B calls the sandbox thread B waits on ORB_run()
+                        * while the sandbox waits for the response of thread A ORB. Deadlock.
+                        * "orbit-local-non-threaded-orb" requests thread unaware ORB.
+                        */
+                       orb=CORBA_ORB_init(&orb_argc,orb_argv,"orbit-local-non-threaded-orb",&ev);
                        if (orb==CORBA_OBJECT_NIL)
                                fatal("Cannot initialize CORBA ORB (CORBA_OBJECT_NIL): %m");
                        if (ev._major!=CORBA_NO_EXCEPTION)
@@ -574,6 +602,11 @@ gboolean fragile;
                        |G_LOG_LEVEL_DEBUG
                        ));
 
+       /* Do not do it later than chroot_setup() as it requires it.
+        * On the other hand it is SETUID-fragile this way.
+        */
+       captive_standalone_init();
+
        fatal_argv0=argv[0];
        fragile=(getuid()!=geteuid() || getuid()==0 || geteuid()==0);
 
@@ -585,14 +618,6 @@ gboolean fragile;
                chroot_setup(TRUE);
 #endif /* MAINTAINER_MODE */
 
-       /* Initialize the i18n stuff */
-       setlocale(LC_ALL,"");
-       bindtextdomain(PACKAGE,LOCALEDIR);
-       textdomain(PACKAGE);
-
-       /* Initialize GObject subsystem of GLib. */
-       g_type_init();
-
        captive_options_init(&options);
        captive_options=&options;       /* for parsing by 'CAPTIVE_POPT_INCLUDE' */