static int mount_points_setup(unsigned n, bool loaded_policy) { unsigned i; int r = 0; for (i = 0; i < n; i ++) { int j; j = mount_one(mount_table + i, loaded_policy); if (j != 0 && r >= 0) r = j; } return r; }
int mount_setup_early(void) { unsigned i; int r = 0; assert_cc(N_EARLY_MOUNT <= ELEMENTSOF(mount_table)); /* Do a minimal mount of /proc and friends to enable the most * basic stuff, such as SELinux */ for (i = 0; i < N_EARLY_MOUNT; i ++) { int j; j = mount_one(mount_table + i, false); if (r == 0) r = j; } return r; }
int mount_setup(bool loaded_policy) { static const char relabel[] = "/run/initramfs/root-fsck\0" "/run/initramfs/shutdown\0"; int r; unsigned i; const char *j; for (i = 0; i < ELEMENTSOF(mount_table); i ++) { r = mount_one(mount_table + i, true); if (r < 0) return r; } /* Nodes in devtmpfs and /run need to be manually updated for * the appropriate labels, after mounting. The other virtual * API file systems like /sys and /proc do not need that, they * use the same label for all their files. */ if (loaded_policy) { usec_t before_relabel, after_relabel; char timespan[FORMAT_TIMESPAN_MAX]; before_relabel = now(CLOCK_MONOTONIC); nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); /* Explicitly relabel these */ NULSTR_FOREACH(j, relabel) label_fix(j, true, false); after_relabel = now(CLOCK_MONOTONIC); log_info("Relabelled /dev and /run in %s.", format_timespan(timespan, sizeof(timespan), after_relabel - before_relabel)); } /* Create a few default symlinks, which are normally created * by udevd, but some scripts might need them before we start * udevd. */ dev_setup(NULL); /* Mark the root directory as shared in regards to mount * propagation. The kernel defaults to "private", but we think * it makes more sense to have a default of "shared" so that * nspawn and the container tools work out of the box. If * specific setups need other settings they can reset the * propagation mode to private if needed. */ if (detect_container(NULL) <= 0) if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0) log_warning("Failed to set up the root directory for shared mount propagation: %m"); /* Create a few directories we always want around, Note that * sd_booted() checks for /run/systemd/system, so this mkdir * really needs to stay for good, otherwise software that * copied sd-daemon.c into their sources will misdetect * systemd. */ mkdir_label("/run/systemd", 0755); mkdir_label("/run/systemd/system", 0755); mkdir_label("/run/systemd/inaccessible", 0000); return 0; }
int mount_cgroup_controllers(char ***join_controllers) { int r; FILE *f; char buf[LINE_MAX]; Set *controllers; /* Mount all available cgroup controllers that are built into the kernel. */ f = fopen("/proc/cgroups", "re"); if (!f) { log_error("Failed to enumerate cgroup controllers: %m"); return 0; } controllers = set_new(string_hash_func, string_compare_func); if (!controllers) { r = log_oom(); goto finish; } /* Ignore the header line */ (void) fgets(buf, sizeof(buf), f); for (;;) { char *controller; int enabled = 0; if (fscanf(f, "%ms %*i %*i %i", &controller, &enabled) != 2) { if (feof(f)) break; log_error("Failed to parse /proc/cgroups."); r = -EIO; goto finish; } if (!enabled) { free(controller); continue; } r = set_put(controllers, controller); if (r < 0) { log_error("Failed to add controller to set."); free(controller); goto finish; } } for (;;) { MountPoint p; char *controller, *where, *options; char ***k = NULL; controller = set_steal_first(controllers); if (!controller) break; if (join_controllers) for (k = join_controllers; *k; k++) if (strv_find(*k, controller)) break; if (k && *k) { char **i, **j; for (i = *k, j = *k; *i; i++) { if (!streq(*i, controller)) { char *t; t = set_remove(controllers, *i); if (!t) { free(*i); continue; } free(t); } *(j++) = *i; } *j = NULL; options = strv_join(*k, ","); if (!options) { free(controller); r = log_oom(); goto finish; } } else { options = controller; controller = NULL; } where = strappend("/sys/fs/cgroup/", options); if (!where) { free(options); r = log_oom(); goto finish; } zero(p); p.what = "cgroup"; p.where = where; p.type = "cgroup"; p.options = options; p.flags = MS_NOSUID|MS_NOEXEC|MS_NODEV; p.mode = MNT_IN_CONTAINER; r = mount_one(&p, true); free(controller); free(where); if (r < 0) { free(options); goto finish; } if (r > 0 && k && *k) { char **i; for (i = *k; *i; i++) { char *t; t = strappend("/sys/fs/cgroup/", *i); if (!t) { r = log_oom(); free(options); goto finish; } r = symlink(options, t); free(t); if (r < 0 && errno != EEXIST) { log_error("Failed to create symlink: %m"); r = -errno; free(options); goto finish; } } } free(options); } r = 0; finish: set_free_free(controllers); fclose(f); return r; }
int mount_cgroup_controllers(char ***join_controllers) { _cleanup_set_free_free_ Set *controllers = NULL; int r; if (!cg_is_legacy_wanted()) return 0; /* Mount all available cgroup controllers that are built into the kernel. */ controllers = set_new(&string_hash_ops); if (!controllers) return log_oom(); r = cg_kernel_controllers(controllers); if (r < 0) return log_error_errno(r, "Failed to enumerate cgroup controllers: %m"); for (;;) { _cleanup_free_ char *options = NULL, *controller = NULL, *where = NULL; MountPoint p = { .what = "cgroup", .type = "cgroup", .flags = MS_NOSUID|MS_NOEXEC|MS_NODEV, .mode = MNT_IN_CONTAINER, }; char ***k = NULL; controller = set_steal_first(controllers); if (!controller) break; if (join_controllers) for (k = join_controllers; *k; k++) if (strv_find(*k, controller)) break; if (k && *k) { char **i, **j; for (i = *k, j = *k; *i; i++) { if (!streq(*i, controller)) { _cleanup_free_ char *t; t = set_remove(controllers, *i); if (!t) { free(*i); continue; } } *(j++) = *i; } *j = NULL; options = strv_join(*k, ","); if (!options) return log_oom(); } else { options = controller; controller = NULL; } where = strappend("/sys/fs/cgroup/", options); if (!where) return log_oom(); p.where = where; p.options = options; r = mount_one(&p, true); if (r < 0) return r; if (r > 0 && k && *k) { char **i; for (i = *k; *i; i++) { _cleanup_free_ char *t = NULL; t = strappend("/sys/fs/cgroup/", *i); if (!t) return log_oom(); r = symlink(options, t); if (r < 0 && errno != EEXIST) return log_error_errno(errno, "Failed to create symlink %s: %m", t); #ifdef SMACK_RUN_LABEL r = mac_smack_copy(t, options); if (r < 0 && r != -EOPNOTSUPP) return log_error_errno(r, "Failed to copy smack label from %s to %s: %m", options, t); #endif } } } /* Now that we mounted everything, let's make the tmpfs the * cgroup file systems are mounted into read-only. */ (void) mount("tmpfs", "/sys/fs/cgroup", "tmpfs", MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755"); return 0; } #if defined(HAVE_SELINUX) || defined(HAVE_SMACK) static int nftw_cb( const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf) { /* No need to label /dev twice in a row... */ if (_unlikely_(ftwbuf->level == 0)) return FTW_CONTINUE; label_fix(fpath, false, false); /* /run/initramfs is static data and big, no need to * dynamically relabel its contents at boot... */ if (_unlikely_(ftwbuf->level == 1 && tflag == FTW_D && streq(fpath, "/run/initramfs"))) return FTW_SKIP_SUBTREE; return FTW_CONTINUE; }; #endif int mount_setup(bool loaded_policy) { unsigned i; int r = 0; for (i = 0; i < ELEMENTSOF(mount_table); i ++) { int j; j = mount_one(mount_table + i, loaded_policy); if (j != 0 && r >= 0) r = j; } if (r < 0) return r; #if defined(HAVE_SELINUX) || defined(HAVE_SMACK) /* Nodes in devtmpfs and /run need to be manually updated for * the appropriate labels, after mounting. The other virtual * API file systems like /sys and /proc do not need that, they * use the same label for all their files. */ if (loaded_policy) { usec_t before_relabel, after_relabel; char timespan[FORMAT_TIMESPAN_MAX]; before_relabel = now(CLOCK_MONOTONIC); nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); after_relabel = now(CLOCK_MONOTONIC); log_info("Relabelled /dev and /run in %s.", format_timespan(timespan, sizeof(timespan), after_relabel - before_relabel, 0)); } #endif /* Create a few default symlinks, which are normally created * by udevd, but some scripts might need them before we start * udevd. */ dev_setup(NULL, UID_INVALID, GID_INVALID); /* Mark the root directory as shared in regards to mount * propagation. The kernel defaults to "private", but we think * it makes more sense to have a default of "shared" so that * nspawn and the container tools work out of the box. If * specific setups need other settings they can reset the * propagation mode to private if needed. */ if (detect_container() <= 0) if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0) log_warning_errno(errno, "Failed to set up the root directory for shared mount propagation: %m"); /* Create a few directories we always want around, Note that * sd_booted() checks for /run/systemd/system, so this mkdir * really needs to stay for good, otherwise software that * copied sd-daemon.c into their sources will misdetect * systemd. */ mkdir_label("/run/systemd", 0755); mkdir_label("/run/systemd/system", 0755); mkdir_label("/run/systemd/inaccessible", 0000); return 0; }
int mount_cgroup_controllers(char ***join_controllers) { int r; char buf[LINE_MAX]; _cleanup_set_free_free_ Set *controllers = NULL; _cleanup_fclose_ FILE *f; /* Mount all available cgroup controllers that are built into the kernel. */ f = fopen("/proc/cgroups", "re"); if (!f) { log_error("Failed to enumerate cgroup controllers: %m"); return 0; } controllers = set_new(string_hash_func, string_compare_func); if (!controllers) return log_oom(); /* Ignore the header line */ (void) fgets(buf, sizeof(buf), f); for (;;) { char *controller; int enabled = 0; if (fscanf(f, "%ms %*i %*i %i", &controller, &enabled) != 2) { if (feof(f)) break; log_error("Failed to parse /proc/cgroups."); return -EIO; } if (!enabled) { free(controller); continue; } r = set_consume(controllers, controller); if (r < 0) { log_error("Failed to add controller to set."); return r; } } for (;;) { MountPoint p = { .what = "cgroup", .type = "cgroup", .flags = MS_NOSUID|MS_NOEXEC|MS_NODEV, .mode = MNT_IN_CONTAINER, }; char ***k = NULL; _cleanup_free_ char *options = NULL, *controller; controller = set_steal_first(controllers); if (!controller) break; if (join_controllers) for (k = join_controllers; *k; k++) if (strv_find(*k, controller)) break; if (k && *k) { char **i, **j; for (i = *k, j = *k; *i; i++) { if (!streq(*i, controller)) { char _cleanup_free_ *t; t = set_remove(controllers, *i); if (!t) { free(*i); continue; } } *(j++) = *i; } *j = NULL; options = strv_join(*k, ","); if (!options) return log_oom(); } else { options = controller; controller = NULL; } p.where = strappenda("/sys/fs/cgroup/", options); p.options = options; r = mount_one(&p, true); if (r < 0) return r; if (r > 0 && k && *k) { char **i; for (i = *k; *i; i++) { char *t = strappenda("/sys/fs/cgroup/", *i); r = symlink(options, t); if (r < 0 && errno != EEXIST) { log_error("Failed to create symlink %s: %m", t); return -errno; } } } } return 0; } static int nftw_cb( const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf) { /* No need to label /dev twice in a row... */ if (_unlikely_(ftwbuf->level == 0)) return FTW_CONTINUE; label_fix(fpath, false, false); /* /run/initramfs is static data and big, no need to * dynamically relabel its contents at boot... */ if (_unlikely_(ftwbuf->level == 1 && tflag == FTW_D && streq(fpath, "/run/initramfs"))) return FTW_SKIP_SUBTREE; return FTW_CONTINUE; }; int mount_setup(bool loaded_policy) { int r; unsigned i; for (i = 0; i < ELEMENTSOF(mount_table); i ++) { r = mount_one(mount_table + i, true); if (r < 0) return r; } /* Nodes in devtmpfs and /run need to be manually updated for * the appropriate labels, after mounting. The other virtual * API file systems like /sys and /proc do not need that, they * use the same label for all their files. */ if (loaded_policy) { usec_t before_relabel, after_relabel; char timespan[FORMAT_TIMESPAN_MAX]; before_relabel = now(CLOCK_MONOTONIC); nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); after_relabel = now(CLOCK_MONOTONIC); log_info("Relabelled /dev and /run in %s.", format_timespan(timespan, sizeof(timespan), after_relabel - before_relabel, 0)); } /* Create a few default symlinks, which are normally created * by udevd, but some scripts might need them before we start * udevd. */ dev_setup(NULL); /* Mark the root directory as shared in regards to mount * propagation. The kernel defaults to "private", but we think * it makes more sense to have a default of "shared" so that * nspawn and the container tools work out of the box. If * specific setups need other settings they can reset the * propagation mode to private if needed. */ if (detect_container(NULL) <= 0) if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0) log_warning("Failed to set up the root directory for shared mount propagation: %m"); /* Create a few directories we always want around, Note that * sd_booted() checks for /run/systemd/system, so this mkdir * really needs to stay for good, otherwise software that * copied sd-daemon.c into their sources will misdetect * systemd. */ mkdir_label("/run/systemd", 0755); mkdir_label("/run/systemd/system", 0755); mkdir_label("/run/systemd/inaccessible", 0000); return 0; }
extern int mount_main(int argc, char **argv) { struct stat statbuf; char *string_flags = xstrdup(""); char *extra_opts; int flags = 0; char *filesystemType = "auto"; int got_filesystemType = 0; char *device = xmalloc(PATH_MAX); char *directory = xmalloc(PATH_MAX); struct mntent *m = NULL; int all = FALSE; int fakeIt = FALSE; int useMtab = TRUE; int rc = EXIT_FAILURE; FILE *f = 0; int opt; /* Parse options */ while ((opt = getopt(argc, argv, "o:rt:wafnv")) > 0) { switch (opt) { case 'o': parse_mount_options(optarg, &flags, &string_flags); break; case 'r': flags |= MS_RDONLY; break; case 't': filesystemType = optarg; got_filesystemType = 1; break; case 'w': flags &= ~MS_RDONLY; break; case 'a': all = TRUE; break; case 'f': fakeIt = TRUE; break; #ifdef BB_FEATURE_MTAB_SUPPORT case 'n': useMtab = FALSE; break; #endif case 'v': break; /* ignore -v */ } } if (!all && optind == argc) show_mounts(got_filesystemType ? filesystemType : 0); if (optind < argc) { /* if device is a filename get its real path */ if (stat(argv[optind], &statbuf) == 0) { char *tmp = simplify_path(argv[optind]); safe_strncpy(device, tmp, PATH_MAX); } else { safe_strncpy(device, argv[optind], PATH_MAX); } } if (optind + 1 < argc) directory = simplify_path(argv[optind + 1]); if (all || optind + 1 == argc) { f = setmntent("/etc/fstab", "r"); if (f == NULL) perror_msg_and_die( "\nCannot read /etc/fstab"); while ((m = getmntent(f)) != NULL) { if (! all && optind + 1 == argc && ( (strcmp(device, m->mnt_fsname) != 0) && (strcmp(device, m->mnt_dir) != 0) ) ) { continue; } if (all && ( // If we're mounting 'all' (strstr(m->mnt_opts, "noauto")) || // and the file system isn't noauto, (strstr(m->mnt_type, "swap")) || // and isn't swap or nfs, then mount it (strstr(m->mnt_type, "nfs")) ) ) { continue; } if (all || flags == 0) { // Allow single mount to override fstab flags flags = 0; string_flags[0] = 0; parse_mount_options(m->mnt_opts, &flags, &string_flags); } strcpy(device, m->mnt_fsname); strcpy(directory, m->mnt_dir); filesystemType = xstrdup(m->mnt_type); singlemount: extra_opts = string_flags; rc = EXIT_SUCCESS; #ifdef BB_NFSMOUNT if (strchr(device, ':') != NULL) { filesystemType = "nfs"; if (nfsmount (device, directory, &flags, &extra_opts, &string_flags, 1)) { perror_msg("nfsmount failed"); rc = EXIT_FAILURE; } } #endif if (!mount_one(device, directory, filesystemType, flags, string_flags, useMtab, fakeIt, extra_opts, TRUE, all)) rc = EXIT_FAILURE; if (! all) break; } if (f) endmntent(f); if (! all && f && m == NULL) fprintf(stderr, "Can't find %s in /etc/fstab\n", device); return rc; } goto singlemount; }
int main(int argc, char *argv[]) { struct mount_options *opts = &options; char *device, *mntdir; int res = 0; if (argc > 0) { char *cp = strrchr(argv[0], '/'); progname = (cp ? cp + 1 : argv[0]); } nilfs_cleaner_logger = nilfs_mount_logger; parse_options(argc, argv, opts); umask(022); if (optind >= argc || !argv[optind]) die(EX_USAGE, _("No device specified")); device = argv[optind++]; if (optind >= argc || !argv[optind]) die(EX_USAGE, _("No mountpoint specified")); mntdir = argv[optind++]; if (opts->fstype && strncmp(opts->fstype, fstype, strlen(fstype))) die(EX_USAGE, _("Unknown filesystem (%s)"), opts->fstype); if (getuid() != geteuid()) die(EX_USAGE, _("%s: mount by non-root user is not supported yet"), progname); if (!nomtab && mtab_does_not_exist()) die(EX_USAGE, _("%s: no %s found - aborting"), progname, MOUNTED); if (!(opts->flags & MS_RDONLY) && !(opts->flags & MS_BIND)) { res = device_is_readonly(device, &devro); if (res) die(EX_USAGE, _("%s: device %s not accessible: %s"), progname, device, strerror(res)); } if (signal(SIGTERM, handle_signal) == SIG_ERR) die(EX_SYSERR, _("Could not set SIGTERM")); if (signal(SIGINT, handle_signal) == SIG_ERR) die(EX_SYSERR, _("Could not set SIGINT")); block_signals(SIG_BLOCK); res = mount_one(device, mntdir, opts); block_signals(SIG_UNBLOCK); my_free(opts->opts); my_free(opts->extra_opts); return res; }