Exemple #1
0
int singularity_ns_ipc_unshare(void) {

    singularity_config_rewind();
    if ( singularity_config_get_bool("allow ipc ns", 1) <= 0 ) {
        singularity_message(VERBOSE2, "Not virtualizing IPC namespace by configuration\n");
        return(0);
    }

    if ( envar_defined("SINGULARITY_UNSHARE_IPC") == FALSE ) {
        singularity_message(VERBOSE2, "Not virtualizing IPC namespace on user request\n");
        return(0);
    }

#ifdef NS_CLONE_NEWIPC
    singularity_message(DEBUG, "Using IPC namespace: CLONE_NEWIPC\n");
    singularity_priv_escalate();
    singularity_message(DEBUG, "Virtualizing IPC namespace\n");
    if ( unshare(CLONE_NEWIPC) < 0 ) {
        singularity_message(ERROR, "Could not virtualize IPC namespace: %s\n", strerror(errno));
        ABORT(255);
    }
    singularity_priv_drop();
    enabled = 0;

#else
    singularity_message(WARNING, "Skipping IPC namespace creation, support not available on host\n");
    return(0);
#endif

    return(0);
}
Exemple #2
0
int singularity_file_resolvconf(void) {
    char *file = "/etc/resolv.conf";

    singularity_message(DEBUG, "Checking configuration option\n");
    if ( singularity_config_get_bool(CONFIG_RESOLV_CONF) <= 0 ) {
        singularity_message(VERBOSE, "Skipping bind of the host's %s\n", file);
        return(0);
    }

    container_file_bind(file, file);

    return(0);
}
Exemple #3
0
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);

}
Exemple #4
0
void singularity_mount_scratch(void) {
    char *container_dir = singularity_rootfs_dir();
    char *scratchdir_path;
    char *tmpdir_path;
    char *sourcedir_path;
    int r;

    singularity_message(DEBUG, "Getting SINGULARITY_SCRATCHDIR from environment\n");
    if ( ( scratchdir_path = envar_path("SINGULARITY_SCRATCHDIR") ) == NULL ) {
        singularity_message(DEBUG, "Not mounting scratch directory: Not requested\n");
        return;
    }

    singularity_message(DEBUG, "Checking configuration file for 'user bind control'\n");
    if ( singularity_config_get_bool(USER_BIND_CONTROL) <= 0 ) {
        singularity_message(VERBOSE, "Not mounting scratch: user bind control is disabled by system administrator\n");
        return;
    }

#ifndef SINGULARITY_NO_NEW_PRIVS
        singularity_message(WARNING, "Not mounting scratch: host does not support PR_SET_NO_NEW_PRIVS\n");
        return;
#endif  

    singularity_message(DEBUG, "Checking if overlay is enabled\n");
    int overlayfs_enabled = singularity_rootfs_overlay_enabled() > 0;
    if ( !overlayfs_enabled ) {
        singularity_message(VERBOSE, "Overlay is not enabled: cannot make directories not preexisting in container scratch.\n");
    }

    singularity_message(DEBUG, "Checking SINGULARITY_WORKDIR from environment\n");
    if ( ( tmpdir_path = envar_path("SINGULARITY_WORKDIR") ) == NULL ) {
        if ( ( tmpdir_path = singularity_sessiondir_get() ) == NULL ) {
            singularity_message(ERROR, "Could not identify a suitable temporary directory for scratch\n");
            return;
        }
    }

    sourcedir_path = joinpath(tmpdir_path, "/scratch");

    free(tmpdir_path);

    char *outside_token = NULL;
    char *current = strtok_r(strdup(scratchdir_path), ",", &outside_token);

    free(scratchdir_path);

    while ( current != NULL ) {

        char *full_sourcedir_path = joinpath(sourcedir_path, basename(strdup(current)));

        if ( s_mkpath(full_sourcedir_path, 0750) < 0 ) {
             singularity_message(ERROR, "Could not create scratch working directory %s: %s\n", full_sourcedir_path, strerror(errno));
             ABORT(255);
         }

        if (overlayfs_enabled) {
            singularity_priv_escalate();
            singularity_message(DEBUG, "Creating scratch directory inside container\n");
            r = s_mkpath(joinpath(container_dir, current), 0755);
            singularity_priv_drop();
            if ( r < 0 ) {
                singularity_message(VERBOSE, "Skipping scratch directory mount, could not create dir inside container %s: %s\n", current, strerror(errno));
                return;
            }
        }

        singularity_priv_escalate();
        singularity_message(VERBOSE, "Binding '%s' to '%s/%s'\n", full_sourcedir_path, container_dir, current);
        r = mount(full_sourcedir_path, joinpath(container_dir, current), NULL, MS_BIND|MS_NOSUID|MS_REC, NULL);
        if ( singularity_priv_userns_enabled() != 1 ) {
            r += mount(NULL, joinpath(container_dir, current), NULL, MS_BIND|MS_NOSUID|MS_REC|MS_REMOUNT, NULL);
        }
        singularity_priv_drop();
        if ( r < 0 ) {
            singularity_message(WARNING, "Could not bind scratch directory into container %s: %s\n", full_sourcedir_path, strerror(errno));
            ABORT(255);
        }

        current = strtok_r(NULL, ",", &outside_token);
        // Ignore empty directories.
        while (current && !strlength(current, 1024)) {current = strtok_r(NULL, ",", &outside_token);}
    }
    return;
}
Exemple #5
0
int _singularity_runtime_mount_tmp(void) {
    char *container_dir = singularity_runtime_rootfs(NULL);
    char *tmp_source;
    char *vartmp_source;

    if ( singularity_config_get_bool(MOUNT_TMP) <= 0 ) {
        singularity_message(VERBOSE, "Skipping tmp dir mounting (per config)\n");
        return(0);
    }

    if ( singularity_registry_get("CONTAIN") == NULL ) {
        tmp_source = strdup("/tmp");
        vartmp_source = strdup("/var/tmp");
    } else {
        char *tmpdirpath;
        if ( ( tmpdirpath = singularity_registry_get("WORKDIR") ) != NULL ) {
            if ( singularity_config_get_bool(USER_BIND_CONTROL) <= 0 ) {
                singularity_message(ERROR, "User bind control is disabled by system administrator\n");
                ABORT(5);
            }
            tmp_source = joinpath(tmpdirpath, "/tmp");
            vartmp_source = joinpath(tmpdirpath, "/var_tmp");
        } else {
            char *sessiondir = singularity_registry_get("SESSIONDIR");
            tmp_source = joinpath(sessiondir, "/tmp");
            vartmp_source = joinpath(sessiondir, "/var_tmp");
        }
        free(tmpdirpath);
    }

    if ( check_mounted("/tmp") < 0 ) {
        if ( s_mkpath(tmp_source, 0755) < 0 ) {
            singularity_message(ERROR, "Could not create source /tmp directory %s: %s\n", tmp_source, strerror(errno));
            ABORT(255);
        }
        if ( is_dir(tmp_source) == 0 ) {
            if ( is_dir(joinpath(container_dir, "/tmp")) == 0 ) {
                singularity_priv_escalate();
                singularity_message(VERBOSE, "Mounting directory: /tmp\n");
                if ( mount(tmp_source, joinpath(container_dir, "/tmp"), NULL, MS_BIND|MS_NOSUID|MS_REC, NULL) < 0 ) {
                    singularity_message(ERROR, "Failed to mount %s -> /tmp: %s\n", tmp_source, strerror(errno));
                    ABORT(255);
                }
                if ( singularity_priv_userns_enabled() != 1 ) {
                    if ( mount(NULL, joinpath(container_dir, "/tmp"), NULL, MS_BIND|MS_NOSUID|MS_REC|MS_REMOUNT, NULL) < 0 ) {
                        singularity_message(ERROR, "Failed to remount /tmp: %s\n", strerror(errno));
                        ABORT(255);
                    }
                }
                singularity_priv_drop();
            } else {
                singularity_message(VERBOSE, "Could not mount container's /tmp directory: does not exist\n");
            }
        } else {
            singularity_message(VERBOSE, "Could not mount host's /tmp directory (%s): does not exist\n", tmp_source);
        }
    } else {
        singularity_message(VERBOSE, "Not mounting '/tmp', already mounted\n");
    }

    if ( check_mounted("/var/tmp") < 0 ) {
        if ( s_mkpath(vartmp_source, 0755) < 0 ) {
            singularity_message(ERROR, "Could not create source /var/tmp directory %s: %s\n", vartmp_source, strerror(errno));
            ABORT(255);
        }
        if ( is_dir(vartmp_source) == 0 ) {
            if ( is_dir(joinpath(container_dir, "/var/tmp")) == 0 ) {
                singularity_priv_escalate();
                singularity_message(VERBOSE, "Mounting directory: /var/tmp\n");
                if ( mount(vartmp_source, joinpath(container_dir, "/var/tmp"), NULL, MS_BIND|MS_NOSUID|MS_REC, NULL) < 0 ) {
                    singularity_message(ERROR, "Failed to mount %s -> /var/tmp: %s\n", vartmp_source, strerror(errno));
                    ABORT(255);
                }
                if ( singularity_priv_userns_enabled() != 1 ) {
                    if ( mount(NULL, joinpath(container_dir, "/var/tmp"), NULL, MS_BIND|MS_NOSUID|MS_REC|MS_REMOUNT, NULL) < 0 ) {
                        singularity_message(ERROR, "Failed to remount /var/tmp: %s\n", strerror(errno));
                        ABORT(255);
                    }
                }
                singularity_priv_drop();
            } else {
                singularity_message(VERBOSE, "Could not mount container's /var/tmp directory: does not exist\n");
            }
        } else {
            singularity_message(VERBOSE, "Could not mount host's /var/tmp directory (%s): does not exist\n", vartmp_source);
        }
    } else {
        singularity_message(VERBOSE, "Not mounting '/var/tmp', already mounted\n");
    }

    free(tmp_source);
    free(vartmp_source);

    return(0);
}
Exemple #6
0
int singularity_rootfs_mount(void) {
    char *rootfs_source = joinpath(mount_point, ROOTFS_SOURCE);
    char *overlay_mount = joinpath(mount_point, OVERLAY_MOUNT);
    char *overlay_upper = joinpath(mount_point, OVERLAY_UPPER);
    char *overlay_work  = joinpath(mount_point, OVERLAY_WORK);
    char *overlay_final = joinpath(mount_point, OVERLAY_FINAL);

    singularity_message(DEBUG, "Checking 'container dir' mount location: %s\n", mount_point);
    if ( is_dir(mount_point) < 0 ) {
        singularity_priv_escalate();
        singularity_message(VERBOSE, "Creating container dir: %s\n", mount_point);
        if ( s_mkpath(mount_point, 0755) < 0 ) {
            singularity_message(ERROR, "Could not create directory: %s\n", mount_point);
            ABORT(255);
        }
        singularity_priv_drop();
    }

    singularity_message(DEBUG, "Checking for rootfs_source directory: %s\n", rootfs_source);
    if ( is_dir(rootfs_source) < 0 ) {
        singularity_priv_escalate();
        singularity_message(VERBOSE, "Creating container destination dir: %s\n", rootfs_source);
        if ( s_mkpath(rootfs_source, 0755) < 0 ) {
            singularity_message(ERROR, "Could not create directory: %s\n", rootfs_source);
            ABORT(255);
        }
        singularity_priv_drop();
    }

    singularity_message(DEBUG, "Checking for overlay_mount directory: %s\n", overlay_mount);
    if ( is_dir(overlay_mount) < 0 ) {
        singularity_priv_escalate();
        singularity_message(VERBOSE, "Creating container mount dir: %s\n", overlay_mount);
        if ( s_mkpath(overlay_mount, 0755) < 0 ) {
            singularity_message(ERROR, "Could not create directory: %s\n", overlay_mount);
            ABORT(255);
        }
        singularity_priv_drop();
    }

    singularity_message(DEBUG, "Checking for overlay_final directory: %s\n", overlay_final);
    if ( is_dir(overlay_final) < 0 ) {
        singularity_priv_escalate();
        singularity_message(VERBOSE, "Creating overlay final dir: %s\n", overlay_final);
        if ( s_mkpath(overlay_final, 0755) < 0 ) {
            singularity_message(ERROR, "Could not create directory: %s\n", overlay_final);
            ABORT(255);
        }
        singularity_priv_drop();
    }

    if ( module == ROOTFS_IMAGE ) {
        if ( rootfs_image_mount() < 0 ) {
            singularity_message(ERROR, "Failed mounting image, aborting...\n");
            ABORT(255);
        }
    } else if ( module == ROOTFS_DIR ) {
        if ( rootfs_dir_mount() < 0 ) {
            singularity_message(ERROR, "Failed mounting directory, aborting...\n");
            ABORT(255);
        }
    } else if ( module == ROOTFS_SQUASHFS ) {
        if ( rootfs_squashfs_mount() < 0 ) {
            singularity_message(ERROR, "Failed mounting SquashFS, aborting...\n");
            ABORT(255);
        }
    } else {
        singularity_message(ERROR, "Internal error, no rootfs type defined\n");
        ABORT(255);
    }

    singularity_message(DEBUG, "OverlayFS enabled by host build\n");
    if ( singularity_config_get_bool(ENABLE_OVERLAY) <= 0 ) {
        singularity_message(VERBOSE3, "Not enabling overlayFS via configuration\n");
    } else if ( envar_defined("SINGULARITY_DISABLE_OVERLAYFS") == TRUE ) {
        singularity_message(VERBOSE3, "Not enabling overlayFS via environment\n");
    } else if ( envar_defined("SINGULARITY_WRITABLE") == TRUE ) {
        singularity_message(VERBOSE3, "Not enabling overlayFS, image mounted writablable\n");
    } else {
#ifdef SINGULARITY_OVERLAYFS
        int overlay_options_len = strlength(rootfs_source, PATH_MAX) + strlength(overlay_upper, PATH_MAX) + strlength(overlay_work, PATH_MAX) + 50;
        char *overlay_options = (char *) malloc(overlay_options_len);
        snprintf(overlay_options, overlay_options_len, "lowerdir=%s,upperdir=%s,workdir=%s", rootfs_source, overlay_upper, overlay_work); // Flawfinder: ignore

        singularity_priv_escalate();
        singularity_message(DEBUG, "Mounting overlay tmpfs: %s\n", overlay_mount);
        if ( mount("tmpfs", overlay_mount, "tmpfs", MS_NOSUID, "size=1m") < 0 ){
            singularity_message(ERROR, "Failed to mount overlay tmpfs %s: %s\n", overlay_mount, strerror(errno));
            ABORT(255);
        }

        singularity_message(DEBUG, "Creating upper overlay directory: %s\n", overlay_upper);
        if ( s_mkpath(overlay_upper, 0755) < 0 ) {
            singularity_message(ERROR, "Failed creating upper overlay directory %s: %s\n", overlay_upper, strerror(errno));
            ABORT(255);
        }

        singularity_message(DEBUG, "Creating overlay work directory: %s\n", overlay_work);
        if ( s_mkpath(overlay_work, 0755) < 0 ) {
            singularity_message(ERROR, "Failed creating overlay work directory %s: %s\n", overlay_work, strerror(errno));
            ABORT(255);
        }

        singularity_message(VERBOSE, "Mounting overlay with options: %s\n", overlay_options);
        if ( mount("overlay", overlay_final, "overlay", MS_NOSUID, overlay_options) < 0 ){
            singularity_message(ERROR, "Could not create overlay: %s\n", strerror(errno));
            ABORT(255); 
        }
        free(overlay_options);
        singularity_priv_drop();

        overlay_enabled = 1;
#else /* SINGULARITY_OVERLAYFS */
        singularity_message(WARNING, "OverlayFS not supported by host build\n");
#endif /* SINGULARITY_OVERLAYFS */
    }

    if ( overlay_enabled != 1 ) {
        singularity_priv_escalate();
        singularity_message(VERBOSE3, "Binding the ROOTFS_SOURCE to OVERLAY_FINAL (%s->%s)\n", joinpath(mount_point, ROOTFS_SOURCE), joinpath(mount_point, OVERLAY_FINAL));
        if ( mount(joinpath(mount_point, ROOTFS_SOURCE), joinpath(mount_point, OVERLAY_FINAL), NULL, MS_BIND|MS_NOSUID|MS_REC, NULL) < 0 ) {
            singularity_message(ERROR, "There was an error binding the path %s: %s\n", joinpath(mount_point, ROOTFS_SOURCE), strerror(errno));
            ABORT(255);
        }
        singularity_priv_drop();
    }

    return(0);
}
Exemple #7
0
int singularity_mount_tmp(void) {
    char *container_dir = singularity_rootfs_dir();
    char *tmp_source;
    char *vartmp_source;
    char *tmpdirpath;

    singularity_config_rewind();
    if ( singularity_config_get_bool("mount tmp", 1) <= 0 ) {
        singularity_message(VERBOSE, "Skipping tmp dir mounting (per config)\n");
        return(0);
    }

    if ( ( tmpdirpath = getenv("SINGULARITY_WORKDIR") ) != NULL ) { // Flawfinder: ignore
        singularity_config_rewind();
        if ( singularity_config_get_bool("user bind control", 1) <= 0 ) {
            singularity_message(ERROR, "User bind control is disabled by system administrator\n");
            ABORT(5);
        }
        tmp_source = joinpath(tmpdirpath, "/tmp");
        vartmp_source = joinpath(tmpdirpath, "/var_tmp");
    } else if ( getenv("SINGULARITY_CONTAIN") != NULL ) { // Flawfinder: ignore
        char *sessiondir = singularity_sessiondir_get();
        tmp_source = joinpath(sessiondir, "/tmp");
        vartmp_source = joinpath(sessiondir, "/var_tmp");
    } else {
        tmp_source = strdup("/tmp");
        vartmp_source = strdup("/var/tmp");
    }

    if ( s_mkpath(tmp_source, 0755) < 0 ) {
        singularity_message(ERROR, "Could not create tmp directory %s: %s\n", tmp_source, strerror(errno));
        ABORT(255);
    }
    if ( s_mkpath(vartmp_source, 0755) < 0 ) {
        singularity_message(ERROR, "Could not create vartmp directory %s: %s\n", vartmp_source, strerror(errno));
        ABORT(255);
    }

    if ( is_dir(tmp_source) == 0 ) {
        if ( is_dir(joinpath(container_dir, "/tmp")) == 0 ) {
            singularity_priv_escalate();
            singularity_message(VERBOSE, "Mounting directory: /tmp\n");
            if ( mount(tmp_source, joinpath(container_dir, "/tmp"), NULL, MS_BIND|MS_NOSUID|MS_REC, NULL) < 0 ) {
                singularity_message(ERROR, "Failed to mount %s -> /tmp: %s\n", tmp_source, strerror(errno));
                ABORT(255);
            }
            singularity_priv_drop();
        } else {
            singularity_message(VERBOSE, "Could not mount container's /tmp directory: does not exist\n");
        }
    } else {
        singularity_message(VERBOSE, "Could not mount host's /tmp directory (%s): does not exist\n", tmp_source);
    }

    if ( is_dir(vartmp_source) == 0 ) {
        if ( is_dir(joinpath(container_dir, "/var/tmp")) == 0 ) {
            singularity_priv_escalate();
            singularity_message(VERBOSE, "Mounting directory: /var/tmp\n");
            if ( mount(vartmp_source, joinpath(container_dir, "/var/tmp"), NULL, MS_BIND|MS_NOSUID|MS_REC, NULL) < 0 ) {
                singularity_message(ERROR, "Failed to mount %s -> /var/tmp: %s\n", vartmp_source, strerror(errno));
                ABORT(255);
            }
            singularity_priv_drop();
        } else {
            singularity_message(VERBOSE, "Could not mount container's /var/tmp directory: does not exist\n");
        }
    } else {
        singularity_message(VERBOSE, "Could not mount host's /var/tmp directory (%s): does not exist\n", vartmp_source);
    }

    free(tmp_source);
    free(vartmp_source);

    return(0);
}
Exemple #8
0
int _singularity_runtime_files_passwd(void) {
    FILE *file_fp;
    char *source_file;
    char *tmp_file;
    char *homedir = singularity_priv_home();
    uid_t uid = singularity_priv_getuid();
    struct passwd *pwent = getpwuid(uid);
    char *containerdir = CONTAINER_FINALDIR;
    char *tmpdir = singularity_registry_get("SESSIONDIR");

    singularity_message(DEBUG, "Called singularity_file_passwd_create()\n");

    if ( uid == 0 ) {
        singularity_message(VERBOSE, "Not updating passwd file, running as root!\n");
        return(0);
    }

    if ( containerdir == NULL ) {
        singularity_message(ERROR, "Failed to obtain container directory\n");
        ABORT(255);
    }

    if ( tmpdir == NULL ) {
        singularity_message(ERROR, "Failed to obtain session directory\n");
        ABORT(255);
    }

    singularity_message(DEBUG, "Checking configuration option: 'config passwd'\n");
    if ( singularity_config_get_bool(CONFIG_PASSWD) <= 0 ) {
        singularity_message(VERBOSE, "Skipping bind of the host's /etc/passwd\n");
        return(0);
    }

    source_file = joinpath(containerdir, "/etc/passwd");
    tmp_file = joinpath(tmpdir, "/passwd");

    singularity_message(VERBOSE2, "Checking for template passwd file: %s\n", source_file);
    if ( is_file(source_file) < 0 ) {
        singularity_message(VERBOSE, "Passwd file does not exist in container, not updating\n");
        return(0);
    }

    singularity_message(VERBOSE2, "Creating template of /etc/passwd\n");
    if ( ( copy_file(source_file, tmp_file) ) < 0 ) {
        singularity_message(ERROR, "Failed copying template passwd file to tmpdir: %s\n", strerror(errno));
        ABORT(255);
    }

    singularity_message(VERBOSE, "Creating template passwd file and appending user data: %s\n", tmp_file);
    if ( ( file_fp = fopen(tmp_file, "a") ) == NULL ) { // Flawfinder: ignore
        singularity_message(ERROR, "Could not open template passwd file %s: %s\n", tmp_file, strerror(errno));
        ABORT(255);
    }

    fprintf(file_fp, "%s:x:%d:%d:%s:%s:%s\n", pwent->pw_name, pwent->pw_uid, pwent->pw_gid, pwent->pw_gecos, homedir, pwent->pw_shell);
    fclose(file_fp);


    container_file_bind(tmp_file, "/etc/passwd");

    // set HOME to the homedir, because it might be different than outside
    envar_set("HOME", homedir, 1);

    return(0);
}
Exemple #9
0
int _singularity_runtime_mount_userbinds(void) {
    char *container_dir = singularity_runtime_rootfs(NULL);
    char *bind_path_string;

    singularity_message(DEBUG, "Checking for environment variable 'SINGULARITY_BINDPATH'\n");
    if ( ( bind_path_string = singularity_registry_get("BINDPATH") ) != NULL ) {

        singularity_message(DEBUG, "Checking for 'user bind control' in config\n");
        if ( singularity_config_get_bool(USER_BIND_CONTROL) <= 0 ) {
            singularity_message(WARNING, "Ignoring user bind request: user bind control is disabled by system administrator\n");
            return(0);
        }

#ifndef SINGULARITY_NO_NEW_PRIVS
        singularity_message(WARNING, "Ignoring user bind request: host does not support PR_SET_NO_NEW_PRIVS\n");
        return(0);
#endif

        singularity_message(DEBUG, "Parsing SINGULARITY_BINDPATH for user-specified bind mounts.\n");
        char *outside_token = NULL;
        char *inside_token = NULL;
        char *current = strtok_r(strdup(bind_path_string), ",", &outside_token);

        free(bind_path_string);

        while ( current != NULL ) {
            int read_only = 0;
            char *source = strtok_r(current, ":", &inside_token);
            char *dest = strtok_r(NULL, ":", &inside_token);
            char *opts = strtok_r(NULL, ":", &inside_token);

            current = strtok_r(NULL, ",", &outside_token);

            if ( dest == NULL ) {
                dest = source;
            }

            singularity_message(DEBUG, "Found bind: %s -> container:%s\n", source, dest);

            if ( opts != NULL ) {
                if ( strcmp(opts, "rw") == 0 ) {
                    // This is the default
                } else if ( strcmp(opts, "ro") == 0 ) {
                    read_only = 1;
                } else {
                    singularity_message(WARNING, "Not mounting requested bind point, invalid mount option %s: %s\n", opts, dest);
                    continue;
                }
            }


            singularity_message(DEBUG, "Checking if bind point is already mounted: %s\n", dest);
            if ( check_mounted(dest) >= 0 ) {
                singularity_message(WARNING, "Not mounting requested bind point (already mounted in container): %s\n", dest);
                continue;
            }

            if ( ( is_file(source) == 0 ) && ( is_file(joinpath(container_dir, dest)) < 0 ) ) {
                if ( singularity_registry_get("OVERLAYFS_ENABLED") != NULL ) {
                    char *dir = dirname(strdup(dest));
                    if ( is_dir(joinpath(container_dir, dir)) < 0 ) {
                        singularity_message(VERBOSE3, "Creating bind directory on overlay file system: %s\n", dest);
                        if ( s_mkpath(joinpath(container_dir, dir), 0755) < 0 ) {
                            singularity_priv_escalate();
                            singularity_message(VERBOSE3, "Retrying with privileges to create bind directory on overlay file system: %s\n", dest);
                            if ( s_mkpath(joinpath(container_dir, dir), 0755) < 0 ) {
                                singularity_message(ERROR, "Could not create basedir for file bind %s: %s\n", dest, strerror(errno));
                                continue;
                            }
                            singularity_priv_drop();
                        }
                    }
                    singularity_priv_escalate();
                    singularity_message(VERBOSE3, "Creating bind file on overlay file system: %s\n", dest);
                    FILE *tmp = fopen(joinpath(container_dir, dest), "w+"); // Flawfinder: ignore
                    singularity_priv_drop();
                    if ( tmp == NULL ) {
                        singularity_message(WARNING, "Skipping user bind, could not create bind point %s: %s\n", dest, strerror(errno));
                        continue;
                    }
                    if ( fclose(tmp) != 0 ) {
                        singularity_message(WARNING, "Skipping user bind, could not close bind point file descriptor %s: %s\n", dest, strerror(errno));
                        continue;
                    }
                    singularity_message(DEBUG, "Created bind file: %s\n", dest);
                } else {
                    singularity_message(WARNING, "Skipping user bind, non existant bind point (file) in container: '%s'\n", dest);
                    continue;
                }
            } else if ( ( is_dir(source) == 0 ) && ( is_dir(joinpath(container_dir, dest)) < 0 ) ) {
                if ( singularity_registry_get("OVERLAYFS_ENABLED") != NULL ) {
                    singularity_message(VERBOSE3, "Creating bind directory on overlay file system: %s\n", dest);
                    if ( s_mkpath(joinpath(container_dir, dest), 0755) < 0 ) {
                        singularity_priv_escalate();
                        singularity_message(VERBOSE3, "Retrying with privileges to create bind directory on overlay file system: %s\n", dest);
                        if ( s_mkpath(joinpath(container_dir, dest), 0755) < 0 ) {
                            singularity_priv_drop();
                            singularity_message(WARNING, "Skipping user bind, could not create bind point %s: %s\n", dest, strerror(errno));
                            continue;
                        }
                        singularity_priv_drop();
                    }
                } else {
                    singularity_message(WARNING, "Skipping user bind, non existant bind point (directory) in container: '%s'\n", dest);
                    continue;
                }
            }

            singularity_priv_escalate();
            singularity_message(VERBOSE, "Binding '%s' to '%s/%s'\n", source, container_dir, dest);
            if ( mount(source, joinpath(container_dir, dest), NULL, MS_BIND|MS_NOSUID|MS_REC, NULL) < 0 ) {
                singularity_message(ERROR, "There was an error binding the path %s: %s\n", source, strerror(errno));
                ABORT(255);
            }
            if ( read_only ) {
                if ( singularity_priv_userns_enabled() == 1 ) {
                    singularity_message(WARNING, "Can not make bind mount read only within the user namespace: %s\n", dest);
                } else {
                    singularity_message(VERBOSE, "Remounting %s read-only\n", dest);
                    if ( mount(NULL, joinpath(container_dir, dest), NULL, MS_RDONLY|MS_BIND|MS_NOSUID|MS_REC|MS_REMOUNT, NULL) < 0 ) {
                        singularity_message(ERROR, "There was an error write-protecting the path %s: %s\n", source, strerror(errno));
                        ABORT(255);
                    }
                    if ( access(joinpath(container_dir, dest), W_OK) == 0 || errno != EROFS ) { // Flawfinder: ignore (precautionary confirmation, not necessary)
                        singularity_message(ERROR, "Failed to write-protect the path %s: %s\n", source, strerror(errno));
                        ABORT(255);
                    }
                }
            } else {
                if ( singularity_priv_userns_enabled() <= 0 ) {
                    if ( mount(NULL, joinpath(container_dir, dest), NULL, MS_BIND|MS_NOSUID|MS_REC|MS_REMOUNT, NULL) < 0 ) {
                        singularity_message(ERROR, "There was an error remounting the path %s: %s\n", source, strerror(errno));
                        ABORT(255);
                    }
                }
            }
            singularity_priv_drop();

        }

        singularity_message(DEBUG, "Unsetting environment variable 'SINGULARITY_BINDPATH'\n");
        unsetenv("SINGULARITY_BINDPATH");
    } else {
        singularity_message(DEBUG, "No user bind mounts specified.\n");
    }
    return(0);
}
Exemple #10
0
int singularity_mount_kernelfs(void) {
    char *container_dir = singularity_rootfs_dir();

    // Mount /proc if we are configured
    singularity_message(DEBUG, "Checking configuration file for 'mount proc'\n");
    singularity_config_rewind();
    if ( singularity_config_get_bool("mount proc", 1) > 0 ) {
        if ( is_dir(joinpath(container_dir, "/proc")) == 0 ) {
            if ( singularity_ns_pid_enabled() >= 0 ) {
                singularity_priv_escalate();
                singularity_message(VERBOSE, "Mounting /proc\n");
                if ( mount("proc", joinpath(container_dir, "/proc"), "proc", 0, NULL) < 0 ) {
                    singularity_message(ERROR, "Could not mount /proc into container: %s\n", strerror(errno));
                    ABORT(255);
                }
                singularity_priv_drop();
            } else {
                singularity_priv_escalate();
                singularity_message(VERBOSE, "Bind mounting /proc\n");
                if ( mount("/proc", joinpath(container_dir, "/proc"), NULL, MS_BIND|MS_NOSUID|MS_REC, NULL) < 0 ) {
                    singularity_message(ERROR, "Could not bind mount container's /proc: %s\n", strerror(errno));
                    ABORT(255);
                }
                singularity_priv_drop();
            }
        } else {
            singularity_message(WARNING, "Not mounting /proc, container has no bind directory\n");
        }
    } else {
        singularity_message(VERBOSE, "Skipping /proc mount\n");
    }


    // Mount /sys if we are configured
    singularity_message(DEBUG, "Checking configuration file for 'mount sys'\n");
    singularity_config_rewind();
    if ( singularity_config_get_bool("mount sys", 1) > 0 ) {
        if ( is_dir(joinpath(container_dir, "/sys")) == 0 ) {
            if ( singularity_ns_user_enabled() < 0 ) {
                singularity_priv_escalate();
                singularity_message(VERBOSE, "Mounting /sys\n");
                if ( mount("sysfs", joinpath(container_dir, "/sys"), "sysfs", 0, NULL) < 0 ) {
                    singularity_message(ERROR, "Could not mount /sys into container: %s\n", strerror(errno));
                    ABORT(255);
                }
                singularity_priv_drop();
            } else {
                singularity_priv_escalate();
                singularity_message(VERBOSE, "Bind mounting /sys\n");
                if ( mount("/sys", joinpath(container_dir, "/sys"), NULL, MS_BIND|MS_NOSUID|MS_REC, NULL) < 0 ) {
                    singularity_message(ERROR, "Could not bind mount container's /sys: %s\n", strerror(errno));
                    ABORT(255);
                }
                singularity_priv_drop();
            }
        } else {
            singularity_message(WARNING, "Not mounting /sys, container has no bind directory\n");
        }
    } else {
        singularity_message(VERBOSE, "Skipping /sys mount\n");
    }

    return(0);
}
Exemple #11
0
int singularity_file_group(void) {
    FILE *file_fp;
    char *source_file;
    char *tmp_file;
    int i;
    uid_t uid = singularity_priv_getuid();
    uid_t gid = singularity_priv_getgid();
    const gid_t *gids = singularity_priv_getgids();
    int gid_count = singularity_priv_getgidcount();
    char *containerdir = singularity_rootfs_dir();
    char *sessiondir = singularity_sessiondir_get();

    singularity_message(DEBUG, "Called singularity_file_group_create()\n");

    if ( uid == 0 ) {
        singularity_message(VERBOSE, "Not updating group file, running as root!\n");
        return(0);
    }

    if ( containerdir == NULL ) {
        singularity_message(ERROR, "Failed to obtain container directory\n");
        ABORT(255);
    }

    if ( sessiondir == NULL ) {
        singularity_message(ERROR, "Failed to obtain session directory\n");
        ABORT(255);
    }

    singularity_message(DEBUG, "Checking configuration option: 'config group'\n");
    if ( singularity_config_get_bool(CONFIG_GROUP) <= 0 ) {
        singularity_message(VERBOSE, "Skipping bind of the host's /etc/group\n");
        return(0);
    }

    source_file = joinpath(containerdir, "/etc/group");
    tmp_file = joinpath(sessiondir, "/group");

    if ( is_file(source_file) < 0 ) {
        singularity_message(VERBOSE, "Group file does not exist in container, not updating\n");
        return(0);
    }

    errno = 0;
    struct passwd *pwent = getpwuid(uid);
    if ( ! pwent ) {
        // List of potential error codes for unknown name taken from man page.
        if ( (errno == 0) || (errno == ESRCH) || (errno == EBADF) || (errno == EPERM) || (errno == ENOENT)) {
            singularity_message(VERBOSE3, "Not updating group file as passwd entry for UID %d not found.\n", uid);
            return(0);
        } else {
            singularity_message(ERROR, "Failed to lookup username for UID %d: %s\n", uid, strerror(errno));
            ABORT(255);
        }
    }

    singularity_message(VERBOSE2, "Creating template of /etc/group for containment\n");
    if ( ( copy_file(source_file, tmp_file) ) < 0 ) {
        singularity_message(ERROR, "Failed copying template group file to sessiondir: %s\n", strerror(errno));
        ABORT(255);
    }

    if ( ( file_fp = fopen(tmp_file, "a") ) == NULL ) { // Flawfinder: ignore
        singularity_message(ERROR, "Could not open template group file %s: %s\n", tmp_file, strerror(errno));
        ABORT(255);
    }

    errno = 0;
    struct group *grent = getgrgid(gid);
    if ( grent ) {
        singularity_message(VERBOSE, "Updating group file with user info\n");
        fprintf(file_fp, "\n%s:x:%u:%s\n", grent->gr_name, grent->gr_gid, pwent->pw_name);
    } else if ( (errno == 0) || (errno == ESRCH) || (errno == EBADF) || (errno == EPERM) || (errno == ENOENT) ) {
        // It's rare, but certainly possible to have a GID that's not a group entry in this system.
        // According to the man page, all of the above errno's can indicate this situation.
        singularity_message(VERBOSE3, "Skipping GID %d as group entry does not exist.\n", gid);
    } else {
        singularity_message(ERROR, "Failed to lookup GID %d group entry: %s\n", gid, strerror(errno));
        ABORT(255);
    }


    singularity_message(DEBUG, "Getting supplementary group info\n");

    for (i=0; i < gid_count; i++) {
        if ( gids[i] == gid ) {
            singularity_message(DEBUG, "Skipping duplicate supplementary group\n");
            continue;
        }

        if ( gids[i] < UINT_MAX && gids[i] >= 500 ) {
            errno = 0;
            struct group *gr = getgrgid(gids[i]);
            if ( gr ) {
                singularity_message(VERBOSE3, "Found supplementary group membership in: %d\n", gids[i]);
                singularity_message(VERBOSE2, "Adding user's supplementary group ('%s') info to template group file\n", grent->gr_name);
                fprintf(file_fp, "%s:x:%u:%s\n", gr->gr_name, gr->gr_gid, pwent->pw_name);
            } else if ( (errno == 0) || (errno == ESRCH) || (errno == EBADF) || (errno == EPERM) ) {
                singularity_message(VERBOSE3, "Skipping GID %d as group entry does not exist.\n", gids[i]);
            } else {
                singularity_message(ERROR, "Failed to lookup GID %d group entry: %s\n", gids[i], strerror(errno));
                ABORT(255);
            }
        } else {
            singularity_message(VERBOSE, "Group id '%d' is out of bounds\n", gids[i]);
        }
    }

    fclose(file_fp);


    container_file_bind(tmp_file, "/etc/group");

    return(0);
}