Index: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c =================================================================== --- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c +++ head/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: head/sys/fs/cd9660/cd9660_vfsops.c =================================================================== --- head/sys/fs/cd9660/cd9660_vfsops.c +++ head/sys/fs/cd9660/cd9660_vfsops.c @@ -101,16 +101,14 @@ cd9660_cmount(struct mntarg *ma, void *data, uint64_t flags) { struct iso_args args; - struct export_args exp; int error; error = copyin(data, &args, sizeof args); if (error) return (error); - vfs_oexport_conv(&args.export, &exp); ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN); - ma = mount_arg(ma, "export", &exp, sizeof(exp)); + ma = mount_arg(ma, "export", &args.export, sizeof(args.export)); ma = mount_argsu(ma, "cs_disk", args.cs_disk, 64); ma = mount_argsu(ma, "cs_local", args.cs_local, 64); ma = mount_argf(ma, "ssector", "%u", args.ssector); Index: head/sys/fs/msdosfs/msdosfs_vfsops.c =================================================================== --- head/sys/fs/msdosfs/msdosfs_vfsops.c +++ head/sys/fs/msdosfs/msdosfs_vfsops.c @@ -190,7 +190,6 @@ msdosfs_cmount(struct mntarg *ma, void *data, uint64_t flags) { struct msdosfs_args args; - struct export_args exp; int error; if (data == NULL) @@ -198,10 +197,9 @@ error = copyin(data, &args, sizeof args); if (error) return (error); - vfs_oexport_conv(&args.export, &exp); ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN); - ma = mount_arg(ma, "export", &exp, sizeof(exp)); + ma = mount_arg(ma, "export", &args.export, sizeof(args.export)); ma = mount_argf(ma, "uid", "%d", args.uid); ma = mount_argf(ma, "gid", "%d", args.gid); ma = mount_argf(ma, "mask", "%d", args.mask); Index: head/sys/fs/nfs/nfsdport.h =================================================================== --- head/sys/fs/nfs/nfsdport.h +++ head/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: head/sys/fs/nfs/nfsport.h =================================================================== --- head/sys/fs/nfs/nfsport.h +++ head/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: head/sys/fs/nfsserver/nfs_nfsdport.c =================================================================== --- head/sys/fs/nfsserver/nfs_nfsdport.c +++ head/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 error; error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, - &exp->nes_numsecflavor, &secflavors); + &exp->nes_numsecflavor, exp->nes_secflavors); if (error) { if (nfs_rootfhset) { exp->nes_exflag = 0; @@ -3071,10 +3071,6 @@ printf("nfsvno_checkexp: numsecflavors out of range\n"); exp->nes_numsecflavor = 0; error = EACCES; - } else { - /* Copy the security flavors. */ - for (i = 0; i < exp->nes_numsecflavor; i++) - exp->nes_secflavors[i] = secflavors[i]; } NFSEXITCODE(error); return (error); @@ -3088,7 +3084,7 @@ int lktype, struct vnode **vpp, struct nfsexstuff *exp, struct ucred **credp) { - int i, error, *secflavors; + int error; *credp = NULL; exp->nes_numsecflavor = 0; @@ -3098,7 +3094,7 @@ error = ESTALE; if (nam && !error) { error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, - &exp->nes_numsecflavor, &secflavors); + &exp->nes_numsecflavor, exp->nes_secflavors); if (error) { if (nfs_rootfhset) { exp->nes_exflag = 0; @@ -3113,10 +3109,6 @@ exp->nes_numsecflavor = 0; error = EACCES; vput(*vpp); - } else { - /* Copy the security flavors. */ - for (i = 0; i < exp->nes_numsecflavor; i++) - exp->nes_secflavors[i] = secflavors[i]; } } NFSEXITCODE(error); @@ -3415,10 +3407,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 +3649,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 +3661,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 +3671,71 @@ &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) - error = nfsrv_v4rootexport(&export, cred, p); + if (!error) { + grps = NULL; + if (export.export.ex_ngroups > NGROUPS_MAX || + export.export.ex_ngroups < 0) + error = EINVAL; + else if (export.export.ex_ngroups > 0) { + 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_groups = NULL; + if (!error) + error = nfsrv_v4rootexport(&export, cred, p); + free(grps, 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; + export.export.ex_groups = NULL; + if (export.export.ex_ngroups > XU_NGROUPS || + export.export.ex_ngroups < 0) + error = EINVAL; + else if (export.export.ex_ngroups > 0) { + 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]; + } + 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; + if (export.export.ex_numsecflavors >= MAXSECFLAVORS || + export.export.ex_numsecflavors < 0) + error = EINVAL; + else { + for (i = 0; i < export.export.ex_numsecflavors; + i++) + export.export.ex_secflavors[i] = + oexp.export.ex_secflavors[i]; + } + export.fspec = oexp.fspec; + if (error == 0) + 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: head/sys/fs/unionfs/union_vfsops.c =================================================================== --- head/sys/fs/unionfs/union_vfsops.c +++ head/sys/fs/unionfs/union_vfsops.c @@ -461,8 +461,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: head/sys/kern/vfs_export.c =================================================================== --- head/sys/kern/vfs_export.c +++ head/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: head/sys/kern/vfs_init.c =================================================================== --- head/sys/kern/vfs_init.c +++ head/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: head/sys/kern/vfs_mount.c =================================================================== --- head/sys/kern/vfs_mount.c +++ head/sys/kern/vfs_mount.c @@ -1041,11 +1041,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")); @@ -1128,11 +1130,66 @@ /* 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)); + o2export.ex_numsecflavors = 1; + o2export.ex_secflavors[0] = AUTH_SYS; /* 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_groups = NULL; + export.ex_ngroups = o2export.ex_anon.cr_ngroups; + if (export.ex_ngroups > 0) { + if (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_error = EINVAL; + } else if (export.ex_ngroups < 0) + export_error = EINVAL; + 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; + if (export.ex_numsecflavors < MAXSECFLAVORS) { + for (i = 0; i < export.ex_numsecflavors; i++) + export.ex_secflavors[i] = + o2export.ex_secflavors[i]; + } else + export_error = EINVAL; + if (export_error == 0) + 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); + grps = NULL; + if (export.ex_ngroups > 0) { + if (export.ex_ngroups <= NGROUPS_MAX) { + 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 + export_error = EINVAL; + } 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,24 +2401,4 @@ error = kernel_mount(ma, flags); return (error); -} - -/* - * Convert the old export args format into new export args. - * - * The old export args struct does not have security flavors. Otherwise, the - * structs are identical. The default security flavor 'sys' is applied when - * the given args export the filesystem. - */ -void -vfs_oexport_conv(const struct oexport_args *oexp, struct export_args *exp) -{ - - bcopy(oexp, exp, sizeof(*oexp)); - if (exp->ex_flags & MNT_EXPORTED) { - exp->ex_numsecflavors = 1; - exp->ex_secflavors[0] = AUTH_SYS; - } else { - exp->ex_numsecflavors = 0; - } } Index: head/sys/nlm/nlm_prot_impl.c =================================================================== --- head/sys/nlm/nlm_prot_impl.c +++ head/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: head/sys/sys/mount.h =================================================================== --- head/sys/sys/mount.h +++ head/sys/sys/mount.h @@ -499,10 +499,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 */ @@ -516,6 +516,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. */ @@ -694,8 +713,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, @@ -928,8 +947,6 @@ void vfs_mountroot(void); /* mount our root filesystem */ 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); void vfs_ref(struct mount *); void vfs_rel(struct mount *); struct mount *vfs_mount_alloc(struct vnode *, struct vfsconf *, const char *, Index: head/sys/ufs/ffs/ffs_vfsops.c =================================================================== --- head/sys/ufs/ffs/ffs_vfsops.c +++ head/sys/ufs/ffs/ffs_vfsops.c @@ -596,7 +596,6 @@ ffs_cmount(struct mntarg *ma, void *data, uint64_t flags) { struct ufs_args args; - struct export_args exp; int error; if (data == NULL) @@ -604,10 +603,9 @@ error = copyin(data, &args, sizeof args); if (error) return (error); - vfs_oexport_conv(&args.export, &exp); ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN); - ma = mount_arg(ma, "export", &exp, sizeof(exp)); + ma = mount_arg(ma, "export", &args.export, sizeof(args.export)); error = kernel_mount(ma, flags); return (error);