From 13c5a6832f9ad7fc5448de1c2f977e575c4b2dcb Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Mon, 16 Oct 2006 22:39:51 +0000 Subject: mount: support user mounts if CONFIG_DESKTOP --- applets/applets.c | 10 +++---- include/applets.h | 6 +++- util-linux/mount.c | 80 +++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 68 insertions(+), 28 deletions(-) diff --git a/applets/applets.c b/applets/applets.c index 5d8b80881..00102daa3 100644 --- a/applets/applets.c +++ b/applets/applets.c @@ -316,10 +316,10 @@ static void parse_config_file(void) #endif /* CONFIG_FEATURE_SUID_CONFIG */ #ifdef CONFIG_FEATURE_SUID -static void check_suid (struct BB_applet *applet) +static void check_suid(struct BB_applet *applet) { - uid_t ruid = getuid (); /* real [ug]id */ - uid_t rgid = getgid (); + uid_t ruid = getuid(); /* real [ug]id */ + uid_t rgid = getgid(); #ifdef CONFIG_FEATURE_SUID_CONFIG if (suid_cfg_readable) { @@ -334,7 +334,7 @@ static void check_suid (struct BB_applet *applet) if (sct->m_uid == ruid) /* same uid */ m >>= 6; - else if ((sct->m_gid == rgid) || ingroup (ruid, sct->m_gid)) /* same group / in group */ + else if ((sct->m_gid == rgid) || ingroup(ruid, sct->m_gid)) /* same group / in group */ m >>= 3; if (!(m & S_IXOTH)) /* is x bit not set ? */ @@ -358,7 +358,7 @@ static void check_suid (struct BB_applet *applet) if (!onetime) { onetime = 1; - fprintf (stderr, "Using fallback suid method\n"); + fprintf(stderr, "Using fallback suid method\n"); } #endif } diff --git a/include/applets.h b/include/applets.h index 3b759de20..0c0209676 100644 --- a/include/applets.h +++ b/include/applets.h @@ -46,6 +46,10 @@ # define _BB_DIR_USR_SBIN _BB_DIR_SBIN #endif +// _BB_SUID_ALWAYS: will complain if busybox isn't suid +// and is run by non-root (applet_main() will not be called at all) +// _BB_SUID_NEVER: will drop suid prior to applet_main() +// _BB_SUID_MAYBE: neither of the above USE_TEST(APPLET_NOUSAGE([, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) USE_TEST(APPLET_NOUSAGE([[, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) @@ -198,7 +202,7 @@ USE_MKSWAP(APPLET(mkswap, _BB_DIR_SBIN, _BB_SUID_NEVER)) USE_MKTEMP(APPLET(mktemp, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER)) USE_MORE(APPLET(more, _BB_DIR_BIN, _BB_SUID_NEVER)) -USE_MOUNT(APPLET(mount, _BB_DIR_BIN, _BB_SUID_NEVER)) +USE_MOUNT(APPLET(mount, _BB_DIR_BIN, USE_DESKTOP(_BB_SUID_MAYBE) SKIP_DESKTOP(_BB_SUID_NEVER))) USE_MOUNTPOINT(APPLET(mountpoint, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_MSH(APPLET_NOUSAGE(msh, msh, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_MT(APPLET(mt, _BB_DIR_BIN, _BB_SUID_NEVER)) diff --git a/util-linux/mount.c b/util-linux/mount.c index 9793b825a..5ced48fea 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -32,8 +32,19 @@ // Not real flags, but we want to be able to check for this. -#define MOUNT_NOAUTO (1<<29) -#define MOUNT_SWAP (1<<30) +enum { + MOUNT_USERS = (1<<28)*ENABLE_DESKTOP, + MOUNT_NOAUTO = (1<<29), + MOUNT_SWAP = (1<<30), +}; +// TODO: more "user" flag compatibility. +// "user" option (from mount manpage): +// Only the user that mounted a filesystem can unmount it again. +// If any user should be able to unmount, then use users instead of user +// in the fstab line. The owner option is similar to the user option, +// with the restriction that the user must be the owner of the special file. +// This may be useful e.g. for /dev/fd if a login script makes +// the console user owner of this device. /* Standard mount options (from -o options or --options), with corresponding * flags */ @@ -51,8 +62,10 @@ struct { USE_FEATURE_MOUNT_FSTAB( {"defaults", 0}, {"quiet", 0}, - {"noauto",MOUNT_NOAUTO}, - {"swap",MOUNT_SWAP}, + {"noauto", MOUNT_NOAUTO}, + {"swap", MOUNT_SWAP}, + USE_DESKTOP({"user", MOUNT_USERS},) + USE_DESKTOP({"users", MOUNT_USERS},) ) USE_FEATURE_MOUNT_FLAGS( @@ -106,7 +119,8 @@ static void append_mount_options(char **oldopts, char *newopts) if (p) len = p - newopts; p = *oldopts; while (1) { - if (!strncmp(p,newopts,len) && (p[len]==',' || p[len]==0)) + if (!strncmp(p, newopts, len) + && (p[len]==',' || p[len]==0)) goto skip; p = strchr(p,','); if(!p) break; @@ -1422,6 +1436,8 @@ report_error: // Parse options, if necessary parse fstab/mtab, and call singlemount for // each directory to be mounted. +const char must_be_root[] = "you must be root"; + int mount_main(int argc, char **argv) { enum { OPT_ALL = 0x10 }; @@ -1433,13 +1449,15 @@ int mount_main(int argc, char **argv) int i, j, rc = 0; unsigned opt; struct mntent mtpair[2], *mtcur = mtpair; + SKIP_DESKTOP(const int nonroot = 0;) + USE_DESKTOP( int nonroot = (getuid() != 0);) /* parse long options, like --bind and --move. Note that -o option * and --option are synonymous. Yes, this means --remount,rw works. */ for (i = j = 0; i < argc; i++) { if (argv[i][0] == '-' && argv[i][1] == '-') { - append_mount_options(&cmdopts,argv[i]+2); + append_mount_options(&cmdopts, argv[i]+2); } else argv[j++] = argv[i]; } argv[j] = 0; @@ -1470,12 +1488,12 @@ int mount_main(int argc, char **argv) if (!(opt & OPT_ALL)) { FILE *mountTable = setmntent(bb_path_mtab_file, "r"); - if (!mountTable) bb_error_msg_and_die("no %s",bb_path_mtab_file); + if (!mountTable) bb_error_msg_and_die("no %s", bb_path_mtab_file); - while (getmntent_r(mountTable,mtpair,bb_common_bufsiz1, + while (getmntent_r(mountTable, mtpair, bb_common_bufsiz1, sizeof(bb_common_bufsiz1))) { - // Don't show rootfs. + // Don't show rootfs. FIXME: why?? if (!strcmp(mtpair->mnt_fsname, "rootfs")) continue; if (!fstype || !strcmp(mtpair->mnt_type, fstype)) @@ -1493,6 +1511,8 @@ int mount_main(int argc, char **argv) // argument when we get it. if (argc == 2) { + if (nonroot) + bb_error_msg_and_die(must_be_root); mtpair->mnt_fsname = argv[0]; mtpair->mnt_dir = argv[1]; mtpair->mnt_type = fstype; @@ -1502,11 +1522,13 @@ int mount_main(int argc, char **argv) } i = parse_mount_options(cmdopts, 0); + if (nonroot && (i & ~MS_SILENT)) // Non-root users cannot specify flags + bb_error_msg_and_die(must_be_root); // If we have a shared subtree flag, don't worry about fstab or mtab. if (ENABLE_FEATURE_MOUNT_FLAGS && - (i & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE ))) + (i & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))) { rc = mount("", argv[0], "", i, ""); if (rc) bb_perror_msg_and_die("%s", argv[0]); @@ -1515,10 +1537,11 @@ int mount_main(int argc, char **argv) // Open either fstab or mtab - if (i & MS_REMOUNT) + fstabname = "/etc/fstab"; + if (i & MS_REMOUNT) { fstabname = bb_path_mtab_file; - else fstabname = "/etc/fstab"; - fstab = setmntent(fstabname,"r"); + } + fstab = setmntent(fstabname, "r"); if (!fstab) bb_perror_msg_and_die("cannot read %s", fstabname); @@ -1544,11 +1567,17 @@ int mount_main(int argc, char **argv) bb_error_msg_and_die("can't find %s in %s", argv[0], fstabname); + mtcur = mtnext; + if (nonroot) { + // fstab must have "users" or "user" + if (!(parse_mount_options(mtcur->mnt_opts, 0) & MOUNT_USERS)) + bb_error_msg_and_die(must_be_root); + } + // Mount the last thing we found. - mtcur = mtnext; mtcur->mnt_opts = xstrdup(mtcur->mnt_opts); - append_mount_options(&(mtcur->mnt_opts),cmdopts); + append_mount_options(&(mtcur->mnt_opts), cmdopts); rc = singlemount(mtcur, 0); free(mtcur->mnt_opts); } @@ -1563,10 +1592,10 @@ int mount_main(int argc, char **argv) // Is this what we're looking for? - if (strcmp(argv[0],mtcur->mnt_fsname) && - strcmp(storage_path,mtcur->mnt_fsname) && - strcmp(argv[0],mtcur->mnt_dir) && - strcmp(storage_path,mtcur->mnt_dir)) continue; + if (strcmp(argv[0], mtcur->mnt_fsname) && + strcmp(storage_path, mtcur->mnt_fsname) && + strcmp(argv[0], mtcur->mnt_dir) && + strcmp(storage_path, mtcur->mnt_dir)) continue; // Remember this entry. Something later may have overmounted // it, and we want the _last_ match. @@ -1576,15 +1605,22 @@ int mount_main(int argc, char **argv) // If we're mounting all. } else { - // Do we need to match a filesystem type? - if (fstype && strcmp(mtcur->mnt_type,fstype)) continue; + // TODO: support "-t type1,type2"; "-t notype1,type2" + + if (fstype && strcmp(mtcur->mnt_type, fstype)) continue; // Skip noauto and swap anyway. - if (parse_mount_options(mtcur->mnt_opts,0) + if (parse_mount_options(mtcur->mnt_opts, 0) & (MOUNT_NOAUTO | MOUNT_SWAP)) continue; + // No, mount -a won't mount anything, + // even user mounts, for mere humans. + + if (nonroot) + bb_error_msg_and_die(must_be_root); + // Mount this thing. if (singlemount(mtcur, 1)) { -- cgit v1.2.3