mount user option

ibotty bsd at ibotty.net
Tue Sep 23 06:09:36 PDT 2003


this patch allows mount(8) to handle a 'user' option in fstab(5), as in
linux.

advantages:
 - user do not need to be able to write to the device to mount it.
 - no need for the vfs.usermount sysctl(8)

the attached patch has some drawbacks:
 1) /sbin/mount needs to be suid root.
 2) it byepasses vfs.usermount security checks.
 3) a user currently cannot umount the filesystem ;-p


regarding 1), mount will set the euid to the uid, if no user option is given
in /etc/fstab. so the suid-bit is only set, when mounting with 'user'.

regarding 2), i cannot imagine a reasonable solution, that does not do this.
but basic security features should be added (e. g.: no files with owner root
on user-mounted filesystem).

regarding 3), i see two solutions.
one is additional kernel support, the other is a suid-root umount binary.
- in the kernel i would need a possibility to change the statfs->f_owner.
- with a suid umount, i would need to store the f_owner in userspace.
this is perfectly possible, but a bit ..ehm.. hacky. 


BEWARE:
 this is patch is only tested with local hdds, floppies and cds (no nfs,
etc.).

~ibottyIndex: Makefile
===================================================================
RCS file: /home/src/dcvs/src/sbin/mount/Makefile,v
retrieving revision 1.3
diff -u -3 -p -r1.3 Makefile
--- Makefile	6 Sep 2003 18:27:57 -0000	1.3
+++ Makefile	23 Sep 2003 12:32:32 -0000
@@ -7,6 +7,8 @@ SRCS=	mount.c mount_ufs.c getmntopts.c v
 MAN=	mount.8
 # We do NOT install the getmntopts.3 man page.
 
+BINMODE=4555
+
 MLINKS+= mount.8 mount_ufs.8
 
 .include <bsd.prog.mk>
Index: extern.h
===================================================================
RCS file: /home/src/dcvs/src/sbin/mount/extern.h,v
retrieving revision 1.2
diff -u -3 -p -r1.2 extern.h
--- extern.h	17 Jun 2003 04:27:33 -0000	1.2
+++ extern.h	23 Sep 2003 11:44:49 -0000
@@ -28,8 +28,8 @@
  */
 
 /* vfslist.c */
-int checkvfsname __P((const char *, const char **));
-const char **makevfslist __P((char *));
+int checkvfsname (const char *, const char **);
+const char **makevfslist (char *);
 
 /* mount_ufs.c */
-int mount_ufs __P((int, char *const *));
+int mount_ufs (int, char *const *);
Index: getmntopts.c
===================================================================
RCS file: /home/src/dcvs/src/sbin/mount/getmntopts.c,v
retrieving revision 1.2
diff -u -3 -p -r1.2 getmntopts.c
--- getmntopts.c	17 Jun 2003 04:27:33 -0000	1.2
+++ getmntopts.c	23 Sep 2003 11:46:34 -0000
@@ -49,11 +49,10 @@
 int getmnt_silent = 0;
 
 void
-getmntopts(options, m0, flagp, altflagp)
-	const char *options;
-	const struct mntopt *m0;
-	int *flagp;
-	int *altflagp;
+getmntopts(const char *options,
+	const struct mntopt *m0, 
+	int *flagp,
+	int *altflagp)
 {
 	const struct mntopt *m;
 	int negative, len;
@@ -106,9 +105,7 @@ getmntopts(options, m0, flagp, altflagp)
 }
 
 void
-rmslashes(rrpin, rrpout)
-	char *rrpin;
-	char *rrpout;
+rmslashes(char *rrpin, char *rrpout)
 {
 	char *rrpoutstart;
 
@@ -128,9 +125,7 @@ rmslashes(rrpin, rrpout)
 }
 
 void
