diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c index 20055d885b0..f412adbe741 100644 --- a/usr.sbin/mountd/mountd.c +++ b/usr.sbin/mountd/mountd.c @@ -228,7 +228,8 @@ static int do_export_mount(struct exportlist *, struct statfs *); static int do_mount(struct exportlist *, struct grouplist *, uint64_t, struct expcred *, char *, int, struct statfs *, int, int *); static int do_opt(char **, char **, struct exportlist *, - struct grouplist *, int *, uint64_t *, struct expcred *); + struct grouplist *, int *, uint64_t *, struct expcred *, + char *); static struct exportlist *ex_search(fsid_t *, struct exportlisthead *); static struct exportlist *get_exp(void); static void free_dir(struct dirlist *); @@ -303,6 +304,7 @@ static int *sock_fd; static int sock_fdcnt; static int sock_fdpos; static int suspend_nfsd = 0; +static int alldirs_fail = 0; static int opt_flags; static int have_v6 = 1; @@ -331,6 +333,7 @@ static gid_t *tmp_groups = NULL; #define OP_MASKLEN 0x200 #define OP_SEC 0x400 #define OP_CLASSMASK 0x800 /* mask not specified, is Class A/B/C default */ +#define OP_NOTROOT 0x1000 /* Mark the the mount path is not a fs root */ #ifdef DEBUG static int debug = 1; @@ -469,7 +472,7 @@ main(int argc, char **argv) else close(s); - while ((c = getopt(argc, argv, "2Adeh:lnp:RrS")) != -1) + while ((c = getopt(argc, argv, "2Aadeh:lnp:RrS")) != -1) switch (c) { case '2': force_v2 = 1; @@ -477,6 +480,9 @@ main(int argc, char **argv) case 'A': warn_admin = 0; break; + case 'a': + alldirs_fail = 1; + break; case 'e': /* now a no-op, since this is the default */ break; @@ -1592,6 +1598,7 @@ get_exportlist_one(int passno) v4root_phase = 0; dirhead = (struct dirlist *)NULL; unvis_dir[0] = '\0'; + fsb.f_mntonname[0] = '\0'; while (get_line()) { if (debug) @@ -1652,7 +1659,7 @@ get_exportlist_one(int passno) warnx("doing opt %s", cp); got_nondir = 1; if (do_opt(&cp, &endcp, ep, grp, &has_host, - &exflags, &anon)) { + &exflags, &anon, unvis_dir)) { getexp_err(ep, tgrp, NULL); goto nextline; } @@ -1733,19 +1740,9 @@ get_exportlist_one(int passno) fsb.f_fsid.val[1]); } - if (warn_admin != 0 && - (ep->ex_flag & EX_ADMINWARN) == 0 && - strcmp(unvis_dir, fsb.f_mntonname) != - 0) { - if (debug) - warnx("exporting %s exports entire " - "%s file system", unvis_dir, - fsb.f_mntonname); - syslog(LOG_ERR, "Warning: exporting %s " - "exports entire %s file system", - unvis_dir, fsb.f_mntonname); - ep->ex_flag |= EX_ADMINWARN; - } + if (strcmp(unvis_dir, fsb.f_mntonname) != + 0) + opt_flags |= OP_NOTROOT; /* * Add dirpath to export mount point. @@ -1815,6 +1812,17 @@ get_exportlist_one(int passno) "WARNING: No mask specified for %s, " "using out-of-date default", (&grp->gr_ptr.gt_net)->nt_name); + if ((opt_flags & OP_NOTROOT) != 0 && warn_admin != 0 && + (ep->ex_flag & EX_ADMINWARN) == 0 && unvis_dir[0] != '\0' && + fsb.f_mntonname[0] != '\0') { + if (debug) + warnx("exporting %s exports entire %s file " + "system", unvis_dir, fsb.f_mntonname); + syslog(LOG_ERR, "Warning: exporting %s exports " + "entire %s file system", unvis_dir, + fsb.f_mntonname); + ep->ex_flag |= EX_ADMINWARN; + } if (check_options(dirhead)) { getexp_err(ep, tgrp, NULL); goto nextline; @@ -2838,7 +2846,7 @@ parsesec(char *seclist, struct exportlist *ep) */ static int do_opt(char **cpp, char **endcpp, struct exportlist *ep, struct grouplist *grp, - int *has_hostp, uint64_t *exflagsp, struct expcred *cr) + int *has_hostp, uint64_t *exflagsp, struct expcred *cr, char *unvis_dir) { char *cpoptarg, *cpoptend; char *cp, *endcp, *cpopt, savedc, savedc2; @@ -2923,6 +2931,12 @@ do_opt(char **cpp, char **endcpp, struct exportlist *ep, struct grouplist *grp, syslog(LOG_ERR, "= after op: %s", cpopt); return (1); } + if ((opt_flags & OP_NOTROOT) != 0) { + syslog(LOG_ERR, "%s: path %s not mount point", + cpopt, unvis_dir); + if (alldirs_fail != 0) + return (1); + } opt_flags |= OP_ALLDIRS; } else if (!strcmp(cpopt, "public")) { if (fnd_equal == 1) { @@ -3319,7 +3333,8 @@ do_mount(struct exportlist *ep, struct grouplist *grp, uint64_t exflags, ret = 1; goto error_exit; } - if (opt_flags & OP_ALLDIRS) { + if ((opt_flags & OP_ALLDIRS) && + alldirs_fail != 0) { if (errno == EINVAL) syslog(LOG_ERR, "-alldirs requested but %s is not a filesystem mountpoint",