From owner-svn-src-projects@freebsd.org Sat Aug 22 22:56:51 2020 Return-Path: Delivered-To: svn-src-projects@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 9D28C3C7ADE for ; Sat, 22 Aug 2020 22:56:51 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BYv033sKrz3g5y; Sat, 22 Aug 2020 22:56:51 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4F7051D765; Sat, 22 Aug 2020 22:56:51 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 07MMupku007830; Sat, 22 Aug 2020 22:56:51 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 07MMuoZZ007827; Sat, 22 Aug 2020 22:56:50 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202008222256.07MMuoZZ007827@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Sat, 22 Aug 2020 22:56:50 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r364496 - in projects/nfs-over-tls: sys/fs/nfs sys/fs/nfsserver sys/sys usr.sbin/mountd X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: in projects/nfs-over-tls: sys/fs/nfs sys/fs/nfsserver sys/sys usr.sbin/mountd X-SVN-Commit-Revision: 364496 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 22 Aug 2020 22:56:51 -0000 Author: rmacklem Date: Sat Aug 22 22:56:50 2020 New Revision: 364496 URL: https://svnweb.freebsd.org/changeset/base/364496 Log: Update mount.h to use high order bits of the 64bit mnt_flags and merge recent changes to mountd.c. Modified: projects/nfs-over-tls/sys/fs/nfs/nfsdport.h projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdport.c projects/nfs-over-tls/sys/sys/mount.h projects/nfs-over-tls/usr.sbin/mountd/mountd.c Modified: projects/nfs-over-tls/sys/fs/nfs/nfsdport.h ============================================================================== --- projects/nfs-over-tls/sys/fs/nfs/nfsdport.h Sat Aug 22 21:32:11 2020 (r364495) +++ projects/nfs-over-tls/sys/fs/nfs/nfsdport.h Sat Aug 22 22:56:50 2020 (r364496) @@ -81,9 +81,9 @@ struct nfsexstuff { #define NFSVNO_EXPORTANON(e) ((e)->nes_exflag & MNT_EXPORTANON) #define NFSVNO_EXSTRICTACCESS(e) ((e)->nes_exflag & MNT_EXSTRICTACCESS) #define NFSVNO_EXV4ONLY(e) ((e)->nes_exflag & MNT_EXV4ONLY) -#define NFSVNO_EXTLS(e) ((e)->nes_exflag & MNTEX_TLS) -#define NFSVNO_EXTLSCERT(e) ((e)->nes_exflag & MNTEX_TLSCERT) -#define NFSVNO_EXTLSCERTUSER(e) ((e)->nes_exflag & MNTEX_TLSCERTUSER) +#define NFSVNO_EXTLS(e) ((e)->nes_exflag & MNT_EXTLS) +#define NFSVNO_EXTLSCERT(e) ((e)->nes_exflag & MNT_EXTLSCERT) +#define NFSVNO_EXTLSCERTUSER(e) ((e)->nes_exflag & MNT_EXTLSCERTUSER) #define NFSVNO_SETEXRDONLY(e) ((e)->nes_exflag = (MNT_EXPORTED|MNT_EXRDONLY)) Modified: projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdport.c ============================================================================== --- projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdport.c Sat Aug 22 21:32:11 2020 (r364495) +++ projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdport.c Sat Aug 22 22:56:50 2020 (r364496) @@ -3561,11 +3561,11 @@ nfsvno_v4rootexport(struct nfsrv_descript *nd) } /* And set ND_EXxx flags for TLS. */ - if ((exflags & MNTEX_TLS) != 0) { + if ((exflags & MNT_EXTLS) != 0) { nd->nd_flag |= ND_EXTLS; - if ((exflags & MNTEX_TLSCERT) != 0) + if ((exflags & MNT_EXTLSCERT) != 0) nd->nd_flag |= ND_EXTLSCERT; - if ((exflags & MNTEX_TLSCERTUSER) != 0) + if ((exflags & MNT_EXTLSCERTUSER) != 0) nd->nd_flag |= ND_EXTLSCERTUSER; } Modified: projects/nfs-over-tls/sys/sys/mount.h ============================================================================== --- projects/nfs-over-tls/sys/sys/mount.h Sat Aug 22 21:32:11 2020 (r364495) +++ projects/nfs-over-tls/sys/sys/mount.h Sat Aug 22 22:56:50 2020 (r364496) @@ -294,6 +294,45 @@ void __mnt_vnode_markerfree_lazy(struct vnode #endif /* _KERNEL */ +#if defined(_WANT_MNTOPTNAMES) || defined(_KERNEL) +struct mntoptnames { + uint64_t o_opt; + const char *o_name; +}; +#define MNTOPT_NAMES \ + { MNT_ASYNC, "asynchronous" }, \ + { MNT_EXPORTED, "NFS exported" }, \ + { MNT_LOCAL, "local" }, \ + { MNT_NOATIME, "noatime" }, \ + { MNT_NOEXEC, "noexec" }, \ + { MNT_NOSUID, "nosuid" }, \ + { MNT_NOSYMFOLLOW, "nosymfollow" }, \ + { MNT_QUOTA, "with quotas" }, \ + { MNT_RDONLY, "read-only" }, \ + { MNT_SYNCHRONOUS, "synchronous" }, \ + { MNT_UNION, "union" }, \ + { MNT_NOCLUSTERR, "noclusterr" }, \ + { MNT_NOCLUSTERW, "noclusterw" }, \ + { MNT_SUIDDIR, "suiddir" }, \ + { MNT_SOFTDEP, "soft-updates" }, \ + { MNT_SUJ, "journaled soft-updates" }, \ + { MNT_MULTILABEL, "multilabel" }, \ + { MNT_ACLS, "acls" }, \ + { MNT_NFS4ACLS, "nfsv4acls" }, \ + { MNT_GJOURNAL, "gjournal" }, \ + { MNT_AUTOMOUNTED, "automounted" }, \ + { MNT_VERIFIED, "verified" }, \ + { MNT_UNTRUSTED, "untrusted" }, \ + { MNT_NOCOVER, "nocover" }, \ + { MNT_EMPTYDIR, "emptydir" }, \ + { MNT_UPDATE, "update" }, \ + { MNT_DELEXPORT, "delexport" }, \ + { MNT_RELOAD, "reload" }, \ + { MNT_FORCE, "force" }, \ + { MNT_SNAPSHOT, "snapshot" }, \ + { 0, NULL } +#endif + /* * User specifiable flags, stored in mnt_flag. */ @@ -326,6 +365,9 @@ void __mnt_vnode_markerfree_lazy(struct vnode #define MNT_EXPORTANON 0x0000000000000400ULL /* anon uid mapping for all */ #define MNT_EXKERB 0x0000000000000800ULL /* exported with Kerberos */ #define MNT_EXPUBLIC 0x0000000020000000ULL /* public export (WebNFS) */ +#define MNT_EXTLS 0x0000004000000000ULL /* require TLS */ +#define MNT_EXTLSCERT 0x0000008000000000ULL /* require TLS with client cert */ +#define MNT_EXTLSCERTUSER 0x0000010000000000ULL /* require TLS with user cert */ /* * Flags set by internal operations, @@ -364,23 +406,6 @@ void __mnt_vnode_markerfree_lazy(struct vnode MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR | \ MNT_ACLS | MNT_USER | MNT_NFS4ACLS | \ MNT_AUTOMOUNTED | MNT_UNTRUSTED) - -/* - * Export flags that are only set/used in the ex_flags field and - * not in mnt_flag. Since some are defined as MNT_EXxxx above, - * these ones are just redefined here. - * MNT_EXPORTED must remain and be set/cleared in mnt_flag. - * The others defined as MNT_xxx should probably remain for - * compatibility with old versions of mountd, etc. - */ -#define MNTEX_TLS 0x0000000000000001ULL /* TLS RPC required */ -#define MNTEX_TLSCERT 0x0000000000000002ULL /* verified cert req */ -#define MNTEX_TLSCERTUSER 0x0000000000000004ULL /* user cert req */ -#define MNTEX_EXPORTED MNT_EXPORTED /* filesystem exported */ -#define MNTEX_RDONLY MNT_EXRDONLY /* exported read only */ -#define MNTEX_EXPORTANON MNT_EXPORTANON /* anon uid mapping for all */ -#define MNTEX_KERB MNT_EXKERB /* exported with Kerberos */ -#define MNTEX_PUBLIC MNT_EXPUBLIC /* public export (WebNFS) */ /* * External filesystem command modifier flags. Modified: projects/nfs-over-tls/usr.sbin/mountd/mountd.c ============================================================================== --- projects/nfs-over-tls/usr.sbin/mountd/mountd.c Sat Aug 22 21:32:11 2020 (r364495) +++ projects/nfs-over-tls/usr.sbin/mountd/mountd.c Sat Aug 22 22:56:50 2020 (r364496) @@ -48,6 +48,7 @@ static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5 __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -112,6 +113,15 @@ struct dirlist { #define DP_DEFSET 0x1 #define DP_HOSTSET 0x2 +/* + * maproot/mapall credentials. + */ +struct expcred { + uid_t cr_uid; + int cr_ngroups; + gid_t cr_groups[NGROUPS_MAX + 1]; +}; + struct exportlist { struct dirlist *ex_dirl; struct dirlist *ex_defdir; @@ -120,8 +130,8 @@ struct exportlist { fsid_t ex_fs; char *ex_fsdir; char *ex_indexfile; - struct xucred ex_defanon; - int ex_defexflags; + struct expcred ex_defanon; + uint64_t ex_defexflags; int ex_numsecflavors; int ex_secflavors[MAXSECFLAVORS]; int ex_defnumsecflavors; @@ -152,8 +162,8 @@ struct grouplist { int gr_type; union grouptypes gr_ptr; struct grouplist *gr_next; - struct xucred gr_anon; - int gr_exflags; + struct expcred gr_anon; + uint64_t gr_exflags; int gr_flag; int gr_numsecflavors; int gr_secflavors[MAXSECFLAVORS]; @@ -184,11 +194,17 @@ struct fhreturn { #define GETPORT_MAXTRY 20 /* Max tries to get a port # */ +/* + * How long to delay a reload of exports when there are RPC request(s) + * to process, in usec. Must be less than 1second. + */ +#define RELOADDELAY 250000 + /* Global defs */ static char *add_expdir(struct dirlist **, char *, int); static void add_dlist(struct dirlist **, struct dirlist *, struct grouplist *, int, struct exportlist *, - struct xucred *, int); + struct expcred *, uint64_t); static void add_mlist(char *, char *); static int check_dirpath(char *); static int check_options(struct dirlist *); @@ -202,10 +218,10 @@ static void clearout_service(void); static void del_mlist(char *hostp, char *dirp); static struct dirlist *dirp_search(struct dirlist *, char *); static int do_export_mount(struct exportlist *, struct statfs *); -static int do_mount(struct exportlist *, struct grouplist *, int, - struct xucred *, char *, int, struct statfs *, int, int *); +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 *, int *, struct xucred *); + struct grouplist *, int *, uint64_t *, struct expcred *); static struct exportlist *ex_search(fsid_t *, struct exportlisthead *); static struct exportlist *get_exp(void); static void free_dir(struct dirlist *); @@ -220,7 +236,7 @@ static void free_exports(struct exportlisthead *); static void read_exportfile(int); static int compare_nmount_exportlist(struct iovec *, int, char *); static int compare_export(struct exportlist *, struct exportlist *); -static int compare_cred(struct xucred *, struct xucred *); +static int compare_cred(struct expcred *, struct expcred *); static int compare_secflavor(int *, int *, int); static void delete_export(struct iovec *, int, struct statfs *, char *); static int get_host(char *, struct grouplist *, struct grouplist *); @@ -231,13 +247,13 @@ static int get_net(char *, struct netmsk *, int); static void getexp_err(struct exportlist *, struct grouplist *, const char *); static struct grouplist *get_grp(void); static void hang_dirp(struct dirlist *, struct grouplist *, - struct exportlist *, int, struct xucred *, int); + struct exportlist *, int, struct expcred *, uint64_t); static void huphandler(int sig); static int makemask(struct sockaddr_storage *ssp, int bitlen); static void mntsrv(struct svc_req *, SVCXPRT *); static void nextfield(char **, char **); static void out_of_mem(void); -static void parsecred(char *, struct xucred *); +static void parsecred(char *, struct expcred *); static int parsesec(char *, struct exportlist *); static int put_exlist(struct dirlist *, XDR *, struct dirlist *, int *, int); @@ -253,6 +269,7 @@ static int xdr_explist_common(XDR *, caddr_t, int); static int xdr_fhs(XDR *, caddr_t); static int xdr_mlist(XDR *, caddr_t); static void terminate(int); +static void cp_cred(struct expcred *, struct expcred *); #define EXPHASH(f) (fnv_32_buf((f), sizeof(fsid_t), 0) % exphashsize) static struct exportlisthead *exphead = NULL; @@ -262,13 +279,6 @@ static SLIST_HEAD(, mountlist) mlhead = SLIST_HEAD_INI static char *exnames_default[2] = { _PATH_EXPORTS, NULL }; static char **exnames; static char **hosts = NULL; -static struct xucred def_anon = { - XUCRED_VERSION, - (uid_t)65534, - 1, - { (gid_t)65533 }, - { NULL } -}; static int force_v2 = 0; static int resvport_only = 1; static int nhosts = 0; @@ -410,6 +420,10 @@ main(int argc, char **argv) int maxrec = RPC_MAXDATASIZE; int attempt_cnt, port_len, port_pos, ret; char **port_list; + uint64_t curtime, nexttime; + struct timeval tv; + struct timespec tp; + sigset_t sighup_mask; /* Check that another mountd isn't already running. */ pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid); @@ -665,19 +679,49 @@ main(int argc, char **argv) } /* Expand svc_run() here so that we can call get_exportlist(). */ + curtime = nexttime = 0; + sigemptyset(&sighup_mask); + sigaddset(&sighup_mask, SIGHUP); for (;;) { - if (got_sighup) { - get_exportlist(1); + clock_gettime(CLOCK_MONOTONIC, &tp); + curtime = tp.tv_sec; + curtime = curtime * 1000000 + tp.tv_nsec / 1000; + sigprocmask(SIG_BLOCK, &sighup_mask, NULL); + if (got_sighup && curtime >= nexttime) { got_sighup = 0; - } + sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); + get_exportlist(1); + clock_gettime(CLOCK_MONOTONIC, &tp); + nexttime = tp.tv_sec; + nexttime = nexttime * 1000000 + tp.tv_nsec / 1000 + + RELOADDELAY; + } else + sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); + + /* + * If a reload is pending, poll for received request(s), + * otherwise set a RELOADDELAY timeout, since a SIGHUP + * could be processed between the got_sighup test and + * the select() system call. + */ + tv.tv_sec = 0; + if (got_sighup) + tv.tv_usec = 0; + else + tv.tv_usec = RELOADDELAY; readfds = svc_fdset; - switch (select(svc_maxfd + 1, &readfds, NULL, NULL, NULL)) { + switch (select(svc_maxfd + 1, &readfds, NULL, NULL, &tv)) { case -1: - if (errno == EINTR) - continue; + if (errno == EINTR) { + /* Allow a reload now. */ + nexttime = 0; + continue; + } syslog(LOG_ERR, "mountd died: select: %m"); exit(1); case 0: + /* Allow a reload now. */ + nexttime = 0; continue; default: svc_getreqset(&readfds); @@ -1047,7 +1091,8 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp) struct sockaddr *saddr; u_short sport; char rpcpath[MNTPATHLEN + 1], dirpath[MAXPATHLEN]; - int bad = 0, defset, hostset; + int defset, hostset; + long bad = 0; sigset_t sighup_mask; int numsecflavors, *secflavorsp; @@ -1463,9 +1508,10 @@ get_exportlist_one(int passno) struct grouplist *grp, *tgrp, *savgrp; struct dirlist *dirhead; struct statfs fsb; - struct xucred anon; + struct expcred anon; char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; - int len, has_host, exflags, got_nondir, dirplen, netgrp; + int len, has_host, got_nondir, dirplen, netgrp; + uint64_t exflags; v4root_phase = 0; dirhead = (struct dirlist *)NULL; @@ -1481,8 +1527,10 @@ get_exportlist_one(int passno) * Set defaults. */ has_host = FALSE; - anon = def_anon; - exflags = MNTEX_EXPORTED; + anon.cr_uid = UID_NOBODY; + anon.cr_ngroups = 1; + anon.cr_groups[0] = GID_NOGROUP; + exflags = MNT_EXPORTED; got_nondir = 0; opt_flags = 0; ep = (struct exportlist *)NULL; @@ -1568,10 +1616,8 @@ get_exportlist_one(int passno) ep = get_exp(); } else { if (ep) { - if (ep->ex_fs.val[0] != - fsb.f_fsid.val[0] || - ep->ex_fs.val[1] != - fsb.f_fsid.val[1]) { + if (fsidcmp(&ep->ex_fs, &fsb.f_fsid) + != 0) { getexp_err(ep, tgrp, "fsid mismatch"); goto nextline; @@ -1700,7 +1746,7 @@ get_exportlist_one(int passno) grp = tgrp; do { grp->gr_exflags = exflags; - grp->gr_anon = anon; + cp_cred(&grp->gr_anon, &anon); if (v4root_phase == 2 && passno == 0) LOGDEBUG("do_mount v4root"); if (passno == 0 && do_mount(ep, grp, exflags, &anon, @@ -1840,7 +1886,7 @@ get_exportlist(int passno) */ bzero(&eargs, sizeof (eargs)); eargs.export.ex_flags = MNT_DELEXPORT; - if (nfssvc(NFSSVC_V4ROOTEXPORT, (caddr_t)&eargs) < 0 && + if (nfssvc(NFSSVC_V4ROOTEXPORT | NFSSVC_NEWSTRUCT, (caddr_t)&eargs) < 0 && errno != ENOENT) syslog(LOG_ERR, "Can't delete exports for V4:"); @@ -1868,7 +1914,7 @@ get_exportlist(int passno) LOGDEBUG("doing passno=0"); /* * Clear flag that notes if a public fh has been exported. - * It is set by do_mount() if MNTEX_PUBLIC is set for the entry. + * It is set by do_mount() if MNT_EXPUBLIC is set for the entry. */ has_publicfh = 0; @@ -2088,8 +2134,7 @@ compare_nmount_exportlist(struct iovec *iov, int iovle if ((oep->ex_flag & EX_DONE) == 0) { LOGDEBUG("not done delete=%s", oep->ex_fsdir); if (statfs(oep->ex_fsdir, &ofs) >= 0 && - oep->ex_fs.val[0] == ofs.f_fsid.val[0] && - oep->ex_fs.val[1] == ofs.f_fsid.val[1]) { + fsidcmp(&oep->ex_fs, &ofs.f_fsid) == 0) { LOGDEBUG("do delete"); /* * Clear has_publicfh if if was set @@ -2220,10 +2265,10 @@ compare_export(struct exportlist *ep, struct exportlis } while (0) /* - * Compare to struct xucred's. Return 0 if the same and 1 otherwise. + * Compare two struct expcred's. Return 0 if the same and 1 otherwise. */ static int -compare_cred(struct xucred *cr0, struct xucred *cr1) +compare_cred(struct expcred *cr0, struct expcred *cr1) { if (cr0->cr_uid != cr1->cr_uid || cr0->cr_ngroups != cr1->cr_ngroups) @@ -2353,8 +2398,7 @@ ex_search(fsid_t *fsid, struct exportlisthead *exhp) i = EXPHASH(fsid); SLIST_FOREACH(ep, &exhp[i], entries) { - if (ep->ex_fs.val[0] == fsid->val[0] && - ep->ex_fs.val[1] == fsid->val[1]) + if (fsidcmp(&ep->ex_fs, fsid) == 0) return (ep); } @@ -2389,7 +2433,7 @@ add_expdir(struct dirlist **dpp, char *cp, int len) */ static void hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep, - int flags, struct xucred *anoncrp, int exflags) + int flags, struct expcred *anoncrp, uint64_t exflags) { struct hostlist *hp; struct dirlist *dp2; @@ -2407,7 +2451,7 @@ hang_dirp(struct dirlist *dp, struct grouplist *grp, s if (ep->ex_numsecflavors > 0) memcpy(ep->ex_defsecflavors, ep->ex_secflavors, sizeof(ep->ex_secflavors)); - ep->ex_defanon = *anoncrp; + cp_cred(&ep->ex_defanon, anoncrp); ep->ex_defexflags = exflags; } else while (grp) { hp = get_ht(); @@ -2441,7 +2485,8 @@ hang_dirp(struct dirlist *dp, struct grouplist *grp, s */ static void add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp, - int flags, struct exportlist *ep, struct xucred *anoncrp, int exflags) + int flags, struct exportlist *ep, struct expcred *anoncrp, + uint64_t exflags) { struct dirlist *dp; struct hostlist *hp; @@ -2490,7 +2535,7 @@ add_dlist(struct dirlist **dpp, struct dirlist *newdp, if (ep->ex_numsecflavors > 0) memcpy(ep->ex_defsecflavors, ep->ex_secflavors, sizeof(ep->ex_secflavors)); - ep->ex_defanon = *anoncrp; + cp_cred(&ep->ex_defanon, anoncrp); ep->ex_defexflags = exflags; } } @@ -2662,7 +2707,7 @@ parsesec(char *seclist, struct exportlist *ep) */ static int do_opt(char **cpp, char **endcpp, struct exportlist *ep, struct grouplist *grp, - int *has_hostp, int *exflagsp, struct xucred *cr) + int *has_hostp, uint64_t *exflagsp, struct expcred *cr) { char *cpoptarg, *cpoptend; char *cp, *endcp, *cpopt, savedc, savedc2; @@ -2697,14 +2742,14 @@ do_opt(char **cpp, char **endcpp, struct exportlist *e } } if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { - *exflagsp |= MNTEX_RDONLY; + *exflagsp |= MNT_EXRDONLY; } else if (cpoptarg && (!strcmp(cpopt, "maproot") || !(allflag = strcmp(cpopt, "mapall")) || !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) { usedarg++; parsecred(cpoptarg, cr); if (allflag == 0) { - *exflagsp |= MNTEX_EXPORTANON; + *exflagsp |= MNT_EXPORTANON; opt_flags |= OP_MAPALL; } else opt_flags |= OP_MAPROOT; @@ -2737,9 +2782,9 @@ do_opt(char **cpp, char **endcpp, struct exportlist *e } else if (!strcmp(cpopt, "alldirs")) { opt_flags |= OP_ALLDIRS; } else if (!strcmp(cpopt, "public")) { - *exflagsp |= MNTEX_PUBLIC; + *exflagsp |= MNT_EXPUBLIC; } else if (!strcmp(cpopt, "webnfs")) { - *exflagsp |= (MNTEX_PUBLIC|MNTEX_RDONLY|MNTEX_EXPORTANON); + *exflagsp |= (MNT_EXPUBLIC|MNT_EXRDONLY|MNT_EXPORTANON); opt_flags |= OP_MAPALL; } else if (cpoptarg && !strcmp(cpopt, "index")) { ep->ex_indexfile = strdup(cpoptarg); @@ -2751,11 +2796,12 @@ do_opt(char **cpp, char **endcpp, struct exportlist *e opt_flags |= OP_SEC; usedarg++; } else if (!strcmp(cpopt, "tls")) { - *exflagsp |= MNTEX_TLS; + *exflagsp |= MNT_EXTLS; } else if (!strcmp(cpopt, "tlscert")) { - *exflagsp |= (MNTEX_TLS | MNTEX_TLSCERT); + *exflagsp |= (MNT_EXTLS | MNT_EXTLSCERT); } else if (!strcmp(cpopt, "tlscertuser")) { - *exflagsp |= (MNTEX_TLS | MNTEX_TLSCERT | MNTEX_TLSCERTUSER); + *exflagsp |= (MNT_EXTLS | MNT_EXTLSCERT | + MNT_EXTLSCERTUSER); } else { syslog(LOG_ERR, "bad opt %s", cpopt); return (1); @@ -2930,7 +2976,7 @@ do_export_mount(struct exportlist *ep, struct statfs * defgrp.gr_type = GT_DEFAULT; defgrp.gr_next = NULL; /* We have an entry for all other hosts/nets. */ - LOGDEBUG("ex_defexflags=0x%x", ep->ex_defexflags); + LOGDEBUG("ex_defexflags=0x%jx", (uintmax_t)ep->ex_defexflags); ret = do_mount(ep, &defgrp, ep->ex_defexflags, &ep->ex_defanon, ep->ex_fsdir, dirlen, fsp, ep->ex_defnumsecflavors, ep->ex_defsecflavors); @@ -2941,8 +2987,8 @@ do_export_mount(struct exportlist *ep, struct statfs * /* Do a mount for each group. */ grp = ep->ex_grphead; while (grp != NULL) { - LOGDEBUG("do mount gr_type=0x%x gr_exflags=0x%x", - grp->gr_type, grp->gr_exflags); + LOGDEBUG("do mount gr_type=0x%x gr_exflags=0x%jx", + grp->gr_type, (uintmax_t)grp->gr_exflags); ret = do_mount(ep, grp, grp->gr_exflags, &grp->gr_anon, ep->ex_fsdir, dirlen, fsp, grp->gr_numsecflavors, grp->gr_secflavors); @@ -2958,8 +3004,8 @@ do_export_mount(struct exportlist *ep, struct statfs * * the kernel. */ static int -do_mount(struct exportlist *ep, struct grouplist *grp, int exflags, - struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb, +do_mount(struct exportlist *ep, struct grouplist *grp, uint64_t exflags, + struct expcred *anoncrp, char *dirp, int dirplen, struct statfs *fsb, int numsecflavors, int *secflavors) { struct statfs fsb1; @@ -2985,8 +3031,14 @@ do_mount(struct exportlist *ep, struct grouplist *grp, bzero(eap, sizeof (struct export_args)); bzero(errmsg, sizeof(errmsg)); eap->ex_flags = exflags; - eap->ex_anon = *anoncrp; - LOGDEBUG("do_mount exflags=0x%x", exflags); + eap->ex_uid = anoncrp->cr_uid; + eap->ex_ngroups = anoncrp->cr_ngroups; + if (eap->ex_ngroups > 0) { + eap->ex_groups = malloc(eap->ex_ngroups * sizeof(gid_t)); + memcpy(eap->ex_groups, anoncrp->cr_groups, eap->ex_ngroups * + sizeof(gid_t)); + } + LOGDEBUG("do_mount exflags=0x%jx", (uintmax_t)exflags); eap->ex_indexfile = ep->ex_indexfile; if (grp->gr_type == GT_HOST) ai = grp->gr_ptr.gt_addrinfo; @@ -3056,9 +3108,11 @@ do_mount(struct exportlist *ep, struct grouplist *grp, */ if (v4root_phase == 2) { nfsea.fspec = v4root_dirpath; - if (nfssvc(NFSSVC_V4ROOTEXPORT, (caddr_t)&nfsea) < 0) { + if (nfssvc(NFSSVC_V4ROOTEXPORT | NFSSVC_NEWSTRUCT, + (caddr_t)&nfsea) < 0) { syslog(LOG_ERR, "Exporting V4: failed"); - return (2); + ret = 2; + goto error_exit; } } else { /* @@ -3109,9 +3163,9 @@ do_mount(struct exportlist *ep, struct grouplist *grp, goto error_exit; } /* back up over the last component */ - while (*cp == '/' && cp > dirp) + while (cp > dirp && *cp == '/') cp--; - while (*(cp - 1) != '/' && cp > dirp) + while (cp > dirp && *(cp - 1) != '/') cp--; if (cp == dirp) { if (debug) @@ -3128,8 +3182,7 @@ do_mount(struct exportlist *ep, struct grouplist *grp, * filesystem. */ if (statfs(dirp, &fsb1) != 0 || - bcmp(&fsb1.f_fsid, &fsb->f_fsid, - sizeof (fsb1.f_fsid)) != 0) { + fsidcmp(&fsb1.f_fsid, &fsb->f_fsid) != 0) { *cp = savedc; syslog(LOG_ERR, "can't export %s %s", dirp, @@ -3145,7 +3198,7 @@ do_mount(struct exportlist *ep, struct grouplist *grp, * If this is the public directory, get the file handle * and load it into the kernel via the nfssvc() syscall. */ - if ((exflags & MNTEX_PUBLIC) != 0) { + if ((exflags & MNT_EXPUBLIC) != 0) { fhandle_t fh; char *public_name; @@ -3174,6 +3227,7 @@ skip: if (cp) *cp = savedc; error_exit: + free(eap->ex_groups); /* free strings allocated by strdup() in getmntopts.c */ if (iov != NULL) { free(iov[0].iov_base); /* fstype */ @@ -3400,22 +3454,19 @@ get_line(void) * Parse a description of a credential. */ static void -parsecred(char *namelist, struct xucred *cr) +parsecred(char *namelist, struct expcred *cr) { char *name; int cnt; char *names; struct passwd *pw; struct group *gr; - gid_t groups[XU_NGROUPS + 1]; - int ngroups; - cr->cr_version = XUCRED_VERSION; /* * Set up the unprivileged user. */ - cr->cr_uid = 65534; - cr->cr_groups[0] = 65533; + cr->cr_uid = UID_NOBODY; + cr->cr_groups[0] = GID_NOGROUP; cr->cr_ngroups = 1; /* * Get the user's password table entry. @@ -3436,19 +3487,24 @@ parsecred(char *namelist, struct xucred *cr) return; } cr->cr_uid = pw->pw_uid; - ngroups = XU_NGROUPS + 1; - if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) { + cr->cr_ngroups = NGROUPS_MAX + 1; + if (getgrouplist(pw->pw_name, pw->pw_gid, cr->cr_groups, + &cr->cr_ngroups)) { syslog(LOG_ERR, "too many groups"); - ngroups = XU_NGROUPS + 1; + cr->cr_ngroups = NGROUPS_MAX + 1; } /* * Compress out duplicate. */ - cr->cr_ngroups = ngroups - 1; - cr->cr_groups[0] = groups[0]; - for (cnt = 2; cnt < ngroups; cnt++) - cr->cr_groups[cnt - 1] = groups[cnt]; + if (cr->cr_ngroups > 1 && cr->cr_groups[0] == + cr->cr_groups[1]) { + for (cnt = 2; cnt < cr->cr_ngroups; cnt++) + cr->cr_groups[cnt - 1] = cr->cr_groups[cnt]; + cr->cr_ngroups--; + } + if (cr->cr_ngroups > NGROUPS_MAX) + cr->cr_ngroups = NGROUPS_MAX; return; } /* @@ -3464,7 +3520,7 @@ parsecred(char *namelist, struct xucred *cr) return; } cr->cr_ngroups = 0; - while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) { + while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS_MAX) { name = strsep_quote(&names, ":"); if (isdigit(*name) || *name == '-') { cr->cr_groups[cr->cr_ngroups++] = atoi(name); @@ -3476,7 +3532,7 @@ parsecred(char *namelist, struct xucred *cr) cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; } } - if (names != NULL && *names != '\0' && cr->cr_ngroups == XU_NGROUPS) + if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS_MAX) syslog(LOG_ERR, "too many groups"); } @@ -3796,4 +3852,14 @@ terminate(int sig __unused) rpcb_unset(MOUNTPROG, MOUNTVERS, NULL); rpcb_unset(MOUNTPROG, MOUNTVERS3, NULL); exit (0); +} + +static void +cp_cred(struct expcred *outcr, struct expcred *incr) +{ + + outcr->cr_uid = incr->cr_uid; + outcr->cr_ngroups = incr->cr_ngroups; + memcpy(outcr->cr_groups, incr->cr_groups, incr->cr_ngroups * + sizeof(gid_t)); }