int singularity_mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data) { if ( ( mountflags & MS_BIND ) ) { setfsuid(singularity_priv_getuid()); } return mount(source, target, filesystemtype, mountflags, data); }
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); }
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); }
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); }