-checkpath(path, resolved)
-	const char *path;
-	char *resolved;
+checkpath(const char *path, char *resolved)
 {
 	struct stat sb;
 
Index: mntopts.h
===================================================================
RCS file: /home/src/dcvs/src/sbin/mount/mntopts.h,v
retrieving revision 1.2
diff -u -3 -p -r1.2 mntopts.h
--- mntopts.h	17 Jun 2003 04:27:33 -0000	1.2
+++ mntopts.h	23 Sep 2003 11:47:17 -0000
@@ -66,11 +66,13 @@ struct mntopt {
 
 /* This is parsed by mount(8), but is ignored by specific mount_*(8)s. */
 #define MOPT_AUTO		{ "auto",	0, 0, 0 }
+#define MOPT_USER		{ "user",	0, 0, 0 }
 
 #define MOPT_FSTAB_COMPAT						\
 	MOPT_RO,							\
 	MOPT_RW,							\
-	MOPT_AUTO
+	MOPT_AUTO,							\
+	MOPT_USER
 
 /* Standard options which all mounts can understand. */
 #define MOPT_STDOPTS							\
@@ -88,7 +90,7 @@ struct mntopt {
 	MOPT_NOCLUSTERR,						\
 	MOPT_NOCLUSTERW
 
-void getmntopts __P((const char *, const struct mntopt *, int *, int *));
-void rmslashes __P((char *, char *));
-void checkpath __P((const char *, char resolved_path[]));
+void getmntopts (const char *, const struct mntopt *, int *, int *);
+void rmslashes (char *, char *);
+void checkpath (const char *, char resolved_path[]);
 extern int getmnt_silent;
Index: mount.8
===================================================================
RCS file: /home/src/dcvs/src/sbin/mount/mount.8,v
retrieving revision 1.2
diff -u -3 -p -r1.2 mount.8
--- mount.8	17 Jun 2003 04:27:33 -0000	1.2
+++ mount.8	23 Sep 2003 12:00:45 -0000
@@ -213,6 +213,8 @@ Lookups will be done in the mounted file
 If those operations fail due to a non-existent file the underlying
 directory is then accessed.
 All creates are done in the mounted filesystem.
+.It Cm user
+Allow any user to mount this filesystem.
 .El
 .Pp
 Any additional options specific to a filesystem type that is not
Index: mount.c
===================================================================
RCS file: /home/src/dcvs/src/sbin/mount/mount.c,v
retrieving revision 1.2
diff -u -3 -p -r1.2 mount.c
--- mount.c	17 Jun 2003 04:27:33 -0000	1.2
+++ mount.c	23 Sep 2003 11:44:12 -0000
@@ -61,21 +61,21 @@
 
 int debug, fstab_style, verbose;
 
-char   *catopt __P((char *, const char *));
+char   *catopt (char *, const char *);
 struct statfs
-       *getmntpt __P((const char *));
-int	hasopt __P((const char *, const char *));
-int	ismounted __P((struct fstab *, struct statfs *, int));
-int	isremountable __P((const char *));
-void	mangle __P((char *, int *, const char **));
-char   *update_options __P((char *, char *, int));
-int	mountfs __P((const char *, const char *, const char *,
-			int, const char *, const char *));
-void	remopt __P((char *, const char *));
-void	prmount __P((struct statfs *));
-void	putfsent __P((const struct statfs *));
-void	usage __P((void));
-char   *flags2opts __P((int));
+       *getmntpt (const char *);
+int	hasopt (const char *, const char *);
+int	ismounted (struct fstab *, struct statfs *, int);
+int	isremountable (const char *);
+void	mangle (char *, int *, const char **);
+char   *update_options (char *, char *, int);
+int	mountfs (const char *, const char *, const char *,
+			int, const char *, const char *, int);
+void	remopt (char *, const char *);
+void	prmount (struct statfs *);
+void	putfsent (const struct statfs *);
+void	usage (void);
+char   *flags2opts (int);
 
 /* Map from mount options to printable formats. */
 static struct opt {
@@ -113,22 +113,22 @@ remountable_fs_names[] = {
 };
 
 int
-main(argc, argv)
-	int argc;
-	char * const argv[];
+main(int argc, char * const argv[])
 {
 	const char *mntfromname, **vfslist, *vfstype;
 	struct fstab *fs;
 	struct statfs *mntbuf;
 	FILE *mountdfp;
 	pid_t pid;
-	int all, ch, i, init_flags, mntsize, rval, have_fstab;
+	int all, ch, i, init_flags, mntsize, rval, have_fstab, safe;
 	char *options;
 
 	all = init_flags = 0;
 	options = NULL;
 	vfslist = NULL;
 	vfstype = "ufs";
+
+	/* iterate over options */
 	while ((ch = getopt(argc, argv, "adfo:prwt:uv")) != -1)
 		switch (ch) {
 		case 'a':
@@ -174,16 +174,20 @@ main(argc, argv)
 	argc -= optind;
 	argv += optind;
 
+
+
 #define	BADTYPE(type)							\
 	(strcmp(type, FSTAB_RO) &&					\
 	    strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ))
 
 	rval = 0;
+
 	switch (argc) {
 	case 0:
 		if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0)
 			err(1, "getmntinfo");
-		if (all) {
+		if (all)	/* mount all filesystems without "noauto" */ 
+		{
 			while ((fs = getfsent()) != NULL) {
 				if (BADTYPE(fs->fs_type))
 					continue;
@@ -194,18 +198,21 @@ main(argc, argv)
 				if (!(init_flags & MNT_UPDATE) &&
 				    ismounted(fs, mntbuf, mntsize))
 					continue;
+				   
 				if (mountfs(fs->fs_vfstype, fs->fs_spec,
 				    fs->fs_file, init_flags, options,
-				    fs->fs_mntops))
+				    fs->fs_mntops, 0))
 					rval = 1;
 			}
-		} else if (fstab_style) {
+		} else if (fstab_style)			 /* only print */
+		{
 			for (i = 0; i < mntsize; i++) {
 				if (checkvfsname(mntbuf[i].f_fstypename, vfslist))
 					continue;
 				putfsent(&mntbuf[i]);
 			}
-		} else {
+		} else 		/* print currently mounted filesystems */
+		{
 			for (i = 0; i < mntsize; i++) {
 				if (checkvfsname(mntbuf[i].f_fstypename,
 				    vfslist))
@@ -219,6 +226,7 @@ main(argc, argv)
 			usage();
 
 		if (init_flags & MNT_UPDATE) {
+
 			mntfromname = NULL;
 			have_fstab = 0;
 			if ((mntbuf = getmntpt(*argv)) == NULL)
@@ -253,7 +261,7 @@ main(argc, argv)
 				    mntbuf->f_flags);
 			}
 			rval = mountfs(mntbuf->f_fstypename, mntfromname,
-			    mntbuf->f_mntonname, init_flags, options, 0);
+			    mntbuf->f_mntonname, init_flags, options, NULL, 0);
 			break;
 		}
 		rmslashes(*argv, *argv);
@@ -264,8 +272,20 @@ main(argc, argv)
 		if (BADTYPE(fs->fs_type))
 			errx(1, "%s has unknown file system type",
 			    *argv);
+
+		safe = 0;
+#ifndef NO_MOPT_USER
+		/* are we allowed, to mount */
+		if (hasopt(fs->fs_mntops, "user") && 
+		    !hasopt(fs->fs_mntops, "nouser")) {
+			remopt( fs->fs_mntops, "user" );
+			remopt( fs->fs_mntops, "nouser" );
+			safe = 1;
+		}
+#endif
+
 		rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file,
-		    init_flags, options, fs->fs_mntops);
+		    init_flags, options, fs->fs_mntops, safe);
 		break;
 	case 2:
 		/*
@@ -278,7 +298,7 @@ main(argc, argv)
 		    access(argv[0], 0) == -1)
 			vfstype = "nfs";
 		rval = mountfs(vfstype,
-		    argv[0], argv[1], init_flags, options, NULL);
+		    argv[0], argv[1], init_flags, options, NULL, 0);
 		break;
 	default:
 		usage();
@@ -287,7 +307,8 @@ main(argc, argv)
 
 	/*
 	 * If the mount was successfully, and done by root, tell mountd the
-	 * good news.  Pid checks are probably unnecessary, but don't hurt.
+	 * good news. 
+	 * Do not tell mountd, if mounted by non-root user.
 	 */
 	if (rval == 0 && getuid() == 0 &&
 	    (mountdfp = fopen(_PATH_MOUNTDPID, "r")) != NULL) {
@@ -301,10 +322,7 @@ main(argc, argv)
 }
 
 int
-ismounted(fs, mntbuf, mntsize)
-	struct fstab *fs;
-	struct statfs *mntbuf;
-	int mntsize;
+ismounted(struct fstab *fs, struct statfs *mntbuf, int mntsize)
 {
 	int i;
 
@@ -321,8 +339,8 @@ ismounted(fs, mntbuf, mntsize)
 }
 
 int
-isremountable(vfsname)
-	const char *vfsname;
+isremountable(const char *vfsname)
+	
 {
 	const char **cp;
 
@@ -333,8 +351,7 @@ isremountable(vfsname)
 }
 
 int
-hasopt(mntopts, option)
-	const char *mntopts, *option;
+hasopt(const char *mntopts, const char *option)
 {
 	int negative, found;
 	char *opt, *optbuf;
@@ -357,10 +374,20 @@ hasopt(mntopts, option)
 	return (found);
 }
 
+
+/*
+ * Mount the filesystem using mount_<type>.
+ * This implementation will restrict the euid.
+ * Subprocesses are then executed as regular user, not as root.
+ */
 int
-mountfs(vfstype, spec, name, flags, options, mntopts)
-	const char *vfstype, *spec, *name, *options, *mntopts;
-	int flags;
+mountfs(const char *vfstype,
+	const char *spec,
+	const char *name, 
+	int flags,
+	const char *options,
+	const char *mntopts,
+	int safe)
 {
 	/* List of directories containing mount_xxx subcommands. */
 	static const char *edirs[] = {
@@ -379,6 +406,17 @@ mountfs(vfstype, spec, name, flags, opti
 	(void)&name;
 #endif
 
+#ifndef NO_MOPT_USER
+	/* if we are not allowed */
+	if ( !safe )
+	{
+		/* sets the euid to the uid,
+		 * this eleminates the suid bit. */
+		seteuid( getuid() );
+	}
+#endif 
+
+
 	/* resolve the mountpoint with realpath(3) */
 	(void)checkpath(name, mntpath);
 	name = mntpath;
@@ -490,8 +528,7 @@ mountfs(vfstype, spec, name, flags, opti
 }
 
 void
-prmount(sfp)
-	struct statfs *sfp;
+prmount(struct statfs *sfp)
 {
 	int flags;
 	struct opt *o;
@@ -525,8 +562,7 @@ prmount(sfp)
 }
 
 struct statfs *
-getmntpt(name)
-	const char *name;
+getmntpt(const char *name)
 {
 	struct statfs *mntbuf;
 	int i, mntsize;
@@ -541,9 +577,7 @@ getmntpt(name)
 }
 
 char *
-catopt(s0, s1)
-	char *s0;
-	const char *s1;
+catopt(char *s0, const char *s1)
 {
 	size_t i;
 	char *cp;
@@ -565,10 +599,7 @@ catopt(s0, s1)
 }
 
 void
-mangle(options, argcp, argv)
-	char *options;
-	int *argcp;
-	const char **argv;
+mangle(char *options, int *argcp, const char **argv)
 {
 	char *p, *s;
 	int argc;
@@ -594,10 +625,7 @@ mangle(options, argcp, argv)
 
 
 char *
-update_options(opts, fstab, curflags)
-	char *opts;
-	char *fstab;
-	int curflags;
+update_options(char *opts, char *fstab, int curflags)
 {
 	char *o, *p;
 	char *cur;
@@ -652,9 +680,7 @@ update_options(opts, fstab, curflags)
 }
 
 void
-remopt(string, opt)
-	char *string;
- 	const char *opt;
+remopt(char *string, const char *opt)
 {
 	char *o, *p, *r;
 
@@ -687,8 +713,7 @@ usage()
 }
 
 void
-putfsent(ent)
-	const struct statfs *ent;
+putfsent(const struct statfs *ent)
 {
 	struct fstab *fst;
 	char *opts;
@@ -713,8 +738,7 @@ putfsent(ent)
 
 
 char *
-flags2opts(flags)
-	int flags;
+flags2opts(int flags)
 {
 	char *res;
 
Index: mount_ufs.c
===================================================================
RCS file: /home/src/dcvs/src/sbin/mount/mount_ufs.c,v
retrieving revision 1.3
diff -u -3 -p -r1.3 mount_ufs.c
--- mount_ufs.c	8 Aug 2003 04:18:39 -0000	1.3
+++ mount_ufs.c	23 Sep 2003 11:48:08 -0000
@@ -50,7 +50,7 @@
 #include "extern.h"
 #include "mntopts.h"
 
-static void ufs_usage __P((void));
+static void ufs_usage (void);
 
 static struct mntopt mopts[] = {
 	MOPT_STDOPTS,
@@ -62,9 +62,7 @@ static struct mntopt mopts[] = {
 };
 
 int
-mount_ufs(argc, argv)
-	int argc;
-	char * const argv[];
+mount_ufs(int argc, char * const argv[])
 {
 	struct ufs_args args;
 	int ch, mntflags;
Index: vfslist.c
===================================================================
RCS file: /home/src/dcvs/src/sbin/mount/vfslist.c,v
retrieving revision 1.2
diff -u -3 -p -r1.2 vfslist.c
--- vfslist.c	17 Jun 2003 04:27:33 -0000	1.2
+++ vfslist.c	23 Sep 2003 11:49:04 -0000
@@ -44,9 +44,7 @@
 static int	  skipvfs;
 
 int
-checkvfsname(vfsname, vfslist)
-	const char *vfsname;
-	const char **vfslist;
+checkvfsname(const char *vfsname, const char **vfslist)
 {
 
 	if (vfslist == NULL)
@@ -60,8 +58,7 @@ checkvfsname(vfsname, vfslist)
 }
 
 const char **
-makevfslist(fslist)
-	char *fslist;
+makevfslist(char *fslist)
 {
 	const char **av;
 	int i;




More information about the Submit mailing list