diff options
-rw-r--r-- | support/include/fstab.h | 7 | ||||
-rw-r--r-- | support/nfs/fstab.c | 58 | ||||
-rw-r--r-- | utils/mount/mount.c | 63 |
3 files changed, 122 insertions, 6 deletions
diff --git a/support/include/fstab.h b/support/include/fstab.h index 8053066..ab30c5a 100644 --- a/support/include/fstab.h +++ b/support/include/fstab.h @@ -3,6 +3,10 @@ #include "nfs_mntent.h" +#ifndef _PATH_FSTAB +#define _PATH_FSTAB "/etc/fstab" +#endif + int mtab_is_writable(void); int mtab_does_not_exist(void); @@ -15,6 +19,9 @@ struct mntentchn *getmntoptfile (const char *file); struct mntentchn *getmntdirbackward (const char *dir, struct mntentchn *mc); struct mntentchn *getmntdevbackward (const char *dev, struct mntentchn *mc); +struct mntentchn *getfsfile (const char *file); +struct mntentchn *getfsspec (const char *spec); + void lock_mtab (void); void unlock_mtab (void); void update_mtab (const char *special, nfs_mntent_t *with); diff --git a/support/nfs/fstab.c b/support/nfs/fstab.c index 23ea927..ba7e580 100644 --- a/support/nfs/fstab.c +++ b/support/nfs/fstab.c @@ -80,8 +80,11 @@ mtab_is_writable() { struct mntentchn mounttable; static int got_mtab = 0; +struct mntentchn fstab; +static int got_fstab = 0; static void read_mounttable(void); +static void read_fstab(void); static struct mntentchn * mtab_head() { @@ -90,6 +93,14 @@ mtab_head() { return &mounttable; } +static struct mntentchn * +fstab_head() +{ + if (!got_fstab) + read_fstab(); + return &fstab; +} + static void my_free(const void *s) { if (s) @@ -167,6 +178,27 @@ read_mounttable() { read_mntentchn(mfp, fnam, mc); } +static void +read_fstab() +{ + mntFILE *mfp = NULL; + const char *fnam; + struct mntentchn *mc = &fstab; + + got_fstab = 1; + mc->nxt = mc->prev = NULL; + + fnam = _PATH_FSTAB; + mfp = nfs_setmntent (fnam, "r"); + if (mfp == NULL || mfp->mntent_fp == NULL) { + int errsv = errno; + error(_("warning: can't open %s: %s"), + _PATH_FSTAB, strerror (errsv)); + return; + } + read_mntentchn(mfp, fnam, mc); +} + /* * Given the directory name NAME, and the place MCPREV we found it last time, * try to find more occurrences. @@ -201,6 +233,32 @@ getmntdevbackward (const char *name, struct mntentchn *mcprev) { return NULL; } +/* Find the dir FILE in fstab. */ +struct mntentchn * +getfsfile (const char *file) +{ + struct mntentchn *mc, *mc0; + + mc0 = fstab_head(); + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) + if (streq(mc->m.mnt_dir, file)) + return mc; + return NULL; +} + +/* Find the device SPEC in fstab. */ +struct mntentchn * +getfsspec (const char *spec) +{ + struct mntentchn *mc, *mc0; + + mc0 = fstab_head(); + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) + if (streq(mc->m.mnt_fsname, spec)) + return mc; + return NULL; +} + /* Updating mtab ----------------------------------------------*/ /* Flag for already existing lock file. */ diff --git a/utils/mount/mount.c b/utils/mount/mount.c index 0edcc1a..cdccfe8 100644 --- a/utils/mount/mount.c +++ b/utils/mount/mount.c @@ -28,6 +28,7 @@ #include <sys/mount.h> #include <getopt.h> #include <mntent.h> +#include <pwd.h> #include "fstab.h" #include "xcommon.h" @@ -75,6 +76,11 @@ struct opt_map { int mask; /* flag mask value */ }; +/* Custom mount options for our own purposes. */ +#define MS_DUMMY 0x00000000 +#define MS_USERS 0x40000000 +#define MS_USER 0x80000000 + static const struct opt_map opt_map[] = { { "defaults", 0, 0, 0 }, /* default options */ { "ro", 1, 0, MS_RDONLY }, /* read-only */ @@ -91,6 +97,20 @@ static const struct opt_map opt_map[] = { { "remount", 0, 0, MS_REMOUNT}, /* Alter flags of mounted FS */ { "bind", 0, 0, MS_BIND }, /* Remount part of tree elsewhere */ { "rbind", 0, 0, MS_BIND|MS_REC }, /* Idem, plus mounted subtrees */ + { "auto", 0, 0, MS_DUMMY }, /* Can be mounted using -a */ + { "noauto", 0, 0, MS_DUMMY }, /* Can only be mounted explicitly */ + { "users", 1, 0, MS_USERS|MS_NOEXEC|MS_NOSUID|MS_NODEV }, + /* Allow ordinary user to mount */ + { "nousers", 0, 1, MS_DUMMY }, /* Forbid ordinary user to mount */ + { "user", 1, 0, MS_USER|MS_NOEXEC|MS_NOSUID|MS_NODEV }, + /* Allow ordinary user to mount */ + { "nouser", 0, 1, MS_DUMMY }, /* Forbid ordinary user to mount */ + { "owner", 0, 0, MS_DUMMY }, /* Let the owner of the device mount */ + { "noowner", 0, 0, MS_DUMMY }, /* Device owner has no special privs */ + { "group", 0, 0, MS_DUMMY }, /* Let the group of the device mount */ + { "nogroup", 0, 0, MS_DUMMY }, /* Device group has no special privs */ + { "_netdev", 0, 0, MS_DUMMY}, /* Device requires network */ + { "comment", 0, 0, MS_DUMMY}, /* fstab comment only (kudzu,_netdev)*/ /* add new options here */ #ifdef MS_NOSUB @@ -105,6 +125,7 @@ static const struct opt_map opt_map[] = { { "mand", 0, 0, MS_MANDLOCK }, /* Allow mandatory locks on this FS */ { "nomand", 0, 1, MS_MANDLOCK }, /* Forbid mandatory locks on this FS */ #endif + { "loop", 1, 0, MS_DUMMY }, /* use a loop device */ #ifdef MS_NOATIME { "atime", 0, 1, MS_NOATIME }, /* Update access time */ { "noatime", 0, 0, MS_NOATIME }, /* Do not update access time */ @@ -122,6 +143,15 @@ static char * fix_opts_string (int flags, const char *extra_opts) { char *new_opts; new_opts = xstrdup((flags & MS_RDONLY) ? "ro" : "rw"); + if (flags & MS_USER) { + /* record who mounted this so they can unmount */ + struct passwd *pw = getpwuid(getuid()); + if(pw) + new_opts = xstrconcat3(new_opts, ",user=", pw->pw_name); + } + if (flags & MS_USERS) + new_opts = xstrconcat3(new_opts, ",users", ""); + for (om = opt_map; om->opt != NULL; om++) { if (om->skip) continue; @@ -282,16 +312,12 @@ int main(int argc, char *argv[]) int c, flags = 0, nfs_mount_vers = 0, mnt_err = 1, fake = 0; char *spec, *mount_point, *extra_opts = NULL; char *mount_opts = NULL, *p; + uid_t uid = getuid(); progname = argv[0]; if ((p = strrchr(progname, '/')) != NULL) progname = p+1; - if (getuid() != 0) { - printf("%s: only root can do that.\n", progname); - exit(1); - } - if(!strncmp(progname, "umount", strlen("umount"))) { if(argc < 2) { umount_usage(); @@ -375,10 +401,35 @@ int main(int argc, char *argv[]) } spec = argv[1]; - mount_point = canonicalize(argv[2]); + mount_point = argv[2]; + + if (uid != 0) { + /* don't even think about it unless options exactly + * make fstab + */ + struct mntentchn *mc; + + if ((mc = getfsfile(mount_point)) == NULL || + strcmp(mc->m.mnt_fsname, spec) != 0 || + strcmp(mc->m.mnt_opts, mount_opts) != 0) { + fprintf(stderr, "%s: permission died - no match for fstab\n", + progname); + exit(1); + } + mounttype = 0; + } + + mount_point = canonicalize(mount_point); parse_opts(mount_opts, &flags, &extra_opts); + if (uid != 0) { + if (! (flags & (MS_USERS | MS_USER))) { + fprintf(stderr, "%s: permission denied\n", progname); + exit(1); + } + } + if (!strcmp(progname, "mount.nfs4") || nfs_mount_vers == 4) { nfs_mount_vers = 4; mnt_err = nfs4mount(spec, mount_point, &flags, &extra_opts, &mount_opts, 0); |