Пример #1
0
int container_exec(int argc, char **argv) {
    message(DEBUG, "Called container_exec(%d, **argv)\n", argc);
    if ( argc <= 1 ) {
        message(ERROR, "Exec requires a command to run\n");
        ABORT(255);
    }

    if ( is_exec("/.exec") == 0 ) {
        argv[0] = strdup("Singularity");
        message(VERBOSE, "Found /.exec inside container, exec()'ing...\n");
        if ( execv("/.exec", argv) != 0 ) { // Flawfinder: ignore (exec* is necessary)
            message(ERROR, "Exec of /.exec failed: %s\n", strerror(errno));
            ABORT(255);
        }
    } else if ( is_exec(argv[1]) == 0 ) {
        message(VERBOSE, "Exec'ing program: %s\n", argv[1]);
        if ( execv(argv[1], &argv[1]) != 0 ) { // Flawfinder: ignore (exec* is necessary)
            message(ERROR, "execv of '%s' failed: %s\n", argv[1], strerror(errno));
            ABORT(255);
        }
    } else {
        message(VERBOSE, "Exec'ing program: %s\n", argv[1]);
        if ( execvp(argv[1], &argv[1]) != 0 ) { // Flawfinder: ignore (exec* is necessary)
            message(ERROR, "execvp of '%s' failed: %s\n", argv[1], strerror(errno));
            ABORT(255);
        }
    }

    message(ERROR, "We should not have reached the end of container_exec\n");
    return(-1);
}
Пример #2
0
int		mode_passif(t_link *link, char **av, char **env)
{
  char		**cmd;
  char		**cmd_two;

  if (av[1] == NULL)
    return (FALSE);
  if (av[2] == NULL)
    {
      my_printf("Mode_passif : ./42sh -c string\n");
      return (FALSE);
    }
  else if (my_strcmp(av[1], "-c") == 0)
    {
      cmd = edit_command(link, my_epur_str(av[2]));
      cmd_two = my_explode(my_epur_str(av[2]), ' ');
      if (cmd == NULL)
	my_printf("%s : command not found\n", av[2]);
      else if (access(cmd_two[0], X_OK) == 0 && is_exec(cmd_two[0]))
	my_printf("%s : command not found\n", av[2]);
      else
	execve(cmd[0], cmd, env);
      my_printf("%s : command not found\n", av[2]);
      return (TRUE);
    }
  my_printf("Mode_passif : ./42sh -c string\n");
  return (FALSE);
}
Пример #3
0
int		basic_exec(char **param, t_lst *lst)
{
	pid_t	pid;
	int		status;
	int		i;
	char	**env;

	i = 0;
	env = lst_to_tab(lst->next);
	if (is_exec(param) == 0)
		return (0);
	if (param[0][0] == '.' || param[0][0] == '/')
	{
		if (access(param[0], X_OK) == 0)
		{
			pid = fork();
			if (pid > 0)
				waitpid(pid, &status, 0);
			if (pid == 0)
				execve(param[0], param, env);
			return (1);
		}
	}
	return (0);
}
Пример #4
0
int singularity_rootfs_check(void) {

    singularity_message(DEBUG, "Checking if container has /bin/sh...\n");
    if ( ( is_exec(joinpath(joinpath(mount_point, OVERLAY_FINAL), "/bin/sh")) < 0 ) && ( is_link(joinpath(joinpath(mount_point, OVERLAY_FINAL), "/bin/sh")) < 0 ) ) {
        singularity_message(ERROR, "Container does not have a valid /bin/sh\n");
        ABORT(255);
    }

    return(0);
}
Пример #5
0
void action_test_do(int argc, char **argv) {
    singularity_message(VERBOSE, "Exec'ing /.test\n");

    if ( is_exec("/.test") == 0 ) {
        if ( execl("/bin/sh", "test:", "-e", "-x", "/.test", NULL) < 0 ) { // Flawfinder: ignore
            singularity_message(ERROR, "Failed to execv() /.test: %s\n", strerror(errno));
        }
    } else {
        singularity_message(INFO, "No test code provided in this container\n");
        exit(0);
    }

    singularity_message(ERROR, "We should never get here... Grrrrrr!\n");
    ABORT(255);
}
Пример #6
0
int container_run(int argc, char **argv) {
    message(DEBUG, "Called container_run(%d, **argv)\n", argc);
    if ( is_exec("/.run") == 0 ) {
        argv[0] = strdup("/.run");
        message(VERBOSE, "Found /.run inside container, exec()'ing...\n");
        if ( execv("/.run", argv) != 0 ) { // Flawfinder: ignore (exec* is necessary)
            message(ERROR, "Exec of /.run failed: %s\n", strerror(errno));
            ABORT(255);
        }
    } else if ( is_exec("/singularity") == 0 ) {
        argv[0] = strdup("/singularity");
        message(VERBOSE, "Found /singularity inside container, exec()'ing...\n");
        if ( execv("/singularity", argv) != 0 ) { // Flawfinder: ignore (exec* is necessary)
            message(ERROR, "Exec of /singularity failed: %s\n", strerror(errno));
            ABORT(255);
        }
    } else {
        message(WARNING, "No Singularity runscript found, launching 'shell'\n");
        container_shell(argc, argv);
    }

    message(ERROR, "We should not have reached the end of container_run()\n");
    return(-1);
}
Пример #7
0
int container_shell(int argc, char **argv) {
    message(DEBUG, "Called container_shell(%d, **argv)\n", argc);

    if ( is_exec("/.shell") == 0 ) {
        argv[0] = strdup("Singularity");
        message(VERBOSE, "Exec()'ing /.shell\n");
        if ( execv("/.shell", argv) != 0 ) { // Flawfinder: ignore (exec* is necessary)
            message(ERROR, "Exec of /.shell failed: %s\n", strerror(errno));
        }
    } else {
        argv[0] = strdup("/bin/sh");
        message(VERBOSE, "Exec()'ing /bin/sh...\n");
        if ( execv("/bin/sh", argv) != 0 ) { // Flawfinder: ignore (exec* is necessary)
            message(ERROR, "Exec of /bin/sh failed: %s\n", strerror(errno));
        }
    }

    message(ERROR, "We should not have reached the end of container_shell()\n");
    return(-1);
}
Пример #8
0
int main(int argc, char **argv) {
    int i, cleanupd_fd;
    struct tempfile *stdout_log, *stderr_log, *singularity_debug;
    struct image_object image;
    pid_t child;
    siginfo_t siginfo;
    struct stat filestat;

    singularity_config_init();

    singularity_suid_init();
    singularity_priv_init();

    singularity_registry_init();
    singularity_priv_drop();

    singularity_runtime_autofs();

    singularity_registry_set("UNSHARE_PID", "1");
    singularity_registry_set("UNSHARE_IPC", "1");

    if ( singularity_registry_get("INSTANCE_BOOT") != NULL ) {
        singularity_registry_set("CONTAIN", "1");
    }

    singularity_cleanupd();

    if ( singularity_registry_get("WRITABLE") != NULL ) {
        singularity_message(VERBOSE3, "Instantiating writable container image object\n");
        image = singularity_image_init(singularity_registry_get("IMAGE"), O_RDWR);
    } else {
        singularity_message(VERBOSE3, "Instantiating read only container image object\n");
        image = singularity_image_init(singularity_registry_get("IMAGE"), O_RDONLY);
    }

    singularity_runtime_ns(SR_NS_ALL);

    singularity_sessiondir();

    singularity_image_mount(&image, CONTAINER_MOUNTDIR);

    action_ready();

    singularity_runtime_overlayfs();
    singularity_runtime_mounts();
    singularity_runtime_files();

    /* After this point, we are running as PID 1 inside PID NS */
    singularity_message(DEBUG, "Preparing sinit daemon\n");
    singularity_registry_set("ROOTFS", CONTAINER_FINALDIR);
    singularity_daemon_init();

    singularity_message(DEBUG, "Entering chroot environment\n");

    singularity_runtime_enter();
    singularity_priv_drop_perm();

    if ( envclean() != 0 ) {
        singularity_message(ERROR, "Failed sanitizing the environment\n");
        ABORT(255);
    }

    if ( chdir("/") < 0 ) {
        singularity_message(ERROR, "Can't change directory to /\n");
    }
    setsid();
    umask(0);

    cleanupd_fd = atoi(singularity_registry_get("CLEANUPD_FD"));

    if ( singularity_registry_get("INSTANCE_BOOT") != NULL ) {
        int pipes[2];

        if ( pipe2(pipes, O_CLOEXEC) < 0 ) {
            singularity_signal_go_ahead(255);
            return(0);
        }

        if ( fork() == 0 ) {
            /* wait a broken pipe which mean exec success */
            struct pollfd pfd;
            pfd.fd = pipes[0];
            pfd.events = POLLRDHUP;

            close(pipes[1]);
            while( poll(&pfd, 1, 1000) >= 0 ) {
                if ( pfd.revents == POLLHUP ) break;
            }
            singularity_signal_go_ahead(0);

            /* wait /sbin/init install signal handler */
            usleep(20000);
            return(0);
        } else {
            close(pipes[0]);
            if ( is_exec("/sbin/init") == 0 ) {
                argv[1] = NULL;
                if ( execv("/sbin/init", argv) < 0 ) { // Flawfinder: ignore
                    singularity_message(ERROR, "Exec of /sbin/init failed\n");
                }
            } else {
                singularity_message(ERROR, "/sbin/init not present in container\n");
            }
            /* send exit status and implicitly kill polling child */
            singularity_signal_go_ahead(255);
            return(0);
        }
    }

    /* set program name */
    if ( prctl(PR_SET_NAME, "sinit", 0, 0, 0) < 0 ) {
        singularity_message(ERROR, "Failed to set program name\n");
        ABORT(255);
    }

    singularity_install_signal_handler();

    /* Close all open fd's that may be present besides daemon info file fd */
    singularity_message(DEBUG, "Closing open fd's\n");
    for( i = sysconf(_SC_OPEN_MAX); i > 2; i-- ) {        
        if ( i != cleanupd_fd ) {
            if ( fstat(i, &filestat) == 0 ) {
                if ( S_ISFIFO(filestat.st_mode) != 0 ) {
                    continue;
                }
            }
            close(i);
        }
    }

    singularity_debug = make_logfile("singularity-debug");
    stdout_log = make_logfile("stdout");
    stderr_log = make_logfile("stderr");
    
    for( i = 0; i <= 2; i++ ) {
        close(i);
    }

    if ( chdir("/") < 0 ) {
        singularity_message(ERROR, "Can't change directory to /\n");
    }
    setsid();
    umask(0);

    /* set program name */
    if ( prctl(PR_SET_NAME, "sinit", 0, 0, 0) < 0 ) {
        singularity_message(ERROR, "Failed to set program name\n");
        ABORT(255);
    }

    child = fork();
    
    if ( child == 0 ) {
        /* Make standard output and standard error files to log stdout & stderr into */
        if ( stdout_log != NULL ) {
            if ( -1 == dup2(stdout_log->fd, 1) ) {
                singularity_message(ERROR, "Unable to dup2(): %s\n", strerror(errno));
                ABORT(255);
            }
        }

        if ( stderr_log != NULL ) {
            if ( -1 == dup2(stderr_log->fd, 2) ) {
                singularity_message(ERROR, "Unable to dup2(): %s\n", strerror(errno));
                ABORT(255);
            }
        }

        /* Unblock signals and execute startscript */
        singularity_unblock_signals();
        if ( is_exec("/.singularity.d/actions/start") == 0 ) {
            singularity_message(DEBUG, "Exec'ing /.singularity.d/actions/start\n");

            if ( execv("/.singularity.d/actions/start", argv) < 0 ) { // Flawfinder: ignore
                singularity_message(ERROR, "Failed to execv() /.singularity.d/actions/start: %s\n", strerror(errno));
                ABORT(CHILD_FAILED);
            }
        } else {
            singularity_message(VERBOSE, "Instance start script not found\n");
            kill(1, SIGCONT);
        }
    } else if ( child > 0 ) {
        if ( singularity_debug != NULL ) {
            if ( -1 == dup2(singularity_debug->fd, 2) ) {
                singularity_message(ERROR, "Unable to dup2(): %s\n", strerror(errno));
                ABORT(255);
            }
        }

        singularity_message(DEBUG, "Waiting for signals\n");
        /* send a SIGALRM if start script doesn't send SIGCONT within 1 seconds */
        alarm(1);
        while (1) {
            if ( singularity_handle_signals(&siginfo) < 0 ) {
                singularity_signal_go_ahead(255);
                break;
            }
            if ( siginfo.si_signo == SIGCHLD ) {
                singularity_message(DEBUG, "Child exited\n");
                if ( siginfo.si_pid == 2 && siginfo.si_status == CHILD_FAILED ) {
                    singularity_signal_go_ahead(CHILD_FAILED);
                    break;
                }
            } else if ( siginfo.si_signo == SIGCONT && siginfo.si_pid == 2 ) {
                /* start script correctly exec */
                singularity_signal_go_ahead(0);
                started = 1;
            } else if ( siginfo.si_signo == SIGALRM && started == 0 ) {
                /* don't receive SIGCONT, start script modified/replaced ? */
                singularity_message(ERROR, "Start script doesn't send SIGCONT\n");
                singularity_signal_go_ahead(255);
                break;
            }
        }
    } else {
        singularity_message(ERROR, "Failed to execute start script\n");
        singularity_signal_go_ahead(255);
    }
    return(0);
}
Пример #9
0
static int parse_phrase_no_colon(FILE *stream, const char *fullphrase,
				 int def_path_no)
{
#define FILENAME_LEN 1000
	char filename[FILENAME_LEN];
	const char *tmp;
	const char *phrase;
	int i;
	int len;

	D_("ppnc: fp=\"%s\", i=%d\n", fullphrase, def_path_no);
	if (!*fullphrase) {
		fputc('@', stream);
		return 0;	/* @@ => @ translation, no looping required */
	}

	/* handle some special phrases */
	for (i = 0; STATIC_OVERLAYS[i].opt; ++i) {
		if (strcmp(fullphrase, STATIC_OVERLAYS[i].opt) == 0) {
			printf("  **\t\"@%s@\" set by overlay to \"%s\".\n",
			       fullphrase, STATIC_OVERLAYS[i].value);
			fputs(STATIC_OVERLAYS[i].value, stream);
			return 0;
		}
	}

	/* if (!path) return; */
	if (!(phrase = strrchr(fullphrase, '/')))
		phrase = fullphrase;
	else
		phrase++;

	if (phrase != fullphrase) {
		/* this means fullphrase contains an / */
		if (is_exec(fullphrase)) {
			fputs(fullphrase, stream);
			
			return 0;	/* found filename in supplied
					 * Path => no looping req'd */
		}
	}

	/* compare with all overlays */
	i = 0;
	while (overlay[i].opt) {
		if (strcasecmp(fullphrase, overlay[i].opt) == 0) {
			printf("  **\t\"@%s@\" set by overlay to \"%s\".\n",
			       fullphrase, overlay[i].value);
			fputs(overlay[i].value, stream);
			return 0;
		}
		i++;
	}

	/* first, search the path */
	i = 0;
	while (path[i]) {
		memset(filename, 0, sizeof filename);
		strncpy(filename, path[i], FILENAME_LEN - 2);
		len = strlen(filename);
		if (filename[len - 1] != '/') {
			filename[len] = '/';
			filename[len + 1] = '\0';
		}
		strncat(filename, phrase, FILENAME_LEN - 1 - strlen(filename));
		if (is_exec(filename)) {
			fputs(filename, stream);
			return 0;	/* found filename in Path => no looping req'd */
		}
		i++;
	}
	/* then, search additional paths */
	i = 0;
	while (additional_paths[i]) {
		strncpy(filename, additional_paths[i], FILENAME_LEN - 1);
		strncat(filename, phrase,
			FILENAME_LEN - 1 - strlen(additional_paths[i]));
		if (is_exec(filename)) {
			fputs(filename, stream);
			return 0;	/* found filename in Path => no
					 * looping req'd */
		}
		i++;
	}
	/* here we neither found it in the path, nor in the additional paths */
	if (def_path_no == -1) {
		return 1;	/* this is from a coloned search: the first
				 * bastard wasn't found, try the next */
	}

	fprintf(stderr, "  **\tWARNING: No executable found for \"%s\", ",
		phrase);

	if (fullphrase != phrase) {
		fprintf(stderr, "  **\tusing full path \"%s\"\n", fullphrase);
		fputs(fullphrase, stream);
		/* return 0;  full path specified => no looping req'd */
	} else if (at_default_path) {
		tmp = at_default_paths[def_path_no];
		fprintf(stderr, "  **\tusing supplied default path \"%s\"\n",
			tmp);
		fputs(tmp, stream);
		if (tmp[strlen(tmp) - 1] != '/')
			fputc('/', stream);
		fputs(phrase, stream);
		if (at_default_paths[def_path_no + 1])
			return 1;	/* next default path exits, so looping
					 * is required */
		/* return 0 */
	} else {	/* at_default_path == NULL && fullphrase == phrase */

		fprintf(stderr,
			"  **\tusing builtin default path \"/usr/sbin/\"\n");
		fputs("/usr/sbin/", stream);
		fputs(phrase, stream);
		/* no default path(s) so no looping */
	}
	/* exit(1) ??? */
	return 0;

#if 0
	tmp = path;
	while (1) {
		i = 0;
		while (*tmp != ':' && *tmp != '\0' && i < FILENAME_LEN - 1)
			filename[i++] = *(tmp++);
		if (*tmp)
			tmp++;	/* skip ':' */
		if (filename[i] != '/')
			filename[i++] = '/';
		filename[i] = '\0';
		strncat(filename, phrase, FILENAME_LEN - 1 - i);

		/* TODO: check if executable */
		if (is_exec(filename)) {
			fputs(filename, stream);
			return 0;	/* found filename in Path => no
					 * looping req'd */
		}

		if (!*tmp) {
			/* here we passed all paths in PATH */
			i = 0;
			while (additional_paths[i]) {
				strncpy(filename, additional_paths[i],
					FILENAME_LEN - 1);
				strncat(filename, phrase,
					FILENAME_LEN - 1 -
					strlen(additional_paths[i]));
				if (is_exec(filename)) {
					fputs(filename, stream);
					return 0;	/* found filename in
							 * Path => no looping
							 * req'd */
				}
				i++;
			}

			if (def_path_no == -1) {
				return 1;	/* this is from a coloned
						 * search: the first bastard
						 * wasn't found, try the next
						*/
			}
			
			fprintf(stderr, "  **\tWARNING: No executable found "
				"for \"%s\", ", phrase);

			if (fullphrase != phrase) {
				fprintf(stderr,
					"  **\tusing full path \"%s\"\n",
					fullphrase);
				fputs(fullphrase, stream);
				/* return 0;  full path specified => no
				 *            looping req'd */
			} else if (at_default_path) {
				tmp = at_default_paths[def_path_no];
				fprintf(stderr, "  **\tusing supplied default"
					" path \"%s\"\n", tmp);
				fputs(tmp, stream);
				if (tmp[strlen(tmp) - 1] != '/')
					fputc('/', stream);
				fputs(phrase, stream);
				if (at_default_paths[def_path_no + 1])
					return 1;	/* next default path
							 * exits, so looping
							 * is required */
				/* return 0 */
			} else {	/* at_default_path == NULL &&
					 * fullphrase == phrase */

				fprintf(stderr, "  **\tusing builtin default "
					"path \"/usr/sbin/\"\n");
				fputs("/usr/sbin/", stream);
				fputs(phrase, stream);
				/* no default path(s) so no looping */
			}
			/* exit(1) ??? */
			return 0;
		}
	}
#endif
}
Пример #10
0
int main(int argc, char ** argv) {
    FILE *containerimage_fp;
    FILE *loop_fp;
    FILE *config_fp;
    char *containerimage;
    char *containername;
    char *containerpath;
    char *username;
    char *command;
    char *tmpdir;
    char *loop_dev_lock;
    char *loop_dev_cache;
    char *loop_dev = 0;
    char *config_path;
    char *tmp_config_string;
    char cwd[PATH_MAX];
    int cwd_fd;
    int tmpdirlock_fd;
    int containerimage_fd;
    int loop_dev_lock_fd;
    int gid_list_count;
    int retval = 0;
    uid_t uid;
    gid_t gid;
    gid_t *gid_list;
    pid_t namespace_fork_pid = 0;
    struct passwd *pw;


//****************************************************************************//
// Init
//****************************************************************************//

    signal(SIGINT, sighandler);
    signal(SIGKILL, sighandler);
    signal(SIGQUIT, sighandler);

    openlog("Singularity", LOG_CONS | LOG_NDELAY, LOG_LOCAL0);

    // Get all user/group info
    uid = getuid();
    gid = getgid();
    gid_list_count = getgroups(0, NULL);
    gid_list = (gid_t *) malloc(sizeof(gid_t) * gid_list_count);
    if ( getgroups(gid_list_count, gid_list) < 0 ) {
        fprintf(stderr, "ABORT: Could not obtain current supplementary group list: %s\n", strerror(errno));
        return(255);
    }
    pw = getpwuid(uid);

    // Check to make sure we are installed correctly
    if ( seteuid(0) < 0 ) {
        fprintf(stderr, "ABORT: Check installation, must be performed by root.\n");
        return(255);
    }

    // Lets start off as the calling UID
    if ( seteuid(uid) < 0 ) {
        fprintf(stderr, "ABORT: Could not set effective uid to %d: %s\n", uid, strerror(errno));
        return(255);
    }
    if ( setegid(gid) < 0 ) {
        fprintf(stderr, "ABORT: Could not set effective gid to %d: %s\n", gid, strerror(errno));
        return(255);
    }

    username = pw->pw_name;
    containerimage = getenv("SINGULARITY_IMAGE");
    command = getenv("SINGULARITY_COMMAND");

    unsetenv("SINGULARITY_COMMAND");
    unsetenv("SINGULARITY_EXEC");

    config_path = (char *) malloc(strlen(SYSCONFDIR) + 30);
    snprintf(config_path, strlen(SYSCONFDIR) + 30, "%s/singularity/singularity.conf", SYSCONFDIR);

    // Figure out where we start
    if ( (cwd_fd = open(".", O_RDONLY)) < 0 ) {
        fprintf(stderr, "ABORT: Could not open cwd fd (%s)!\n", strerror(errno));
        return(1);
    }
    if ( getcwd(cwd, PATH_MAX) == NULL ) {
        fprintf(stderr, "Could not obtain current directory path: %s\n", strerror(errno));
        return(1);
    }

    if ( containerimage == NULL ) {
        fprintf(stderr, "ABORT: SINGULARITY_IMAGE undefined!\n");
        return(1);
    }

    if ( is_file(containerimage) != 0 ) {
        fprintf(stderr, "ABORT: Container image path is invalid: %s\n", containerimage);
        return(1);
    }

    if ( is_file(config_path) != 0 ) {
        fprintf(stderr, "ABORT: Configuration file not found: %s\n", config_path);
        return(255);
    }

    if ( is_owner(config_path, 0) != 0 ) {
        fprintf(stderr, "ABORT: Configuration file is not owned by root: %s\n", config_path);
        return(255);
    }

    // TODO: Offer option to only run containers owned by root (so root can approve
    // containers)
    if ( uid == 0 && is_owner(containerimage, 0) < 0 ) {
        fprintf(stderr, "ABORT: Root should only run containers that root owns!\n");
        return(1);
    }

    containername = basename(strdup(containerimage));

    tmpdir = strjoin("/tmp/.singularity-", file_id(containerimage));
    loop_dev_lock = joinpath(tmpdir, "loop_dev.lock");
    loop_dev_cache = joinpath(tmpdir, "loop_dev");

    containerpath = (char *) malloc(strlen(tmpdir) + 5);
    snprintf(containerpath, strlen(tmpdir) + 5, "%s/mnt", tmpdir);

    syslog(LOG_NOTICE, "User=%s[%d], Command=%s, Container=%s, CWD=%s, Arg1=%s", username, uid, command, containerimage, cwd, argv[1]);


//****************************************************************************//
// Setup
//****************************************************************************//


    if ( ( config_fp = fopen(config_path, "r") ) == NULL ) {
        fprintf(stderr, "ERROR: Could not open config file %s: %s\n", config_path, strerror(errno));
        return(255);
    }

    if ( getenv("SINGULARITY_WRITABLE") == NULL ) {
        if ( ( containerimage_fp = fopen(containerimage, "r") ) == NULL ) {
            fprintf(stderr, "ERROR: Could not open image read only %s: %s\n", containerimage, strerror(errno));
            return(255);
        }
        containerimage_fd = fileno(containerimage_fp);
        if ( flock(containerimage_fd, LOCK_SH | LOCK_NB) < 0 ) {
            fprintf(stderr, "ABORT: Image is locked by another process\n");
            return(5);
        }
    } else {
        if ( ( containerimage_fp = fopen(containerimage, "r+") ) == NULL ) {
            fprintf(stderr, "ERROR: Could not open image read/write %s: %s\n", containerimage, strerror(errno));
            return(255);
        }
        containerimage_fd = fileno(containerimage_fp);
        if ( flock(containerimage_fd, LOCK_EX | LOCK_NB) < 0 ) {
            fprintf(stderr, "ABORT: Image is locked by another process\n");
            return(5);
        }
    }


//****************************************************************************//
// We are now running with escalated privileges until we exec
//****************************************************************************//

    if ( seteuid(0) < 0 ) {
        fprintf(stderr, "ABORT: Could not escalate effective user privileges %s\n", strerror(errno));
        return(255);
    }
    if ( setegid(0) < 0 ) {
        fprintf(stderr, "ABORT: Could not escalate effective group privileges: %s\n", strerror(errno));
        return(255);
    }

    if ( s_mkpath(tmpdir, 0755) < 0 ) {
        fprintf(stderr, "ABORT: Could not create temporary directory %s: %s\n", tmpdir, strerror(errno));
        return(255);
    }

    if ( is_owner(tmpdir, 0) < 0 ) {
        fprintf(stderr, "ABORT: Container working directory has wrong ownership: %s\n", tmpdir);
        syslog(LOG_ERR, "Container working directory has wrong ownership: %s", tmpdir);
        return(255);
    }

    tmpdirlock_fd = open(tmpdir, O_RDONLY);
    if ( tmpdirlock_fd < 0 ) {
        fprintf(stderr, "ERROR: Could not obtain file descriptor on %s: %s\n", tmpdir, strerror(errno));
        return(255);
    }

    if ( flock(tmpdirlock_fd, LOCK_SH | LOCK_NB) < 0 ) {
        fprintf(stderr, "ERROR: Could not obtain shared lock on %s: %s\n", tmpdir, strerror(errno));
        return(255);
    }

    if ( ( loop_dev_lock_fd = open(loop_dev_lock, O_CREAT | O_RDWR, 0644) ) < 0 ) {
        fprintf(stderr, "ERROR: Could not open loop_dev_lock %s: %s\n", loop_dev_lock, strerror(errno));
        return(255);
    }

    if ( s_mkpath(containerpath, 0755) < 0 ) {
        fprintf(stderr, "ABORT: Could not create directory %s: %s\n", containerpath, strerror(errno));
        return(255);
    }

    if ( is_owner(containerpath, 0) < 0 ) {
        fprintf(stderr, "ABORT: Container directory is not root owned: %s\n", containerpath);
        syslog(LOG_ERR, "Container directory has wrong ownership: %s", tmpdir);
        return(255);
    }

    if ( flock(loop_dev_lock_fd, LOCK_EX | LOCK_NB) == 0 ) {
        loop_dev = obtain_loop_dev();

        if ( ( loop_fp = fopen(loop_dev, "r+") ) < 0 ) {
            fprintf(stderr, "ERROR: Failed to open loop device %s: %s\n", loop_dev, strerror(errno));
            syslog(LOG_ERR, "Failed to open loop device %s: %s", loop_dev, strerror(errno));
            return(255);
        }

        if ( associate_loop(containerimage_fp, loop_fp, 1) < 0 ) {
            fprintf(stderr, "ERROR: Could not associate %s to loop device %s\n", containerimage, loop_dev);
            syslog(LOG_ERR, "Failed to associate %s to loop device %s", containerimage, loop_dev);
            return(255);
        }

        if ( fileput(loop_dev_cache, loop_dev) < 0 ) {
            fprintf(stderr, "ERROR: Could not write to loop_dev_cache %s: %s\n", loop_dev_cache, strerror(errno));
            return(255);
        }

        flock(loop_dev_lock_fd, LOCK_SH | LOCK_NB);

    } else {
        flock(loop_dev_lock_fd, LOCK_SH);
        if ( ( loop_dev = filecat(loop_dev_cache) ) == NULL ) {
            fprintf(stderr, "ERROR: Could not retrieve loop_dev_cache from %s\n", loop_dev_cache);
            return(255);
        }

        if ( ( loop_fp = fopen(loop_dev, "r") ) < 0 ) {
            fprintf(stderr, "ERROR: Failed to open loop device %s: %s\n", loop_dev, strerror(errno));
            return(255);
        }
    }



//****************************************************************************//
// Management fork
//****************************************************************************//

    namespace_fork_pid = fork();
    if ( namespace_fork_pid == 0 ) {

//****************************************************************************//
// Setup namespaces
//****************************************************************************//

        if ( unshare(CLONE_NEWNS) < 0 ) {
            fprintf(stderr, "ABORT: Could not virtualize mount namespace: %s\n", strerror(errno));
            return(255);
        }

        // Privatize the mount namespaces (thank you for the pointer Doug Jacobsen!)
        if ( mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0 ) {
            // I am not sure if this error needs to be caught, maybe it will fail
            // on older kernels? If so, we can fix then.
            fprintf(stderr, "ABORT: Could not make mountspaces private: %s\n", strerror(errno));
            return(255);
        }

#ifdef NS_CLONE_NEWPID
        if ( getenv("SINGULARITY_NO_NAMESPACE_PID") == NULL ) {
            unsetenv("SINGULARITY_NO_NAMESPACE_PID");
            if ( unshare(CLONE_NEWPID) < 0 ) {
                fprintf(stderr, "ABORT: Could not virtualize PID namespace: %s\n", strerror(errno));
                return(255);
            }
        }
#else
#ifdef NS_CLONE_PID
        // This is for older legacy CLONE_PID
        if ( getenv("SINGULARITY_NO_NAMESPACE_PID") == NULL ) {
            unsetenv("SINGULARITY_NO_NAMESPACE_PID");
            if ( unshare(CLONE_PID) < 0 ) {
                fprintf(stderr, "ABORT: Could not virtualize PID namespace: %s\n", strerror(errno));
                return(255);
            }
        }
#endif
#endif
#ifdef NS_CLONE_FS
        if ( getenv("SINGULARITY_NO_NAMESPACE_FS") == NULL ) {
            unsetenv("SINGULARITY_NO_NAMESPACE_FS");
            if ( unshare(CLONE_FS) < 0 ) {
                fprintf(stderr, "ABORT: Could not virtualize file system namespace: %s\n", strerror(errno));
                return(255);
            }
        }
#endif
#ifdef NS_CLONE_FILES
        if ( getenv("SINGULARITY_NO_NAMESPACE_FILES") == NULL ) {
            unsetenv("SINGULARITY_NO_NAMESPACE_FILES");
            if ( unshare(CLONE_FILES) < 0 ) {
                fprintf(stderr, "ABORT: Could not virtualize file descriptor namespace: %s\n", strerror(errno));
                return(255);
            }
        }
#endif


//****************************************************************************//
// Mount image
//****************************************************************************//

        if ( getenv("SINGULARITY_WRITABLE") == NULL ) {
            unsetenv("SINGULARITY_WRITABLE");
            if ( mount_image(loop_dev, containerpath, 0) < 0 ) {
                fprintf(stderr, "ABORT: exiting...\n");
                return(255);
            }
        } else {
            if ( mount_image(loop_dev, containerpath, 1) < 0 ) {
                fprintf(stderr, "ABORT: exiting...\n");
                return(255);
            }
        }


//****************************************************************************//
// Check image
//****************************************************************************//

        if ( is_exec(joinpath(containerpath, "/bin/sh")) < 0 ) {
            fprintf(stderr, "ERROR: Container image does not have a valid /bin/sh\n");
            return(1);
        }


//****************************************************************************//
// Bind mounts
//****************************************************************************//

        if ( getenv("SINGULARITY_CONTAIN") == NULL ) {
            unsetenv("SINGULARITY_CONTAIN");
    
            rewind(config_fp);
            while ( ( tmp_config_string = config_get_key_value(config_fp, "bind path") ) != NULL ) {
                if ( ( is_file(tmp_config_string) != 0 ) && ( is_dir(tmp_config_string) != 0 ) ) {
                    fprintf(stderr, "ERROR: Non existant bind source path: '%s'\n", tmp_config_string);
                    continue;
                }
                if ( ( is_file(joinpath(containerpath, tmp_config_string)) != 0 ) && ( is_dir(joinpath(containerpath, tmp_config_string)) != 0 ) ) {
                    fprintf(stderr, "WARNING: Non existant bind container destination path: '%s'\n", tmp_config_string);
                    continue;
                }
                if ( mount_bind(tmp_config_string, joinpath(containerpath, tmp_config_string), 0) < 0 ) {
                    fprintf(stderr, "ABORTING!\n");
                    return(255);
                }
            }


            if (is_file(joinpath(containerpath, "/etc/nsswitch.conf")) == 0 ) {
                if ( is_file(joinpath(SYSCONFDIR, "/singularity/default-nsswitch.conf")) == 0 ) {
                    if ( mount_bind(joinpath(SYSCONFDIR, "/singularity/default-nsswitch.conf"), joinpath(containerpath, "/etc/nsswitch.conf"), 0) != 0 ) {
                        fprintf(stderr, "ABORT: Could not bind /etc/nsswitch.conf\n");
                        return(255);
                    }
                } else {
                    fprintf(stderr, "WARNING: Template /etc/nsswitch.conf does not exist: %s\n", joinpath(SYSCONFDIR, "/singularity/default-nsswitch.conf"));
                }
            }

            if ( uid != 0 ) { // If we are root, no need to mess with passwd or group
                if (is_file(joinpath(containerpath, "/etc/passwd")) == 0 ) {
                    if ( is_file(joinpath(tmpdir, "/passwd")) < 0 ) {
                        if ( build_passwd(joinpath(containerpath, "/etc/passwd"), joinpath(tmpdir, "/passwd")) < 0 ) {
                            fprintf(stderr, "ABORT: Failed creating template password file\n");
                            return(255);
                        }
                    }
                    if ( mount_bind(joinpath(tmpdir, "/passwd"), joinpath(containerpath, "/etc/passwd"), 0) < 0 ) {
                        fprintf(stderr, "ABORT: Could not bind /etc/passwd\n");
                        return(255);
                    }
                }
    
                if (is_file(joinpath(containerpath, "/etc/group")) == 0 ) {
                    if ( is_file(joinpath(tmpdir, "/group")) < 0 ) {
                        if ( build_group(joinpath(containerpath, "/etc/group"), joinpath(tmpdir, "/group")) < 0 ) {
                            fprintf(stderr, "ABORT: Failed creating template group file\n");
                            return(255);
                        }
                    }
                    if ( mount_bind(joinpath(tmpdir, "/group"), joinpath(containerpath, "/etc/group"), 0) < 0 ) {
                        fprintf(stderr, "ABORT: Could not bind /etc/group\n");
                        return(255);
                    }
                }
            }
        }

//****************************************************************************//
// Fork child in new namespaces
//****************************************************************************//

        exec_fork_pid = fork();

        if ( exec_fork_pid == 0 ) {


//****************************************************************************//
// Enter the file system
//****************************************************************************//

            if ( chroot(containerpath) < 0 ) {
                fprintf(stderr, "ABORT: failed enter CONTAINERIMAGE: %s\n", containerpath);
                return(255);
            }
            if ( chdir("/") < 0 ) {
                fprintf(stderr, "ABORT: Could not chdir after chroot to /: %s\n", strerror(errno));
                return(1);
            }


//****************************************************************************//
// Setup real mounts within the container
//****************************************************************************//

            rewind(config_fp);
            if ( config_get_key_bool(config_fp, "mount proc", 1) > 0 ) {
                if ( is_dir("/proc") == 0 ) {
                    if ( mount("proc", "/proc", "proc", 0, NULL) < 0 ) {
                        fprintf(stderr, "ABORT: Could not mount /proc: %s\n", strerror(errno));
                        return(255);
                    }
                }
            }

            rewind(config_fp);
            if ( config_get_key_bool(config_fp, "mount sys", 1) > 0 ) {
                if ( is_dir("/sys") == 0 ) {
                    if ( mount("sysfs", "/sys", "sysfs", 0, NULL) < 0 ) {
                        fprintf(stderr, "ABORT: Could not mount /sys: %s\n", strerror(errno));
                        return(255);
                    }
                }
            }


//****************************************************************************//
// Drop all privileges for good
//****************************************************************************//

            if ( setgroups(gid_list_count, gid_list) < 0 ) {
                fprintf(stderr, "ABOFT: Could not reset supplementary group list: %s\n", strerror(errno));
                return(255);
            }
            if ( setregid(gid, gid) < 0 ) {
                fprintf(stderr, "ABORT: Could not dump real and effective group privileges: %s\n", strerror(errno));
                return(255);
            }
            if ( setreuid(uid, uid) < 0 ) {
                fprintf(stderr, "ABORT: Could not dump real and effective user privileges: %s\n", strerror(errno));
                return(255);
            }


//****************************************************************************//
// Setup final environment
//****************************************************************************//

            // After this, we exist only within the container... Let's make it known!
            if ( setenv("SINGULARITY_CONTAINER", "true", 0) != 0 ) {
                fprintf(stderr, "ABORT: Could not set SINGULARITY_CONTAINER to 'true'\n");
                return(1);
            }

            if ( is_dir(cwd) == 0 ) {
               if ( chdir(cwd) < 0 ) {
                    fprintf(stderr, "ABORT: Could not chdir to: %s: %s\n", cwd, strerror(errno));
                    return(1);
                }
            } else {
                if ( fchdir(cwd_fd) < 0 ) {
                    fprintf(stderr, "ABORT: Could not fchdir to cwd: %s\n", strerror(errno));
                    return(1);
                }
            }


//****************************************************************************//
// Execv to container process
//****************************************************************************//

            if ( command == NULL ) {
                fprintf(stderr, "No command specified, launching 'shell'\n");
                command = strdup("shell");
            }

            if ( strcmp(command, "run") == 0 ) {
                if ( is_exec("/singularity") == 0 ) {
                    argv[0] = strdup("/singularity");
                    if ( execv("/singularity", argv) != 0 ) {
                        fprintf(stderr, "ABORT: exec of /bin/sh failed: %s\n", strerror(errno));
                    }
                } else {
                    fprintf(stderr, "No Singularity runscript found, launching 'shell'\n");
                    command = strdup("shell");
                }
            }
            
            if ( strcmp(command, "exec") == 0 ) {
                if ( argc <= 1 ) {
                    fprintf(stderr, "ABORT: Exec requires a command to run\n");
                    return(1);
                }
                if ( execvp(argv[1], &argv[1]) != 0 ) {
                    fprintf(stderr, "ABORT: execvp of '%s' failed: %s\n", argv[1], strerror(errno));
                    return(1);
                }
            }
            
            if ( strcmp(command, "shell") == 0 ) {
                char *prompt;

                prompt = (char *) malloc(strlen(containername) + 16);
                snprintf(prompt, strlen(containerimage) + 16, "Singularity/%s> ", containername);
                setenv("PS1", prompt, 1);

                if ( is_exec("/bin/bash") == 0 ) {
                    char *args[argc+2];
                    int i;

                    args[0] = strdup("/bin/bash");
                    args[1] = strdup("--norc");
                    args[2] = strdup("--noprofile");
                    for(i=1; i<=argc; i++) {
                        args[i+2] = argv[i];
                    }

                    if ( execv("/bin/bash", args) != 0 ) {
                        fprintf(stderr, "ABORT: exec of /bin/bash failed: %s\n", strerror(errno));
                    }
                } else {
                    argv[0] = strdup("/bin/sh");
                    if ( execv("/bin/sh", argv) != 0 ) {
                        fprintf(stderr, "ABORT: exec of /bin/sh failed: %s\n", strerror(errno));
                    }
                }
            }

            // If we get here... we fail on bad command
            fprintf(stderr, "ABORT: Unrecognized Singularity command: %s\n", command);
            return(1);


//****************************************************************************//
// Outer child waits for inner child
//****************************************************************************//

        } else if ( exec_fork_pid > 0 ) {
            int tmpstatus;

            strncpy(argv[0], "Singularity: exec", strlen(argv[0]));

            if ( seteuid(uid) < 0 ) {
                fprintf(stderr, "ABORT: Could not set effective user privileges to %d: %s\n", uid, strerror(errno));
                return(255);
            }

            waitpid(exec_fork_pid, &tmpstatus, 0);
            retval = WEXITSTATUS(tmpstatus);
        } else {
            fprintf(stderr, "ABORT: Could not fork namespace process: %s\n", strerror(errno));
            return(255);
        }
        return(retval);

    } else if ( namespace_fork_pid > 0 ) {
        int tmpstatus;

        strncpy(argv[0], "Singularity: namespace", strlen(argv[0]));

        if ( seteuid(uid) < 0 ) {
            fprintf(stderr, "ABORT: Could not set effective user privileges to %d: %s\n", uid, strerror(errno));
            return(255);
        }

        waitpid(namespace_fork_pid, &tmpstatus, 0);
        retval = WEXITSTATUS(tmpstatus);
    } else {
        fprintf(stderr, "ABORT: Could not fork management process: %s\n", strerror(errno));
        return(255);
    }


//****************************************************************************//
// Final wrap up before exiting
//****************************************************************************//


    if ( close(cwd_fd) < 0 ) {
        fprintf(stderr, "ERROR: Could not close cwd_fd: %s\n", strerror(errno));
        retval++;
    }

    if ( flock(tmpdirlock_fd, LOCK_EX | LOCK_NB) == 0 ) {
        close(tmpdirlock_fd);
        if ( seteuid(0) < 0 ) {
            fprintf(stderr, "ABORT: Could not re-escalate effective user privileges: %s\n", strerror(errno));
            return(255);
        }

        if ( s_rmdir(tmpdir) < 0 ) {
            fprintf(stderr, "WARNING: Could not remove all files in %s: %s\n", tmpdir, strerror(errno));
        }
    
        // Dissociate loops from here Just in case autoflush didn't work.
        (void)disassociate_loop(loop_fp);

        if ( seteuid(uid) < 0 ) {
            fprintf(stderr, "ABORT: Could not drop effective user privileges: %s\n", strerror(errno));
            return(255);
        }

    } else {
//        printf("Not removing tmpdir, lock still\n");
    }

    close(containerimage_fd);
    close(tmpdirlock_fd);

    free(loop_dev_lock);
    free(containerpath);
    free(tmpdir);
    closelog();

    return(retval);
}