Пример #1
0
int s_mkpath(char *dir, mode_t mode) {
    if (!dir) {
        return(-1);
    }

    if (strlength(dir, 2) == 1 && dir[0] == '/') {
        return(0);
    }

    if ( is_dir(dir) == 0 ) {
        // Directory already exists, stop...
        return(0);
    }

    if ( s_mkpath(dirname(strdupa(dir)), mode) < 0 ) {
        // Return if priors failed
        return(-1);
    }

    message(DEBUG, "Creating directory: %s\n", dir);
    if ( mkdir(dir, mode) < 0 ) {
        message(ERROR, "Could not create directory %s: %s\n", dir, strerror(errno));
        return(-1);
    }

    return(0);
}
Пример #2
0
int _singularity_runtime_mount_binds(void) {
    char *tmp_config_string;
    char *container_dir = singularity_runtime_rootfs(NULL);

    if ( singularity_registry_get("CONTAIN") != NULL ) {
        singularity_message(DEBUG, "Skipping bind mounts as contain was requested\n");
        return(0);
    }

    singularity_message(DEBUG, "Checking configuration file for 'bind path'\n");
    const char **tmp_config_string_list = singularity_config_get_value_multi(BIND_PATH);
    if ( strlength(*tmp_config_string_list, 1) == 0 ) {
        return(0);
    }
    while ( *tmp_config_string_list != NULL ) {
        tmp_config_string = strdup(*tmp_config_string_list);
        tmp_config_string_list++;
        char *source = strtok(tmp_config_string, ":");
        char *dest = strtok(NULL, ":");
        chomp(source);
        if ( dest == NULL ) {
            dest = strdup(source);
        } else {
            chomp(dest);
        }

        singularity_message(VERBOSE2, "Found 'bind path' = %s, %s\n", source, dest);

        if ( ( is_file(source) < 0 ) && ( is_dir(source) < 0 ) ) {
            singularity_message(WARNING, "Non existent 'bind path' source: '%s'\n", source);
            continue;
        }

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

        if ( ( is_file(source) == 0 ) && ( is_file(joinpath(container_dir, dest)) < 0 ) ) {
            if ( singularity_registry_get("OVERLAYFS_ENABLED") != NULL ) {
                char *basedir = dirname(joinpath(container_dir, dest));

                singularity_message(DEBUG, "Checking base directory for file %s ('%s')\n", dest, basedir);
                if ( is_dir(basedir) != 0 ) {
                    singularity_message(DEBUG, "Creating base directory for file bind\n");
                    singularity_priv_escalate();
                    if ( s_mkpath(basedir, 0755) != 0 ) {
                        singularity_message(ERROR, "Failed creating base directory to bind file: %s\n", dest);
                        ABORT(255);
                    }
                    singularity_priv_drop();
                }

                free(basedir);

                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, "Could not create bind point file in container %s: %s\n", dest, strerror(errno));
                    continue;
                }
                if ( fclose(tmp) != 0 ) {
                    singularity_message(WARNING, "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, "Non existent 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_priv_escalate();
                singularity_message(VERBOSE3, "Creating bind directory on overlay file system: %s\n", dest);
                if ( s_mkpath(joinpath(container_dir, dest), 0755) < 0 ) {
                    singularity_priv_drop();
                    singularity_message(WARNING, "Could not create bind point directory in container %s: %s\n", dest, strerror(errno));
                    continue;
                }
                singularity_priv_drop();
            } else {
                singularity_message(WARNING, "Non existent 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 ( singularity_priv_userns_enabled() != 1 ) {
            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();
    }

    return(0);
}
Пример #3
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;
}
Пример #4
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);
}
Пример #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);
}
Пример #6
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);
}
Пример #7
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);
}
Пример #8
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);
}