mount user option

ibotty bsd at ibotty.net
Thu Sep 25 16:36:27 PDT 2003


> somehow, for now, DO NOT APPLY THIS PATCH to your checkout!!!
> i could not mount any fs with this patch (+some
> recent changes) now, so beware!

i do no know, what has caused this...
the patch is actually ok, something else must have caused this, now it is
fine though.
anyways, i attached a new cvs diff.

this patch finally handles the sysctl vfs.usermount.
you must set vfs.usermount to 1, to usermount any fs with 'user' option.

i also commented vfs-syscalls.c on every place, where security checks are
done (and not done).

so the only things missing are: 
- checking, if the user is a local user
 (i have no real idea on how to get the users console (utmp maybe?))
- manpage (i will write it at a journey by train tomorrow)


somehow i seem to have blown up mount_procfs, i have no idea how though, it
bails out with a BUS_ERROR. (maybe 'it wasnt me'(tm).)

so do not try the patch if you badly need procfs.

btw: i shortened the diff by excluding dirs, which i only ansi-ized
(declarations). take the usermount.tar.gz from ../..

~ibottyIndex: sys/kern/vfs_syscalls.c
===================================================================
RCS file: /home/src/dcvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.17
diff -u -3 -p -r1.17 vfs_syscalls.c
--- sys/kern/vfs_syscalls.c	23 Sep 2003 05:03:51 -0000	1.17
+++ sys/kern/vfs_syscalls.c	25 Sep 2003 22:56:43 -0000
@@ -114,20 +114,31 @@ mount(struct mount_args *uap)
 	struct nameidata nd;
 	char fstypename[MFSNAMELEN];
 
-	if (usermount == 0 && (error = suser(td)))
+	/* this is a dropin replacement for suser in mount(2)
+	   this macro cannot be used outside of mount(2):
+	   it needs a valid proc *p and struct mount_args *uap. */
+#define SUSER(_thread)							\
+	( (suser(_thread) || 						\
+		(p->p_ucred->cr_ruid != 0 &&				\
+		 SCARG(uap, flags) & MNT_USER ))			\
+	  		? EPERM : 0 )
+
+
+	if (usermount == 0 && (error = SUSER(td)))
 		return (error);
+
 	/*
 	 * Do not allow NFS export by non-root users.
 	 */
 	if (SCARG(uap, flags) & MNT_EXPORTED) {
-		error = suser(td);
+		error = SUSER(td);
 		if (error)
 			return (error);
 	}
 	/*
 	 * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users
 	 */
-	if (suser(td)) 
+	if (SUSER(td)) 
 		SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
 	/*
 	 * Get vnode to be covered
@@ -158,9 +169,11 @@ mount(struct mount_args *uap)
 		/*
 		 * Only root, or the user that did the original mount is
 		 * permitted to update it.
+		 * If the filesystem was mounted with the MNT_USER option,
+		 * noone is permitted to update it.
 		 */
 		if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
-		    (error = suser(td))) {
+		    suser(td) && (SCARG(uap, flags) & MNT_USER)) {
 			vput(vp);
 			return (error);
 		}
