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