Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c @@ -101,8 +101,8 @@ static int zfs_statfs(vfs_t *vfsp, struct statfs *statp); static int zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp); static int zfs_sync(vfs_t *vfsp, int waitfor); -static int zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, int *extflagsp, - struct ucred **credanonp, int *numsecflavors, int **secflavors); +static int zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, uint64_t *extflagsp, + struct ucred **credanonp, int *numsecflavors, int *secflavors); static int zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp); static void zfs_objset_close(zfsvfs_t *zfsvfs); static void zfs_freevfs(vfs_t *vfsp); @@ -2268,8 +2268,8 @@ } static int -zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, int *extflagsp, - struct ucred **credanonp, int *numsecflavors, int **secflavors) +zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, uint64_t *extflagsp, + struct ucred **credanonp, int *numsecflavors, int *secflavors) { zfsvfs_t *zfsvfs = vfsp->vfs_data; Index: sys/fs/cd9660/cd9660_vfsops.c =================================================================== --- sys/fs/cd9660/cd9660_vfsops.c +++ sys/fs/cd9660/cd9660_vfsops.c @@ -101,7 +101,7 @@ cd9660_cmount(struct mntarg *ma, void *data, uint64_t flags) { struct iso_args args; - struct export_args exp; + struct o2export_args exp; int error; error = copyin(data, &args, sizeof args); Index: sys/fs/msdosfs/msdosfs_vfsops.c =================================================================== --- sys/fs/msdosfs/msdosfs_vfsops.c +++ sys/fs/msdosfs/msdosfs_vfsops.c @@ -190,7 +190,7 @@ msdosfs_cmount(struct mntarg *ma, void *data, uint64_t flags) { struct msdosfs_args args; - struct export_args exp; + struct o2export_args exp; int error; if (data == NULL) Index: sys/fs/nfs/nfsdport.h =================================================================== --- sys/fs/nfs/nfsdport.h +++ sys/fs/nfs/nfsdport.h @@ -54,7 +54,7 @@ * needs to be returned by nfsd_fhtovp(). */ struct nfsexstuff { - int nes_exflag; /* export flags */ + uint64_t nes_exflag; /* export flags */ int nes_numsecflavor; /* # of security flavors */ int nes_secflavors[MAXSECFLAVORS]; /* and the flavors */ }; Index: sys/fs/nfs/nfsport.h =================================================================== --- sys/fs/nfs/nfsport.h +++ sys/fs/nfs/nfsport.h @@ -1081,6 +1081,11 @@ struct export_args export; }; +struct nfsex_oldargs { + char *fspec; + struct o2export_args export; +}; + /* * These export flags should be defined, but there are no bits left. * Maybe a separate mnt_exflag field could be added or the mnt_flag Index: sys/fs/nfsserver/nfs_nfsdport.c =================================================================== --- sys/fs/nfsserver/nfs_nfsdport.c +++ sys/fs/nfsserver/nfs_nfsdport.c @@ -3056,10 +3056,10 @@ nfsvno_checkexp(struct mount *mp, struct sockaddr *nam, struct nfsexstuff *exp, struct ucred **credp) { - int i, error, *secflavors; + int i, error, secflavors[MAXSECFLAVORS]; error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, - &exp->nes_numsecflavor, &secflavors); + &exp->nes_numsecflavor, secflavors); if (error) { if (nfs_rootfhset) { exp->nes_exflag = 0; @@ -3088,7 +3088,7 @@ int lktype, struct vnode **vpp, struct nfsexstuff *exp, struct ucred **credp) { - int i, error, *secflavors; + int i, error, secflavors[MAXSECFLAVORS]; *credp = NULL; exp->nes_numsecflavor = 0; @@ -3098,7 +3098,7 @@ error = ESTALE; if (nam && !error) { error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, - &exp->nes_numsecflavor, &secflavors); + &exp->nes_numsecflavor, secflavors); if (error) { if (nfs_rootfhset) { exp->nes_exflag = 0; @@ -3415,10 +3415,11 @@ nfsvno_v4rootexport(struct nfsrv_descript *nd) { struct ucred *credanon; - int exflags, error = 0, numsecflavor, *secflavors, i; + int error = 0, numsecflavor, secflavors[MAXSECFLAVORS], i; + uint64_t exflags; error = vfs_stdcheckexp(&nfsv4root_mnt, nd->nd_nam, &exflags, - &credanon, &numsecflavor, &secflavors); + &credanon, &numsecflavor, secflavors); if (error) { error = NFSERR_PROGUNAVAIL; goto out; @@ -3656,8 +3657,9 @@ nfssvc_srvcall(struct thread *p, struct nfssvc_args *uap, struct ucred *cred) { struct nfsex_args export; + struct nfsex_oldargs oexp; struct file *fp = NULL; - int stablefd, len; + int stablefd, i, len; struct nfsd_clid adminrevoke; struct nfsd_dumplist dumplist; struct nfsd_dumpclients *dumpclients; @@ -3667,6 +3669,7 @@ vnode_t vp; int error = EINVAL, igotlock; struct proc *procp; + gid_t *grps; static int suspend_nfsd = 0; if (uap->flag & NFSSVC_PUBLICFH) { @@ -3676,11 +3679,65 @@ &nfs_pubfh.nfsrvfh_data, sizeof (fhandle_t)); if (!error) nfs_pubfhset = 1; - } else if (uap->flag & NFSSVC_V4ROOTEXPORT) { + } else if ((uap->flag & (NFSSVC_V4ROOTEXPORT | NFSSVC_NEWSTRUCT)) == + (NFSSVC_V4ROOTEXPORT | NFSSVC_NEWSTRUCT)) { error = copyin(uap->argp,(caddr_t)&export, sizeof (struct nfsex_args)); - if (!error) + if (!error) { + if (export.export.ex_ngroups > 0) { + if (export.export.ex_ngroups > NGROUPS_MAX) + export.export.ex_ngroups = NGROUPS_MAX; + grps = malloc(export.export.ex_ngroups * + sizeof(gid_t), M_TEMP, M_WAITOK); + error = copyin(export.export.ex_groups, grps, + export.export.ex_ngroups * sizeof(gid_t)); + export.export.ex_groups = grps; + } else { + export.export.ex_ngroups = 0; + export.export.ex_groups = NULL; + } + if (!error) + error = nfsrv_v4rootexport(&export, cred, p); + free(export.export.ex_groups, M_TEMP); + } + } else if ((uap->flag & (NFSSVC_V4ROOTEXPORT | NFSSVC_NEWSTRUCT)) == + NFSSVC_V4ROOTEXPORT) { + error = copyin(uap->argp,(caddr_t)&oexp, + sizeof (struct nfsex_oldargs)); + if (!error) { + memset(&export.export, 0, sizeof(export.export)); + export.export.ex_flags = (uint64_t)oexp.export.ex_flags; + export.export.ex_root = oexp.export.ex_root; + export.export.ex_uid = oexp.export.ex_anon.cr_uid; + export.export.ex_ngroups = + oexp.export.ex_anon.cr_ngroups; + if (export.export.ex_ngroups > 0) { + if (export.export.ex_ngroups > XU_NGROUPS) + export.export.ex_ngroups = XU_NGROUPS; + export.export.ex_groups = malloc( + export.export.ex_ngroups * sizeof(gid_t), + M_TEMP, M_WAITOK); + for (i = 0; i < export.export.ex_ngroups; i++) + export.export.ex_groups[i] = + oexp.export.ex_anon.cr_groups[i]; + } else { + export.export.ex_ngroups = 0; + export.export.ex_groups = NULL; + } + export.export.ex_addr = oexp.export.ex_addr; + export.export.ex_addrlen = oexp.export.ex_addrlen; + export.export.ex_mask = oexp.export.ex_mask; + export.export.ex_masklen = oexp.export.ex_masklen; + export.export.ex_indexfile = oexp.export.ex_indexfile; + export.export.ex_numsecflavors = + oexp.export.ex_numsecflavors; + for (i = 0; i < export.export.ex_numsecflavors; i++) + export.export.ex_secflavors[i] = + oexp.export.ex_secflavors[i]; + export.fspec = oexp.fspec; error = nfsrv_v4rootexport(&export, cred, p); + free(export.export.ex_groups, M_TEMP); + } } else if (uap->flag & NFSSVC_NOPUBLICFH) { nfs_pubfhset = 0; error = 0; Index: sys/fs/unionfs/union_vfsops.c =================================================================== --- sys/fs/unionfs/union_vfsops.c +++ sys/fs/unionfs/union_vfsops.c @@ -466,8 +466,8 @@ } static int -unionfs_checkexp(struct mount *mp, struct sockaddr *nam, int *extflagsp, - struct ucred **credanonp, int *numsecflavors, int **secflavors) +unionfs_checkexp(struct mount *mp, struct sockaddr *nam, uint64_t *extflagsp, + struct ucred **credanonp, int *numsecflavors, int *secflavors) { return (EOPNOTSUPP); } Index: sys/kern/vfs_export.c =================================================================== --- sys/kern/vfs_export.c +++ sys/kern/vfs_export.c @@ -79,7 +79,7 @@ */ struct netcred { struct radix_node netc_rnodes[2]; - int netc_exflags; + uint64_t netc_exflags; struct ucred *netc_anon; int netc_numsecflavors; int netc_secflavors[MAXSECFLAVORS]; @@ -118,18 +118,12 @@ ("%s: numsecflavors >= MAXSECFLAVORS", __func__)); /* - * XXX: This routine converts from a `struct xucred' - * (argp->ex_anon) to a `struct ucred' (np->netc_anon). This + * XXX: This routine converts from a uid plus gid list + * to a `struct ucred' (np->netc_anon). This * operation is questionable; for example, what should be done * with fields like cr_uidinfo and cr_prison? Currently, this * routine does not touch them (leaves them as NULL). */ - if (argp->ex_anon.cr_version != XUCRED_VERSION) { - vfs_mount_error(mp, "ex_anon.cr_version: %d != %d", - argp->ex_anon.cr_version, XUCRED_VERSION); - return (EINVAL); - } - if (argp->ex_addrlen == 0) { if (mp->mnt_flag & MNT_DEFEXPORTED) { vfs_mount_error(mp, @@ -139,9 +133,9 @@ np = &nep->ne_defexported; np->netc_exflags = argp->ex_flags; np->netc_anon = crget(); - np->netc_anon->cr_uid = argp->ex_anon.cr_uid; - crsetgroups(np->netc_anon, argp->ex_anon.cr_ngroups, - argp->ex_anon.cr_groups); + np->netc_anon->cr_uid = argp->ex_uid; + crsetgroups(np->netc_anon, argp->ex_ngroups, + argp->ex_groups); np->netc_anon->cr_prison = &prison0; prison_hold(np->netc_anon->cr_prison); np->netc_numsecflavors = argp->ex_numsecflavors; @@ -218,9 +212,9 @@ } np->netc_exflags = argp->ex_flags; np->netc_anon = crget(); - np->netc_anon->cr_uid = argp->ex_anon.cr_uid; - crsetgroups(np->netc_anon, argp->ex_anon.cr_ngroups, - argp->ex_anon.cr_groups); + np->netc_anon->cr_uid = argp->ex_uid; + crsetgroups(np->netc_anon, argp->ex_ngroups, + argp->ex_groups); np->netc_anon->cr_prison = &prison0; prison_hold(np->netc_anon->cr_prison); np->netc_numsecflavors = argp->ex_numsecflavors; @@ -512,8 +506,8 @@ */ int -vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp, - struct ucred **credanonp, int *numsecflavors, int **secflavors) +vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, uint64_t *extflagsp, + struct ucred **credanonp, int *numsecflavors, int *secflavors) { struct netcred *np; @@ -534,8 +528,9 @@ KASSERT(*numsecflavors < MAXSECFLAVORS, ("%s: numsecflavors >= MAXSECFLAVORS", __func__)); } - if (secflavors) - *secflavors = np->netc_secflavors; + if (secflavors && np->netc_numsecflavors > 0) + memcpy(secflavors, np->netc_secflavors, np->netc_numsecflavors * + sizeof(int)); lockmgr(&mp->mnt_explock, LK_RELEASE, NULL); return (0); } Index: sys/kern/vfs_init.c =================================================================== --- sys/kern/vfs_init.c +++ sys/kern/vfs_init.c @@ -268,8 +268,8 @@ } static int -vfs_checkexp_sigdefer(struct mount *mp, struct sockaddr *nam, int *exflg, - struct ucred **credp, int *numsecflavors, int **secflavors) +vfs_checkexp_sigdefer(struct mount *mp, struct sockaddr *nam, uint64_t *exflg, + struct ucred **credp, int *numsecflavors, int *secflavors) { int prev_stops, rc; Index: sys/kern/vfs_mount.c =================================================================== --- sys/kern/vfs_mount.c +++ sys/kern/vfs_mount.c @@ -1038,11 +1038,13 @@ ) { struct export_args export; + struct o2export_args o2export; struct vnode *rootvp; void *bufp; struct mount *mp; - int error, export_error, len; + int error, export_error, i, len; uint64_t flag; + gid_t *grps; ASSERT_VOP_ELOCKED(vp, __func__); KASSERT((fsflags & MNT_UPDATE) != 0, ("MNT_UPDATE should be here")); @@ -1125,11 +1127,58 @@ /* Assume that there is only 1 ABI for each length. */ switch (len) { case (sizeof(struct oexport_args)): - bzero(&export, sizeof(export)); + bzero(&o2export, sizeof(o2export)); /* FALLTHROUGH */ + case (sizeof(o2export)): + bcopy(bufp, &o2export, len); + export.ex_flags = (uint64_t)o2export.ex_flags; + export.ex_root = o2export.ex_root; + export.ex_uid = o2export.ex_anon.cr_uid; + export.ex_ngroups = o2export.ex_anon.cr_ngroups; + if (export.ex_ngroups > 0) { + if (export.ex_ngroups > XU_NGROUPS) + export.ex_ngroups = XU_NGROUPS; + export.ex_groups = malloc(export.ex_ngroups * + sizeof(gid_t), M_TEMP, M_WAITOK); + for (i = 0; i < export.ex_ngroups; i++) + export.ex_groups[i] = + o2export.ex_anon.cr_groups[i]; + } else { + export.ex_ngroups = 0; + export.ex_groups = NULL; + } + export.ex_addr = o2export.ex_addr; + export.ex_addrlen = o2export.ex_addrlen; + export.ex_mask = o2export.ex_mask; + export.ex_masklen = o2export.ex_masklen; + export.ex_indexfile = o2export.ex_indexfile; + export.ex_numsecflavors = o2export.ex_numsecflavors; + for (i = 0; i < export.ex_numsecflavors; i++) + export.ex_secflavors[i] = + o2export.ex_secflavors[i]; + export_error = vfs_export(mp, &export); + free(export.ex_groups, M_TEMP); + break; case (sizeof(export)): bcopy(bufp, &export, len); - export_error = vfs_export(mp, &export); + export_error = 0; + grps = NULL; + if (export.ex_ngroups > 0) { + if (export.ex_ngroups > NGROUPS) + export.ex_ngroups = NGROUPS; + grps = malloc(export.ex_ngroups * sizeof(gid_t), + M_TEMP, M_WAITOK); + export_error = copyin(export.ex_groups, grps, + export.ex_ngroups * sizeof(gid_t)); + if (export_error == 0) + export.ex_groups = grps; + } else if (export.ex_ngroups == 0) + export.ex_groups = NULL; + else + export_error = EINVAL; + if (export_error == 0) + export_error = vfs_export(mp, &export); + free(grps, M_TEMP); break; default: export_error = EINVAL; @@ -2344,7 +2393,7 @@ } void -vfs_oexport_conv(const struct oexport_args *oexp, struct export_args *exp) +vfs_oexport_conv(const struct oexport_args *oexp, struct o2export_args *exp) { bcopy(oexp, exp, sizeof(*oexp)); Index: sys/nlm/nlm_prot_impl.c =================================================================== --- sys/nlm/nlm_prot_impl.c +++ sys/nlm/nlm_prot_impl.c @@ -1735,7 +1735,8 @@ nlm_get_vfs_state(struct nlm_host *host, struct svc_req *rqstp, fhandle_t *fhp, struct vfs_state *vs, accmode_t accmode) { - int error, exflags; + int error; + uint64_t exflags; struct ucred *cred = NULL, *credanon = NULL; memset(vs, 0, sizeof(*vs)); Index: sys/sys/mount.h =================================================================== --- sys/sys/mount.h +++ sys/sys/mount.h @@ -494,10 +494,10 @@ }; /* - * Export arguments for local filesystem mount calls. + * Not quite so old export arguments with 32bit ex_flags and xucred ex_anon. */ #define MAXSECFLAVORS 5 -struct export_args { +struct o2export_args { int ex_flags; /* export related flags */ uid_t ex_root; /* mapping for root uid */ struct xucred ex_anon; /* mapping for anonymous user */ @@ -511,6 +511,25 @@ }; /* + * Export arguments for local filesystem mount calls. + */ +#define MAXSECFLAVORS 5 +struct export_args { + uint64_t ex_flags; /* export related flags */ + uid_t ex_root; /* mapping for root uid */ + uid_t ex_uid; /* mapping for anonymous user */ + int ex_ngroups; + gid_t *ex_groups; + struct sockaddr *ex_addr; /* net address to which exported */ + u_char ex_addrlen; /* and the net address length */ + struct sockaddr *ex_mask; /* mask of valid bits in saddr */ + u_char ex_masklen; /* and the smask length */ + char *ex_indexfile; /* index file for WebNFS URLs */ + int ex_numsecflavors; /* security flavor count */ + int ex_secflavors[MAXSECFLAVORS]; /* list of security flavors */ +}; + +/* * Structure holding information for a publicly exported filesystem * (WebNFS). Currently the specs allow just for one such filesystem. */ @@ -689,8 +708,8 @@ typedef int vfs_fhtovp_t(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp); typedef int vfs_checkexp_t(struct mount *mp, struct sockaddr *nam, - int *extflagsp, struct ucred **credanonp, - int *numsecflavors, int **secflavors); + uint64_t *extflagsp, struct ucred **credanonp, + int *numsecflavors, int *secflavors); typedef int vfs_init_t(struct vfsconf *); typedef int vfs_uninit_t(struct vfsconf *); typedef int vfs_extattrctl_t(struct mount *mp, int cmd, @@ -924,7 +943,7 @@ void vfs_mountedfrom(struct mount *, const char *from); void vfs_notify_upper(struct vnode *, int); void vfs_oexport_conv(const struct oexport_args *oexp, - struct export_args *exp); + struct o2export_args *exp); void vfs_ref(struct mount *); void vfs_rel(struct mount *); struct mount *vfs_mount_alloc(struct vnode *, struct vfsconf *, const char *, Index: sys/ufs/ffs/ffs_vfsops.c =================================================================== --- sys/ufs/ffs/ffs_vfsops.c +++ sys/ufs/ffs/ffs_vfsops.c @@ -589,7 +589,7 @@ ffs_cmount(struct mntarg *ma, void *data, uint64_t flags) { struct ufs_args args; - struct export_args exp; + struct o2export_args exp; int error; if (data == NULL) Index: usr.sbin/mountd/mountd.c =================================================================== --- usr.sbin/mountd/mountd.c +++ usr.sbin/mountd/mountd.c @@ -112,6 +112,15 @@ #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]; +}; + struct exportlist { struct dirlist *ex_dirl; struct dirlist *ex_defdir; @@ -120,8 +129,8 @@ 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 +161,8 @@ 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]; @@ -188,7 +197,7 @@ 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 +211,10 @@ 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 +229,7 @@ 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 +240,13 @@ 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 +262,7 @@ 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 +272,6 @@ 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; @@ -1463,9 +1466,10 @@ 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,7 +1485,9 @@ * Set defaults. */ has_host = FALSE; - anon = def_anon; + anon.cr_uid = 65534; + anon.cr_ngroups = 1; + anon.cr_groups[0] = 65533; exflags = MNT_EXPORTED; got_nondir = 0; opt_flags = 0; @@ -1700,7 +1706,7 @@ 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 +1846,7 @@ */ 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:"); @@ -2220,10 +2226,10 @@ } 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) @@ -2389,7 +2395,7 @@ */ 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 +2413,7 @@ 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 +2447,8 @@ */ 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 +2497,7 @@ 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 +2669,7 @@ */ 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; @@ -2924,7 +2931,7 @@ 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); @@ -2935,8 +2942,8 @@ /* 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); @@ -2952,8 +2959,8 @@ * 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; @@ -2979,8 +2986,14 @@ 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; @@ -3050,9 +3063,11 @@ */ 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 { /* @@ -3168,6 +3183,7 @@ 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 */ @@ -3394,17 +3410,14 @@ * 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. */ @@ -3430,19 +3443,19 @@ 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; + 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; } /* * 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]; + for (cnt = 2; cnt < cr->cr_ngroups; cnt++) + cr->cr_groups[cnt - 1] = cr->cr_groups[cnt]; + cr->cr_ngroups--; return; } /* @@ -3458,7 +3471,7 @@ 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); @@ -3470,7 +3483,7 @@ 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"); } @@ -3790,4 +3803,14 @@ 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)); }