All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Fix NFS mount options in mount.nfs v3
@ 2006-07-08  4:47 Amit Gud
  0 siblings, 0 replies; only message in thread
From: Amit Gud @ 2006-07-08  4:47 UTC (permalink / raw)
  To: Neil Brown; +Cc: nfs, Steve Dickson, Steinar H. Gunderson

[-- Attachment #1: Type: text/plain, Size: 66 bytes --]



AG
-- 
May the source be with you.
http://www.cis.ksu.edu/~gud


[-- Attachment #2: fix-mount-options-v3.patch --]
[-- Type: text/plain, Size: 14663 bytes --]

If the 'user' or 'users' mount option is specified on commandline, verify with /etc/fstab if it is really specified. Setuid bit is still ON and should remain ON since mount drops the root privileges.

I've given this patch a good hammering, but not exhaustive by any means.  

Based on 1.0.9.


Signed-off-by: Amit Gud <agud@redhat.com>

---
diff -uprN -X dontdiff nfs-utils/support/include/fstab.h nfs-utils-ag/support/include/fstab.h
--- nfs-utils/support/include/fstab.h	2006-07-02 17:34:57.000000000 -0400
+++ nfs-utils-ag/support/include/fstab.h	2006-07-07 23:29:17.000000000 -0400
@@ -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);
 
@@ -16,6 +20,10 @@ struct mntentchn *getmntoptfile (const c
 struct mntentchn *getmntdirbackward (const char *dir, struct mntentchn *mc);
 struct mntentchn *getmntdevbackward (const char *dev, struct mntentchn *mc);
 
+struct mntentchn *fstab_head (void);
+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 -uprN -X dontdiff nfs-utils/support/include/nfs_mntent.h nfs-utils-ag/support/include/nfs_mntent.h
--- nfs-utils/support/include/nfs_mntent.h	2006-07-02 17:34:57.000000000 -0400
+++ nfs-utils-ag/support/include/nfs_mntent.h	2006-07-07 22:40:01.000000000 -0400
@@ -7,10 +7,10 @@
 #define _NFS_MNTENT_H
 
 typedef struct nfs_mntent_s {
-	const char *mnt_fsname;
-	const char *mnt_dir;
-	const char *mnt_type;
-	const char *mnt_opts;
+	char *mnt_fsname;
+	char *mnt_dir;
+	char *mnt_type;
+	char *mnt_opts;
 	int mnt_freq;
 	int mnt_passno;
 } nfs_mntent_t;
diff -uprN -X dontdiff nfs-utils/support/nfs/fstab.c nfs-utils-ag/support/nfs/fstab.c
--- nfs-utils/support/nfs/fstab.c	2006-07-02 17:34:57.000000000 -0400
+++ nfs-utils-ag/support/nfs/fstab.c	2006-07-07 23:29:06.000000000 -0400
@@ -78,10 +78,10 @@ mtab_is_writable() {
 
 /* Contents of mtab and fstab ---------------------------------*/
 
-struct mntentchn mounttable;
-static int got_mtab = 0;
+struct mntentchn mounttable, fstab;
+static int got_mtab = 0, got_fstab = 0;
 
-static void read_mounttable(void);
+static void read_mounttable(void), read_fstab(void);
 
 struct mntentchn *
 mtab_head() {
@@ -96,6 +96,13 @@ my_free(const void *s) {
 		free((void *) s);
 }
 
+struct mntentchn *
+fstab_head() {
+	if (!got_fstab)
+		read_fstab();
+	return &fstab;
+}
+
 static void
 discard_mntentchn(struct mntentchn *mc0) {
 	struct mntentchn *mc, *mc1;
@@ -167,6 +174,26 @@ 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 +228,30 @@ getmntdevbackward (const char *name, str
 	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 -uprN -X dontdiff nfs-utils/utils/mount/Makefile.am nfs-utils-ag/utils/mount/Makefile.am
--- nfs-utils/utils/mount/Makefile.am	2006-07-02 17:34:58.000000000 -0400
+++ nfs-utils-ag/utils/mount/Makefile.am	2006-07-07 15:06:26.000000000 -0400
@@ -14,9 +14,10 @@ MAINTAINERCLEANFILES = Makefile.in
 
 install-exec-hook:
 	(cd $(DESTDIR)$(sbindir) && \
-	  ln -sf $(sbin_PROGRAMS) mount.nfs4 && \
-	  ln -sf $(sbin_PROGRAMS) umount.nfs && \
-	  ln -sf $(sbin_PROGRAMS) umount.nfs4)
+	  chmod +s $(sbin_PROGRAMS) && \
+	  cp -p $(sbin_PROGRAMS) mount.nfs4 && \
+	  cp -p $(sbin_PROGRAMS) umount.nfs && \
+	  cp -p $(sbin_PROGRAMS) umount.nfs4)
 uninstall-hook:
 	(cd $(DESTDIR)$(sbindir) && \
 	    rm -f mount.nfs4 umount.nfs umount.nfs4)
diff -uprN -X dontdiff nfs-utils/utils/mount/mount.c nfs-utils-ag/utils/mount/mount.c
--- nfs-utils/utils/mount/mount.c	2006-07-02 17:34:58.000000000 -0400
+++ nfs-utils-ag/utils/mount/mount.c	2006-07-07 23:46:20.000000000 -0400
@@ -28,6 +28,7 @@
 #include <sys/mount.h>
 #include <getopt.h>
 #include <mntent.h>
+#include <pwd.h>
 
 #include "fstab.h"
 #include "xcommon.h"
@@ -74,6 +75,12 @@ struct opt_map {
   int  mask;                    /* flag mask value */
 };
 
+/* Custom mount options for our own purposes.  */
+/* Maybe these should now be freed for kernel use again */
+#define MS_DUMMY	0x00000000
+#define MS_USERS	0x40000000
+#define MS_USER		0x20000000
+
 static const struct opt_map opt_map[] = {
   { "defaults", 0, 0, 0         },      /* default options */
   { "ro",       1, 0, MS_RDONLY },      /* read-only */
@@ -90,6 +97,18 @@ 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",    0, 0, MS_USERS  },      /* Allow ordinary user to mount */
+  { "nousers",  0, 1, MS_USERS  },      /* Forbid ordinary user to mount */
+  { "user",     0, 0, MS_USER   },      /* Allow ordinary user to mount */
+  { "nouser",   0, 1, MS_USER   },      /* 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
@@ -104,6 +123,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 */
@@ -121,6 +141,12 @@ static char * fix_opts_string (int flags
 	char *new_opts;
 
 	new_opts = xstrdup((flags & MS_RDONLY) ? "ro" : "rw");
+	if (flags & MS_USER) {
+		struct passwd *pw = getpwuid(getuid());
+		if(pw)
+			new_opts = xstrconcat3(new_opts, ",user=", pw->pw_name);
+	}
+	
 	for (om = opt_map; om->opt != NULL; om++) {
 		if (om->skip)
 			continue;
@@ -132,9 +158,20 @@ static char * fix_opts_string (int flags
 	if (extra_opts && *extra_opts) {
 		new_opts = xstrconcat3(new_opts, ",", extra_opts);
 	}
+
 	return new_opts;
 }
 
+void copy_mntent(struct mntent *ment, nfs_mntent_t *nment)
+{
+	/* Not sure why nfs_mntent_t should exist */
+	strcpy(nment->mnt_fsname, ment->mnt_fsname);
+	strcpy(nment->mnt_dir, ment->mnt_dir);
+	strcpy(nment->mnt_type, ment->mnt_type);
+	strcpy(nment->mnt_opts, ment->mnt_opts);
+	nment->mnt_freq = ment->mnt_freq;
+	nment->mnt_passno = ment->mnt_passno;
+}
 
 int add_mtab(char *fsname, char *mount_point, char *fstype, int flags, char *opts, int freq, int passno)
 {
@@ -146,8 +183,16 @@ int add_mtab(char *fsname, char *mount_p
 	ment.mnt_dir = mount_point;
 	ment.mnt_type = fstype;
 	ment.mnt_opts = fix_opts_string(flags, opts);
-	ment.mnt_freq = 0;
-	ment.mnt_passno= 0;
+	ment.mnt_freq = freq;
+	ment.mnt_passno= passno;
+
+	if(flags & MS_REMOUNT) {
+		nfs_mntent_t nment;
+		
+		copy_mntent(&ment, &nment);
+		update_mtab(nment.mnt_dir, &nment);
+		return 0;
+	}
 
 	if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)	{
 		fprintf(stderr, "Can't get "MOUNTED"~ lock file");
@@ -242,20 +287,56 @@ static void parse_opts (const char *opti
 
 }
 
+/*
+ * Look for an option in a comma-separated list
+ */
+int
+contains(const char *list, const char *s) {
+	int n = strlen(s);
+
+	while (*list) {
+		if (strncmp(list, s, n) == 0 &&
+		  (list[n] == 0 || list[n] == ','))
+			return 1;
+		while (*list && *list++ != ',') ;
+	}
+	return 0;
+}
+
+/*
+ * If list contains "user=peter" and we ask for "user=", return "peter"
+ */
+char *
+get_value(const char *list, const char *s) {
+	const char *t;
+	int n = strlen(s);
+
+	while (*list) {
+		if (strncmp(list, s, n) == 0) {
+			s = t = list+n;
+			while (*s && *s != ',')
+				s++;
+			return xstrndup(t, s-t);
+		}
+		while (*list && *list++ != ',') ;
+	}
+	return 0;
+}
+
 static void mount_error(char *node)
 {
 	switch(errno) {
 		case ENOTDIR:
-			printf("%s: mount point %s is not a directory\n", progname, node);
+			fprintf(stderr, "%s: mount point %s is not a directory\n", progname, node);
 			break;
 		case EBUSY:
-			printf("%s: %s is already mounted or busy\n", progname, node);
+			fprintf(stderr, "%s: %s is already mounted or busy\n", progname, node);
 			break;
 		case ENOENT:
-			printf("%s: mount point %s does not exist\n", progname, node);
+			fprintf(stderr, "%s: mount point %s does not exist\n", progname, node);
 			break;
 		default:
-			printf("%s: %s\n", progname, strerror(errno));
+			fprintf(stderr, "%s: %s\n", progname, strerror(errno));
 	}
 }
 
@@ -264,16 +345,13 @@ 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;
+	struct mntentchn *mc;
+	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();
@@ -355,9 +433,33 @@ int main(int argc, char *argv[])
 
 	spec = argv[1];
 	mount_point = canonicalize(argv[2]);
-	
+
 	parse_opts(mount_opts, &flags, &extra_opts);
 
+	if (uid != 0 && !(flags & MS_USERS) && !(flags & MS_USER)) {
+		fprintf(stderr, "%s: permission denied\n", progname);
+		exit(1);
+	}
+
+	if ((flags & MS_USER || flags & MS_USERS) && uid != 0) {
+		/* check if fstab has entry, and further see if the user or users option is given */
+		if ((mc = getfsspec(spec)) == NULL &&
+		    (mc = getfsfile(spec)) == NULL) {
+			fprintf(stderr, "%s: permission denied - invalid option\n", progname);
+			exit(1);
+		}
+		else {
+			if((flags & MS_USER) && !contains(mc->m.mnt_opts, "user")) {
+				fprintf(stderr, "%s: permission denied - invalid option\n", progname);
+				exit(1);
+			}
+			if((flags & MS_USERS) && !contains(mc->m.mnt_opts, "users")) {
+				fprintf(stderr, "%s: permission denied - invalid option\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);
@@ -370,16 +472,19 @@ int main(int argc, char *argv[])
 	}
 
 	if (!mnt_err && !fake) {
-		mnt_err = do_mount_syscall(spec, mount_point, nfs_mount_vers == 4 ? "nfs4" : "nfs", flags, mount_opts);
+		if(!(flags & MS_REMOUNT)) {
+			mnt_err = do_mount_syscall(spec, mount_point,
+					nfs_mount_vers == 4 ? "nfs4" : "nfs", flags, mount_opts);
 		
-		if(mnt_err) {
-			mount_error(mount_point);
-			exit(-1);
+			if(mnt_err) {
+				mount_error(mount_point);
+				exit(-1);
+			}
 		}
-
-		if(!nomtab)
+		if(!nomtab) {
 			add_mtab(spec, mount_point, nfs_mount_vers == 4 ? "nfs4" : "nfs",
 				 flags, extra_opts, 0, 0);
+		}
 	}
 
 	return 0;
diff -uprN -X dontdiff nfs-utils/utils/mount/nfs_mount.h nfs-utils-ag/utils/mount/nfs_mount.h
--- nfs-utils/utils/mount/nfs_mount.h	2006-07-02 17:34:58.000000000 -0400
+++ nfs-utils-ag/utils/mount/nfs_mount.h	2006-07-07 22:38:15.000000000 -0400
@@ -80,5 +80,7 @@ struct nfs_mount_data {
 
 int nfsmount(const char *, const char *, int *, char **, char **, int *, int);
 void mount_errors(char *, int, int);
+int contains(const char *, const char *);
+char *get_value(const char *, const char *);
 
 #endif /* _NFS_MOUNT_H */
diff -uprN -X dontdiff nfs-utils/utils/mount/nfsumount.c nfs-utils-ag/utils/mount/nfsumount.c
--- nfs-utils/utils/mount/nfsumount.c	2006-07-02 17:34:58.000000000 -0400
+++ nfs-utils-ag/utils/mount/nfsumount.c	2006-07-07 23:24:03.000000000 -0400
@@ -23,12 +23,14 @@
 #include <mntent.h>
 #include <sys/mount.h>
 #include <ctype.h>
+#include <pwd.h>
 
 #include "xcommon.h"
 #include "fstab.h"
 #include "nls.h"
 #include "conn.h"
 
+#include "nfs_mount.h"
 #include "mount_constants.h"
 #include "mount.h"
 #include "nfsumount.h"
@@ -307,7 +309,7 @@ int _nfsumount(const char *spec, const c
 		goto out_bad;
 	return nfs_call_umount(&mnt_server, &dirname);
  out_bad:
-	printf("%s: %s: not found or not mounted\n", progname, spec);
+	fprintf(stderr, "%s: %s: not found or not mounted\n", progname, spec);
 	return 0;
 }
 
@@ -376,6 +378,21 @@ int nfsumount(int argc, char *argv[])
 		printf(_("Could not find %s in mtab\n"), spec);
 
 	if(mc) {
+		if(contains(mc->m.mnt_opts, "user") && getuid() != 0) {
+			struct passwd *pw = getpwuid(getuid());
+			if(!pw || strcmp(pw->pw_name, get_value(mc->m.mnt_opts, "user="))) {
+				fprintf(stderr, "%s: permission denied to unmount %s\n",
+						progname, spec);
+				exit(1);
+			}
+		} else {
+			if(!contains(mc->m.mnt_opts, "users") && getuid() != 0) {
+				fprintf(stderr, "%s: only root can unmount %s from %s\n",
+						progname, mc->m.mnt_fsname, mc->m.mnt_dir);
+				exit(1);
+			}
+		}
+
 		ret = _nfsumount(mc->m.mnt_fsname, mc->m.mnt_opts);
 		if(ret)
 			ret = add_mtab2(mc->m.mnt_fsname, mc->m.mnt_dir,

[-- Attachment #3: Type: text/plain, Size: 299 bytes --]

Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

[-- Attachment #4: Type: text/plain, Size: 140 bytes --]

_______________________________________________
NFS maillist  -  NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2006-07-08  4:44 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-07-08  4:47 [PATCH] Fix NFS mount options in mount.nfs v3 Amit Gud

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.