@@ -186,6 +199,8 @@ mount(struct mount_args *uap)
 	/*
 	 * If the user is not root, ensure that they own the directory
 	 * onto which we are attempting to mount.
+	 * Does no extra checks for MNT_USER mounts, because they are
+	 * always done with euid = 0
 	 */
 	if ((error = VOP_GETATTR(vp, &va, td)) ||
 	    (va.va_uid != p->p_ucred->cr_uid &&
@@ -280,7 +295,11 @@ mount(struct mount_args *uap)
 	mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
 	strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
 	mp->mnt_vnodecovered = vp;
-	mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
+	/* if user-mounted fs, set owner */
+	if (SCARG(uap, flags) & MNT_USER)
+		mp->mnt_stat.f_owner = p->p_ucred->cr_ruid;
+	else
+		mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
 	mp->mnt_iosize_max = DFLTPHYS;
 	VOP_UNLOCK(vp, 0, td);
 update:
@@ -430,6 +449,8 @@ unmount(struct unmount_args *uap)
 	/*
 	 * Only root, or the user that did the original mount is
 	 * permitted to unmount this filesystem.
+	 * Because MNT_USER mounts are owned by non-root,
+	 * this non-root user can unmount this fs.
 	 */
 	if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
 	    (error = suser(td))) {
Index: sbin/mount/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
--- sbin/mount/extern.h	17 Jun 2003 04:27:33 -0000	1.2
+++ sbin/mount/extern.h	25 Sep 2003 20:52:58 -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: sbin/mount/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
--- sbin/mount/getmntopts.c	17 Jun 2003 04:27:33 -0000	1.2
+++ sbin/mount/getmntopts.c	25 Sep 2003 20:52:58 -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: sbin/mount/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
--- sbin/mount/mntopts.h	17 Jun 2003 04:27:33 -0000	1.2
+++ sbin/mount/mntopts.h	25 Sep 2003 21:40:56 -0000
@@ -57,6 +57,7 @@ struct mntopt {
 #define MOPT_NOCLUSTERR		{ "clusterr",	1, MNT_NOCLUSTERR, 0 }
 #define MOPT_NOCLUSTERW		{ "clusterw",	1, MNT_NOCLUSTERW, 0 }
 #define MOPT_SUIDDIR		{ "suiddir",	0, MNT_SUIDDIR, 0 }
+#define MOPT_USER		{ "user",	0, MNT_USER, 0 }
 
 /* Control flags. */
 #define MOPT_FORCE		{ "force",	0, MNT_FORCE, 0 }
@@ -70,7 +71,8 @@ struct mntopt {
 #define MOPT_FSTAB_COMPAT						\
 	MOPT_RO,							\
 	MOPT_RW,							\
-	MOPT_AUTO
+	MOPT_AUTO,							\
+	MOPT_USER
 
 /* Standard options which all mounts can understand. */
 #define MOPT_STDOPTS							\
@@ -86,9 +88,10 @@ struct mntopt {
 	MOPT_RDONLY,							\
 	MOPT_UNION,							\
 	MOPT_NOCLUSTERR,						\
-	MOPT_NOCLUSTERW
+	MOPT_NOCLUSTERW,						\
+	MOPT_USER
 
-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: sbin/mount/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
--- sbin/mount/mount.8	17 Jun 2003 04:27:33 -0000	1.2
+++ sbin/mount/mount.8	25 Sep 2003 20:52:58 -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: sbin/mount/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
--- sbin/mount/mount.c	17 Jun 2003 04:27:33 -0000	1.2
+++ sbin/mount/mount.c	25 Sep 2003 20:52:58 -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 *);
+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,9 +113,7 @@ 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;
@@ -129,6 +127,8 @@ main(argc, argv)
 	options = NULL;
 	vfslist = NULL;
 	vfstype = "ufs";
+
+	/* iterate over options */
 	while ((ch = getopt(argc, argv, "adfo:prwt:uv")) != -1)
 		switch (ch) {
 		case 'a':
@@ -176,7 +176,8 @@ main(argc, argv)
 
 #define	BADTYPE(type)							\
 	(strcmp(type, FSTAB_RO) &&					\
-	    strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ))
+	    strcmp(type, FSTAB_RW) && 					\
+		strcmp(type, FSTAB_RQ))
 
 	rval = 0;
 	switch (argc) {
@@ -194,18 +195,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))
 					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 +223,7 @@ main(argc, argv)
 			usage();
 
 		if (init_flags & MNT_UPDATE) {
+
 			mntfromname = NULL;
 			have_fstab = 0;
 			if ((mntbuf = getmntpt(*argv)) == NULL)
@@ -253,7 +258,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);
 			break;
 		}
 		rmslashes(*argv, *argv);
@@ -264,6 +269,7 @@ main(argc, argv)
 		if (BADTYPE(fs->fs_type))
 			errx(1, "%s has unknown file system type",
 			    *argv);
+
 		rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file,
 		    init_flags, options, fs->fs_mntops);
 		break;
@@ -287,7 +293,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 +308,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 +325,8 @@ ismounted(fs, mntbuf, mntsize)
 }
 
 int
-isremountable(vfsname)
-	const char *vfsname;
+isremountable(const char *vfsname)
+	
 {
 	const char **cp;
 
@@ -333,8 +337,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 +360,17 @@ hasopt(mntopts, option)
 	return (found);
 }
 
+
+/*
+ * Mount the filesystem using mount_<type>.
+ */
 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 )
 {
 	/* List of directories containing mount_xxx subcommands. */
 	static const char *edirs[] = {
@@ -379,6 +389,7 @@ mountfs(vfstype, spec, name, flags, opti
 	(void)&name;
 #endif
 
+
 	/* resolve the mountpoint with realpath(3) */
 	(void)checkpath(name, mntpath);
 	name = mntpath;
@@ -490,8 +501,7 @@ mountfs(vfstype, spec, name, flags, opti
 }
 
 void
-prmount(sfp)
-	struct statfs *sfp;
+prmount(struct statfs *sfp)
 {
 	int flags;
 	struct opt *o;
@@ -525,8 +535,7 @@ prmount(sfp)
 }
 
 struct statfs *
-getmntpt(name)
-	const char *name;
+getmntpt(const char *name)
 {
 	struct statfs *mntbuf;
 	int i, mntsize;
@@ -541,9 +550,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 +572,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 +598,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 +653,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 +686,7 @@ usage()
 }
 
 void
-putfsent(ent)
-	const struct statfs *ent;
+putfsent(const struct statfs *ent)
 {
 	struct fstab *fst;
 	char *opts;
@@ -713,8 +711,7 @@ putfsent(ent)
 
 
 char *
-flags2opts(flags)
-	int flags;
+flags2opts(int flags)
 {
 	char *res;
 
Index: sbin/mount/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
--- sbin/mount/vfslist.c	17 Jun 2003 04:27:33 -0000	1.2
+++ sbin/mount/vfslist.c	25 Sep 2003 21:19:30 -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