コード例 #1
0
ファイル: mount.c プロジェクト: yqin/singularity
int main(int argc, char **argv) {
    struct image_object image;

    singularity_config_init();

    singularity_suid_init();
    singularity_priv_init();

    singularity_registry_init();
    singularity_priv_drop();

    singularity_runtime_autofs();

    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);
    }

    if ( is_owner(CONTAINER_MOUNTDIR, 0) != 0 ) {
        singularity_message(ERROR, "Root must own container mount directory: %s\n", CONTAINER_MOUNTDIR);
        ABORT(255);
    }

    singularity_runtime_ns(SR_NS_MNT);

    singularity_image_mount(&image, CONTAINER_MOUNTDIR);

    singularity_runtime_overlayfs();

    singularity_priv_drop_perm();

    envar_set("SINGULARITY_MOUNTPOINT", CONTAINER_FINALDIR, 1);

    if ( argc > 1 ) {

        singularity_message(VERBOSE, "Running command: %s\n", argv[1]);
        singularity_message(DEBUG, "Calling exec...\n");
        execvp(argv[1], &argv[1]); // Flawfinder: ignore (Yes flawfinder, we are exec'ing)

        singularity_message(ERROR, "Exec failed: %s: %s\n", argv[1], strerror(errno));
        ABORT(255);

    } else {

        singularity_message(INFO, "%s is mounted at: %s\n\n", singularity_image_name(&image), CONTAINER_FINALDIR);
        envar_set("PS1", "Singularity> ", 1);

        execl("/bin/sh", "/bin/sh", NULL); // Flawfinder: ignore (Yes flawfinder, this is what we want, sheesh, so demanding!)

        singularity_message(ERROR, "Exec of /bin/sh failed: %s\n", strerror(errno));
        ABORT(255);
    }

    return(0);
}
コード例 #2
0
ファイル: bind.c プロジェクト: gmkurtzer/singularity
int singularity_image_bind(int argc, char ** argv) {
    uid_t uid = geteuid();
    FILE *containerimage_fp;
    char *containerimage;
    char *loop_dev;

    if ( argv[1] == NULL ) {
        fprintf(stderr, "USAGE: SINGULARITY_IMAGE=[image] %s [command...]\n", argv[0]);
        return(1);
    }

    singularity_message(VERBOSE, "Checking calling user\n");
    if ( uid != 0 ) {
        singularity_message(ERROR, "Calling user must be root\n");
        ABORT(1);
    }

    if ( ( containerimage = envar_path("SINGULARITY_IMAGE") ) == NULL ) {
        singularity_message(ERROR, "SINGULARITY_IMAGE not defined!\n");
        ABORT(255);
    }

    singularity_message(VERBOSE, "Evaluating image: %s\n", containerimage);

    singularity_message(VERBOSE, "Checking if container image exists\n");
    if ( is_file(containerimage) < 0 ) {
        singularity_message(ERROR, "Container image not found: %s\n", containerimage);
        ABORT(1);
    }

    singularity_message(VERBOSE, "Checking if container can be opened read/write\n");
    if ( ( containerimage_fp = fopen(containerimage, "r+") ) == NULL ) { // Flawfinder: ignore
        singularity_message(ERROR, "Could not open image %s: %s\n", containerimage, strerror(errno));
        ABORT(255);
    }

    singularity_priv_init();
    singularity_config_init(joinpath(SYSCONFDIR, "/singularity/singularity.conf"));
    singularity_sessiondir_init(containerimage);
    singularity_ns_mnt_unshare();

    free(containerimage);

    singularity_message(DEBUG, "Binding container to loop interface\n");
    if ( ( loop_dev = singularity_loop_bind(containerimage_fp)) == NULL ) {
        singularity_message(ERROR, "Could not bind image to loop!\n");
        ABORT(255);
    }
    fclose(containerimage_fp);

    singularity_message(VERBOSE, "Setting SINGULARITY_LOOPDEV to '%s'\n", loop_dev);
    setenv("SINGULARITY_LOOPDEV", loop_dev, 1);

    return(0);
}
コード例 #3
0
ファイル: start.c プロジェクト: yqin/singularity
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);
}
コード例 #4
0
ファイル: sexec.c プロジェクト: gmkurtzer/singularity
int main(int argc, char **argv) {
    char *image;

    // Before we do anything, check privileges and drop permission
    singularity_priv_init();
    singularity_priv_drop();

#ifdef SINGULARITY_SUID
    singularity_message(VERBOSE2, "Running SUID program workflow\n");

    singularity_message(VERBOSE2, "Checking program has appropriate permissions\n");
    if ( ( getuid() != 0 ) && ( ( is_owner("/proc/self/exe", 0) < 0 ) || ( is_suid("/proc/self/exe") < 0 ) ) ) {
        singularity_abort(255, "This program must be SUID root\n");
    }

    singularity_message(VERBOSE2, "Checking configuration file is properly owned by root\n");
    if ( is_owner(joinpath(SYSCONFDIR, "/singularity/singularity.conf"), 0 ) < 0 ) {
        singularity_abort(255, "Running in privileged mode, root must own the Singularity configuration file\n");
    }

    singularity_config_init(joinpath(SYSCONFDIR, "/singularity/singularity.conf"));

    singularity_message(VERBOSE2, "Checking that we are allowed to run as SUID\n");
    if ( singularity_config_get_bool(ALLOW_SETUID) == 0 ) {
        singularity_abort(255, "SUID mode has been disabled by the sysadmin... Aborting\n");
    }

    singularity_message(VERBOSE2, "Checking if we were requested to run as NOSUID by user\n");
    if ( envar_defined("SINGULARITY_NOSUID") == TRUE ) {
        singularity_abort(1, "NOSUID mode has been requested... Aborting\n");
    }

#else
    singularity_message(VERBOSE, "Running NON-SUID program workflow\n");

    singularity_message(DEBUG, "Checking program has appropriate permissions\n");
    if ( is_suid("/proc/self/exe") >= 0 ) {
        singularity_abort(255, "This program must **NOT** be SUID\n");
    }

    singularity_config_init(joinpath(SYSCONFDIR, "/singularity/singularity.conf"));

    if ( singularity_priv_getuid() != 0 ) {
        singularity_message(VERBOSE2, "Checking that we are allowed to run as SUID\n");
        if ( singularity_config_get_bool(ALLOW_SETUID) == 1 ) {
            singularity_message(VERBOSE2, "Checking if we were requested to run as NOSUID by user\n");
            if ( envar_defined("SINGULARITY_NOSUID") == FALSE ) {
                char sexec_suid_path[] = LIBEXECDIR "/singularity/sexec-suid";
		
		singularity_message(VERBOSE, "Checking for sexec-suid at %s\n", sexec_suid_path);

		if ( is_file(sexec_suid_path) == 0 ) {
                    if ( ( is_owner(sexec_suid_path, 0 ) == 0 ) && ( is_suid(sexec_suid_path) == 0 ) ) {
                        singularity_message(VERBOSE, "Invoking SUID sexec: %s\n", sexec_suid_path);

                        execv(sexec_suid_path, argv); // Flawfinder: ignore
                        singularity_abort(255, "Failed to execute sexec binary (%s): %s\n", sexec_suid_path, strerror(errno));
                    } else {
                        singularity_message(VERBOSE, "Not invoking SUID mode: SUID sexec permissions not properly set\n");
                    }
		}
		else {
		    singularity_message(VERBOSE, "Not invoking SUID mode: SUID sexec not installed\n");
		}
            } else {
                singularity_message(VERBOSE, "Not invoking SUID mode: NOSUID mode requested\n");
            }
        } else {
            singularity_message(VERBOSE, "Not invoking SUID mode: disallowed by the system administrator\n");
        }
    } else {
        singularity_message(VERBOSE, "Not invoking SUID mode: running as root\n");
    }

#endif /* SINGULARITY_SUID */

    if ( ( image = envar_path("SINGULARITY_IMAGE") ) == NULL ) {
        singularity_abort(255, "SINGULARITY_IMAGE not defined!\n");
    }

    singularity_action_init();
    singularity_rootfs_init(image);
    singularity_sessiondir_init(image);

    free(image);

    singularity_ns_unshare();

    singularity_rootfs_mount();

    singularity_rootfs_check();

    singularity_file();

    singularity_mount();

    singularity_rootfs_chroot();

    singularity_action_do(argc, argv);

    return(0);

}
コード例 #5
0
ファイル: singularity.c プロジェクト: DrDaveD/singularity
static int setup_container(spank_t spank)
{
    int rc;
    struct image_object image;
    char *command = NULL;

    if ((rc = setup_container_environment(spank)) != 0) { return rc; }

    /*
     * Ugg, singularity_* calls tend to call ABORT(255), which translates to
     * exit(255), all over the place.  The slurm SPANK hook API may not
     * expect such sudden death of the pending slurm task.  I've left
     * a bunch of following "return rc;" commented out, as the failure
     * conditions from singularity_* calls isn't clear to me.
     */

    // Before we do anything, check privileges and drop permission
    singularity_priv_init();
    singularity_priv_drop();

    singularity_message(VERBOSE, "Running Slurm/Singularity integration "
                        "plugin\n");

    if ((rc = singularity_config_init()) != 0) {
         return rc;
    }


    singularity_priv_init();
//TODO    singularity_suid_init(argv);

    singularity_registry_init();
    singularity_priv_userns();
    singularity_priv_drop();

    singularity_cleanupd();

    singularity_runtime_ns(SR_NS_ALL);

    singularity_sessiondir();

    image = singularity_image_init(singularity_registry_get("IMAGE")); 

    if ( singularity_registry_get("WRITABLE") == NULL ) {
        singularity_image_open(&image, O_RDONLY);
    } else {
        singularity_image_open(&image, O_RDWR);
    }  

    singularity_image_check(&image);
    singularity_image_bind(&image);
    singularity_image_mount(&image, singularity_runtime_rootfs(NULL));

    action_ready(singularity_runtime_rootfs(NULL));

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

    singularity_runtime_environment();

    singularity_priv_drop_perm();

 
    if ((rc = setup_container_cwd()) < 0) { 
       singularity_message(ERROR, "Could not obtain current directory.\n");
       return rc; 
    }

    envar_set("SINGULARITY_CONTAINER", singularity_image_name(&image), 1); // Legacy PS1 support
    envar_set("SINGULARITY_NAME", singularity_image_name(&image), 1);
    envar_set("SINGULARITY_SHELL", singularity_registry_get("SHELL"), 1);

    command = singularity_registry_get("COMMAND");
    singularity_message(LOG, "USER=%s, IMAGE='%s', COMMAND='%s'\n", singularity_priv_getuser(), singularity_image_name(&image), singularity_registry_get("COMMAND"));

    // At this point, the current process is in the runtime container environment.
    // Return control flow back to Slurm: when execv is invoked, it'll be done from
    // within the container.

    return 0;
}