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