#include "../client/giochannel-blind.h" /* for captive_giochannel_blind_new() */
#include <signal.h>
#include "../storage/relastblock.h" /* for captive_storage_relastblock() */
+#include <sys/file.h> /* flock() */
#ifdef HAVE_ORBIT_LINK
void link_set_tmpdir(const char *dir);
}
}
+static void createlockdir(const gchar *dir)
+{
+gint retries;
+
+ for (retries=0;retries<10;retries++) {
+struct stat statbuf;
+int dirfd;
+
+ if (mkdir(dir,0700)) {
+ if (errno!=EEXIST)
+ g_error(_("Failed to create chroot directory \"%s\": %m"),dir);
+ unlink_nonrecursive(dir);
+ if (mkdir(dir,0700))
+ g_error(_("Failed to create chroot directory \"%s\" after attempted unlink: %m"),dir);
+ }
+ dirfd=open(dir,O_RDONLY);
+ if (dirfd==-1) {
+ if (errno!=ENOENT)
+ g_error(_("Failed to open created chroot directory \"%s\" to lock it: %m"),dir);
+ continue;
+ }
+ /* Do not use 'LOCK_NB' here as the garbage collector should release it soon. */
+ if (flock(dirfd,LOCK_EX))
+ g_error(_("Failed to lock created chroot directory \"%s\": %m"),dir);
+ if (lstat(dir,&statbuf)) {
+ if (errno!=ENOENT)
+ g_error(_("Failed to lstat(2) created chroot directory \"%s\": %m"),dir);
+ if (close(dirfd))
+ g_error(_("Failed to close created and locked chroot directory \"%s\": %m"),dir);
+ continue;
+ }
+ /* Leave 'dirfd' open to leave it LOCK_EX-ed. */
+ break;
+ }
+}
+
static gchar *sandbox_parent_read_ior
(int Vfs_IOR_fd_read,gchar **child_chroot_pid_hashkey_dirp,CaptiveVfsParentObject *captive_vfs_parent_object)
{
/* FIXME: Security: Duplicate giop_tmpdir_init() here. */
if (!sandbox_parent_own_orbit_dir) {
/* FIXME: Make 'CAPTIVE_SANDBOX_CHROOT' configurable. */
- sandbox_parent_own_orbit_dir=g_strdup_printf("%s/tmp/captive-orbit-%d",CAPTIVE_SANDBOX_CHROOT,getpid());
- if (mkdir(sandbox_parent_own_orbit_dir,0700)) {
- g_assert(errno==EEXIST);
- sandbox_parent_own_orbit_dir_cleanup_init();
- unlink_nonrecursive(sandbox_parent_own_orbit_dir);
- if (mkdir(sandbox_parent_own_orbit_dir,0700))
- g_assert_not_reached();
- }
+ /* Use also geteuid() marker here as could not remove the directory
+ * of some other user otherwise.
+ */
+ sandbox_parent_own_orbit_dir=g_strdup_printf("%s/tmp/captive-orbit-%d-%d",CAPTIVE_SANDBOX_CHROOT,getpid(),geteuid());
sandbox_parent_own_orbit_dir_cleanup_init();
+ createlockdir(sandbox_parent_own_orbit_dir);
#ifdef HAVE_ORBIT_LINK
link_set_tmpdir(sandbox_parent_own_orbit_dir);
#else
g_return_val_if_reached(FALSE);
case 0: { /* child */
+const char *sandbox_argv0;
+int execv_rc;
errint=close(Vfs_IOR_fds[0]); /* close Vfs_IOR_fd_read */
g_return_val_if_fail(errint==0,FALSE);
captive_sandbox_fd_closeup(2 /* STDERR */ +1);
- execv(CAPTIVE_VFS_OBJECT(captive_vfs_parent_object)->options.sandbox_server_argv[0],
+ sandbox_argv0=CAPTIVE_VFS_OBJECT(captive_vfs_parent_object)->options.sandbox_server_argv[0];
+ execv_rc=execv(sandbox_argv0,
/* re-const */ (char * const *)CAPTIVE_VFS_OBJECT(captive_vfs_parent_object)->options.sandbox_server_argv);
+ g_warning(_("Failed to spawn sandbox server - execv(\"%s\",...)=%d: %m"),sandbox_argv0,execv_rc);
g_return_val_if_reached(FALSE);
} /* NOTREACHED */