Fix export_args ex_flags field so that is 64bits, the same as mnt_flags.
Since mnt_flags was upgraded to 64bits there has been a quirk in "struct export_args", since it hold a copy of mnt_flags in ex_flags, which is an "int" (32bits). This happens to currently work, since all the flag bits used in ex_flags are defined in the low order 32bits. However, new export flags cannot be defined. Also, ex_anon is a "struct xucred", which limits it to 16 additional groups. This patch revises "struct export_args" to make ex_flags 64bits and replaces ex_anon with ex_uid, ex_ngroups and ex_groups (which points to a groups list, so it can be malloc'd up to NGROUPS in size. This requires that the VFS_CHECKEXP() arguments change, so I also modified the last "secflavors" argument to be an array pointer, so that the secflavors could be copied in VFS_CHECKEXP() while the export entry is locked. (Without this patch VFS_CHECKEXP() returns a pointer to the secflavors array and then it is used after being unlocked, which is potentially a problem if the exports entry is changed. In practice this does not occur when mountd is run with "-S", but I think it is worth fixing.) This patch also deleted the vfs_oexport_conv() function, since do_mount_update() does the conversion, as required by the old vfs_cmount() calls. Reviewed by: kib, freqlabs Relnotes: yes Differential Revision: https://reviews.freebsd.org/D25088
This commit is contained in:
parent
e81d909274
commit
1f7104d720
@ -101,8 +101,8 @@ static int zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp);
|
|||||||
static int zfs_statfs(vfs_t *vfsp, struct statfs *statp);
|
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_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp);
|
||||||
static int zfs_sync(vfs_t *vfsp, int waitfor);
|
static int zfs_sync(vfs_t *vfsp, int waitfor);
|
||||||
static int zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, int *extflagsp,
|
static int zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, uint64_t *extflagsp,
|
||||||
struct ucred **credanonp, int *numsecflavors, int **secflavors);
|
struct ucred **credanonp, int *numsecflavors, int *secflavors);
|
||||||
static int zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp);
|
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_objset_close(zfsvfs_t *zfsvfs);
|
||||||
static void zfs_freevfs(vfs_t *vfsp);
|
static void zfs_freevfs(vfs_t *vfsp);
|
||||||
@ -2268,8 +2268,8 @@ zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, int *extflagsp,
|
zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, uint64_t *extflagsp,
|
||||||
struct ucred **credanonp, int *numsecflavors, int **secflavors)
|
struct ucred **credanonp, int *numsecflavors, int *secflavors)
|
||||||
{
|
{
|
||||||
zfsvfs_t *zfsvfs = vfsp->vfs_data;
|
zfsvfs_t *zfsvfs = vfsp->vfs_data;
|
||||||
|
|
||||||
|
@ -101,16 +101,14 @@ static int
|
|||||||
cd9660_cmount(struct mntarg *ma, void *data, uint64_t flags)
|
cd9660_cmount(struct mntarg *ma, void *data, uint64_t flags)
|
||||||
{
|
{
|
||||||
struct iso_args args;
|
struct iso_args args;
|
||||||
struct export_args exp;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = copyin(data, &args, sizeof args);
|
error = copyin(data, &args, sizeof args);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
vfs_oexport_conv(&args.export, &exp);
|
|
||||||
|
|
||||||
ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN);
|
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_disk", args.cs_disk, 64);
|
||||||
ma = mount_argsu(ma, "cs_local", args.cs_local, 64);
|
ma = mount_argsu(ma, "cs_local", args.cs_local, 64);
|
||||||
ma = mount_argf(ma, "ssector", "%u", args.ssector);
|
ma = mount_argf(ma, "ssector", "%u", args.ssector);
|
||||||
|
@ -190,7 +190,6 @@ static int
|
|||||||
msdosfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
|
msdosfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
|
||||||
{
|
{
|
||||||
struct msdosfs_args args;
|
struct msdosfs_args args;
|
||||||
struct export_args exp;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
@ -198,10 +197,9 @@ msdosfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
|
|||||||
error = copyin(data, &args, sizeof args);
|
error = copyin(data, &args, sizeof args);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
vfs_oexport_conv(&args.export, &exp);
|
|
||||||
|
|
||||||
ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN);
|
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, "uid", "%d", args.uid);
|
||||||
ma = mount_argf(ma, "gid", "%d", args.gid);
|
ma = mount_argf(ma, "gid", "%d", args.gid);
|
||||||
ma = mount_argf(ma, "mask", "%d", args.mask);
|
ma = mount_argf(ma, "mask", "%d", args.mask);
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
* needs to be returned by nfsd_fhtovp().
|
* needs to be returned by nfsd_fhtovp().
|
||||||
*/
|
*/
|
||||||
struct nfsexstuff {
|
struct nfsexstuff {
|
||||||
int nes_exflag; /* export flags */
|
uint64_t nes_exflag; /* export flags */
|
||||||
int nes_numsecflavor; /* # of security flavors */
|
int nes_numsecflavor; /* # of security flavors */
|
||||||
int nes_secflavors[MAXSECFLAVORS]; /* and the flavors */
|
int nes_secflavors[MAXSECFLAVORS]; /* and the flavors */
|
||||||
};
|
};
|
||||||
|
@ -1081,6 +1081,11 @@ struct nfsex_args {
|
|||||||
struct export_args export;
|
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.
|
* 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
|
* Maybe a separate mnt_exflag field could be added or the mnt_flag
|
||||||
|
@ -3056,10 +3056,10 @@ int
|
|||||||
nfsvno_checkexp(struct mount *mp, struct sockaddr *nam, struct nfsexstuff *exp,
|
nfsvno_checkexp(struct mount *mp, struct sockaddr *nam, struct nfsexstuff *exp,
|
||||||
struct ucred **credp)
|
struct ucred **credp)
|
||||||
{
|
{
|
||||||
int i, error, *secflavors;
|
int error;
|
||||||
|
|
||||||
error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp,
|
error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp,
|
||||||
&exp->nes_numsecflavor, &secflavors);
|
&exp->nes_numsecflavor, exp->nes_secflavors);
|
||||||
if (error) {
|
if (error) {
|
||||||
if (nfs_rootfhset) {
|
if (nfs_rootfhset) {
|
||||||
exp->nes_exflag = 0;
|
exp->nes_exflag = 0;
|
||||||
@ -3071,10 +3071,6 @@ nfsvno_checkexp(struct mount *mp, struct sockaddr *nam, struct nfsexstuff *exp,
|
|||||||
printf("nfsvno_checkexp: numsecflavors out of range\n");
|
printf("nfsvno_checkexp: numsecflavors out of range\n");
|
||||||
exp->nes_numsecflavor = 0;
|
exp->nes_numsecflavor = 0;
|
||||||
error = EACCES;
|
error = EACCES;
|
||||||
} else {
|
|
||||||
/* Copy the security flavors. */
|
|
||||||
for (i = 0; i < exp->nes_numsecflavor; i++)
|
|
||||||
exp->nes_secflavors[i] = secflavors[i];
|
|
||||||
}
|
}
|
||||||
NFSEXITCODE(error);
|
NFSEXITCODE(error);
|
||||||
return (error);
|
return (error);
|
||||||
@ -3088,7 +3084,7 @@ nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam,
|
|||||||
int lktype, struct vnode **vpp, struct nfsexstuff *exp,
|
int lktype, struct vnode **vpp, struct nfsexstuff *exp,
|
||||||
struct ucred **credp)
|
struct ucred **credp)
|
||||||
{
|
{
|
||||||
int i, error, *secflavors;
|
int error;
|
||||||
|
|
||||||
*credp = NULL;
|
*credp = NULL;
|
||||||
exp->nes_numsecflavor = 0;
|
exp->nes_numsecflavor = 0;
|
||||||
@ -3098,7 +3094,7 @@ nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam,
|
|||||||
error = ESTALE;
|
error = ESTALE;
|
||||||
if (nam && !error) {
|
if (nam && !error) {
|
||||||
error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp,
|
error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp,
|
||||||
&exp->nes_numsecflavor, &secflavors);
|
&exp->nes_numsecflavor, exp->nes_secflavors);
|
||||||
if (error) {
|
if (error) {
|
||||||
if (nfs_rootfhset) {
|
if (nfs_rootfhset) {
|
||||||
exp->nes_exflag = 0;
|
exp->nes_exflag = 0;
|
||||||
@ -3113,10 +3109,6 @@ nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam,
|
|||||||
exp->nes_numsecflavor = 0;
|
exp->nes_numsecflavor = 0;
|
||||||
error = EACCES;
|
error = EACCES;
|
||||||
vput(*vpp);
|
vput(*vpp);
|
||||||
} else {
|
|
||||||
/* Copy the security flavors. */
|
|
||||||
for (i = 0; i < exp->nes_numsecflavor; i++)
|
|
||||||
exp->nes_secflavors[i] = secflavors[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NFSEXITCODE(error);
|
NFSEXITCODE(error);
|
||||||
@ -3415,10 +3407,11 @@ int
|
|||||||
nfsvno_v4rootexport(struct nfsrv_descript *nd)
|
nfsvno_v4rootexport(struct nfsrv_descript *nd)
|
||||||
{
|
{
|
||||||
struct ucred *credanon;
|
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,
|
error = vfs_stdcheckexp(&nfsv4root_mnt, nd->nd_nam, &exflags,
|
||||||
&credanon, &numsecflavor, &secflavors);
|
&credanon, &numsecflavor, secflavors);
|
||||||
if (error) {
|
if (error) {
|
||||||
error = NFSERR_PROGUNAVAIL;
|
error = NFSERR_PROGUNAVAIL;
|
||||||
goto out;
|
goto out;
|
||||||
@ -3656,8 +3649,9 @@ static int
|
|||||||
nfssvc_srvcall(struct thread *p, struct nfssvc_args *uap, struct ucred *cred)
|
nfssvc_srvcall(struct thread *p, struct nfssvc_args *uap, struct ucred *cred)
|
||||||
{
|
{
|
||||||
struct nfsex_args export;
|
struct nfsex_args export;
|
||||||
|
struct nfsex_oldargs oexp;
|
||||||
struct file *fp = NULL;
|
struct file *fp = NULL;
|
||||||
int stablefd, len;
|
int stablefd, i, len;
|
||||||
struct nfsd_clid adminrevoke;
|
struct nfsd_clid adminrevoke;
|
||||||
struct nfsd_dumplist dumplist;
|
struct nfsd_dumplist dumplist;
|
||||||
struct nfsd_dumpclients *dumpclients;
|
struct nfsd_dumpclients *dumpclients;
|
||||||
@ -3667,6 +3661,7 @@ nfssvc_srvcall(struct thread *p, struct nfssvc_args *uap, struct ucred *cred)
|
|||||||
vnode_t vp;
|
vnode_t vp;
|
||||||
int error = EINVAL, igotlock;
|
int error = EINVAL, igotlock;
|
||||||
struct proc *procp;
|
struct proc *procp;
|
||||||
|
gid_t *grps;
|
||||||
static int suspend_nfsd = 0;
|
static int suspend_nfsd = 0;
|
||||||
|
|
||||||
if (uap->flag & NFSSVC_PUBLICFH) {
|
if (uap->flag & NFSSVC_PUBLICFH) {
|
||||||
@ -3676,11 +3671,71 @@ nfssvc_srvcall(struct thread *p, struct nfssvc_args *uap, struct ucred *cred)
|
|||||||
&nfs_pubfh.nfsrvfh_data, sizeof (fhandle_t));
|
&nfs_pubfh.nfsrvfh_data, sizeof (fhandle_t));
|
||||||
if (!error)
|
if (!error)
|
||||||
nfs_pubfhset = 1;
|
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,
|
error = copyin(uap->argp,(caddr_t)&export,
|
||||||
sizeof (struct nfsex_args));
|
sizeof (struct nfsex_args));
|
||||||
|
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)
|
if (!error)
|
||||||
error = nfsrv_v4rootexport(&export, cred, p);
|
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) {
|
} else if (uap->flag & NFSSVC_NOPUBLICFH) {
|
||||||
nfs_pubfhset = 0;
|
nfs_pubfhset = 0;
|
||||||
error = 0;
|
error = 0;
|
||||||
|
@ -461,8 +461,8 @@ unionfs_fhtovp(struct mount *mp, struct fid *fidp, int flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
unionfs_checkexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
|
unionfs_checkexp(struct mount *mp, struct sockaddr *nam, uint64_t *extflagsp,
|
||||||
struct ucred **credanonp, int *numsecflavors, int **secflavors)
|
struct ucred **credanonp, int *numsecflavors, int *secflavors)
|
||||||
{
|
{
|
||||||
return (EOPNOTSUPP);
|
return (EOPNOTSUPP);
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ static struct netcred *vfs_export_lookup(struct mount *, struct sockaddr *);
|
|||||||
*/
|
*/
|
||||||
struct netcred {
|
struct netcred {
|
||||||
struct radix_node netc_rnodes[2];
|
struct radix_node netc_rnodes[2];
|
||||||
int netc_exflags;
|
uint64_t netc_exflags;
|
||||||
struct ucred *netc_anon;
|
struct ucred *netc_anon;
|
||||||
int netc_numsecflavors;
|
int netc_numsecflavors;
|
||||||
int netc_secflavors[MAXSECFLAVORS];
|
int netc_secflavors[MAXSECFLAVORS];
|
||||||
@ -118,18 +118,12 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
|
|||||||
("%s: numsecflavors >= MAXSECFLAVORS", __func__));
|
("%s: numsecflavors >= MAXSECFLAVORS", __func__));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX: This routine converts from a `struct xucred'
|
* XXX: This routine converts from a uid plus gid list
|
||||||
* (argp->ex_anon) to a `struct ucred' (np->netc_anon). This
|
* to a `struct ucred' (np->netc_anon). This
|
||||||
* operation is questionable; for example, what should be done
|
* operation is questionable; for example, what should be done
|
||||||
* with fields like cr_uidinfo and cr_prison? Currently, this
|
* with fields like cr_uidinfo and cr_prison? Currently, this
|
||||||
* routine does not touch them (leaves them as NULL).
|
* 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 (argp->ex_addrlen == 0) {
|
||||||
if (mp->mnt_flag & MNT_DEFEXPORTED) {
|
if (mp->mnt_flag & MNT_DEFEXPORTED) {
|
||||||
vfs_mount_error(mp,
|
vfs_mount_error(mp,
|
||||||
@ -139,9 +133,9 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
|
|||||||
np = &nep->ne_defexported;
|
np = &nep->ne_defexported;
|
||||||
np->netc_exflags = argp->ex_flags;
|
np->netc_exflags = argp->ex_flags;
|
||||||
np->netc_anon = crget();
|
np->netc_anon = crget();
|
||||||
np->netc_anon->cr_uid = argp->ex_anon.cr_uid;
|
np->netc_anon->cr_uid = argp->ex_uid;
|
||||||
crsetgroups(np->netc_anon, argp->ex_anon.cr_ngroups,
|
crsetgroups(np->netc_anon, argp->ex_ngroups,
|
||||||
argp->ex_anon.cr_groups);
|
argp->ex_groups);
|
||||||
np->netc_anon->cr_prison = &prison0;
|
np->netc_anon->cr_prison = &prison0;
|
||||||
prison_hold(np->netc_anon->cr_prison);
|
prison_hold(np->netc_anon->cr_prison);
|
||||||
np->netc_numsecflavors = argp->ex_numsecflavors;
|
np->netc_numsecflavors = argp->ex_numsecflavors;
|
||||||
@ -218,9 +212,9 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
|
|||||||
}
|
}
|
||||||
np->netc_exflags = argp->ex_flags;
|
np->netc_exflags = argp->ex_flags;
|
||||||
np->netc_anon = crget();
|
np->netc_anon = crget();
|
||||||
np->netc_anon->cr_uid = argp->ex_anon.cr_uid;
|
np->netc_anon->cr_uid = argp->ex_uid;
|
||||||
crsetgroups(np->netc_anon, argp->ex_anon.cr_ngroups,
|
crsetgroups(np->netc_anon, argp->ex_ngroups,
|
||||||
argp->ex_anon.cr_groups);
|
argp->ex_groups);
|
||||||
np->netc_anon->cr_prison = &prison0;
|
np->netc_anon->cr_prison = &prison0;
|
||||||
prison_hold(np->netc_anon->cr_prison);
|
prison_hold(np->netc_anon->cr_prison);
|
||||||
np->netc_numsecflavors = argp->ex_numsecflavors;
|
np->netc_numsecflavors = argp->ex_numsecflavors;
|
||||||
@ -512,8 +506,8 @@ vfs_export_lookup(struct mount *mp, struct sockaddr *nam)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
|
vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, uint64_t *extflagsp,
|
||||||
struct ucred **credanonp, int *numsecflavors, int **secflavors)
|
struct ucred **credanonp, int *numsecflavors, int *secflavors)
|
||||||
{
|
{
|
||||||
struct netcred *np;
|
struct netcred *np;
|
||||||
|
|
||||||
@ -534,8 +528,9 @@ vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
|
|||||||
KASSERT(*numsecflavors < MAXSECFLAVORS,
|
KASSERT(*numsecflavors < MAXSECFLAVORS,
|
||||||
("%s: numsecflavors >= MAXSECFLAVORS", __func__));
|
("%s: numsecflavors >= MAXSECFLAVORS", __func__));
|
||||||
}
|
}
|
||||||
if (secflavors)
|
if (secflavors && np->netc_numsecflavors > 0)
|
||||||
*secflavors = np->netc_secflavors;
|
memcpy(secflavors, np->netc_secflavors, np->netc_numsecflavors *
|
||||||
|
sizeof(int));
|
||||||
lockmgr(&mp->mnt_explock, LK_RELEASE, NULL);
|
lockmgr(&mp->mnt_explock, LK_RELEASE, NULL);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
@ -268,8 +268,8 @@ vfs_fhtovp_sigdefer(struct mount *mp, struct fid *fidp, int flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vfs_checkexp_sigdefer(struct mount *mp, struct sockaddr *nam, int *exflg,
|
vfs_checkexp_sigdefer(struct mount *mp, struct sockaddr *nam, uint64_t *exflg,
|
||||||
struct ucred **credp, int *numsecflavors, int **secflavors)
|
struct ucred **credp, int *numsecflavors, int *secflavors)
|
||||||
{
|
{
|
||||||
int prev_stops, rc;
|
int prev_stops, rc;
|
||||||
|
|
||||||
|
@ -1041,11 +1041,13 @@ vfs_domount_update(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
struct export_args export;
|
struct export_args export;
|
||||||
|
struct o2export_args o2export;
|
||||||
struct vnode *rootvp;
|
struct vnode *rootvp;
|
||||||
void *bufp;
|
void *bufp;
|
||||||
struct mount *mp;
|
struct mount *mp;
|
||||||
int error, export_error, len;
|
int error, export_error, i, len;
|
||||||
uint64_t flag;
|
uint64_t flag;
|
||||||
|
gid_t *grps;
|
||||||
|
|
||||||
ASSERT_VOP_ELOCKED(vp, __func__);
|
ASSERT_VOP_ELOCKED(vp, __func__);
|
||||||
KASSERT((fsflags & MNT_UPDATE) != 0, ("MNT_UPDATE should be here"));
|
KASSERT((fsflags & MNT_UPDATE) != 0, ("MNT_UPDATE should be here"));
|
||||||
@ -1128,11 +1130,66 @@ vfs_domount_update(
|
|||||||
/* Assume that there is only 1 ABI for each length. */
|
/* Assume that there is only 1 ABI for each length. */
|
||||||
switch (len) {
|
switch (len) {
|
||||||
case (sizeof(struct oexport_args)):
|
case (sizeof(struct oexport_args)):
|
||||||
bzero(&export, sizeof(export));
|
bzero(&o2export, sizeof(o2export));
|
||||||
|
o2export.ex_numsecflavors = 1;
|
||||||
|
o2export.ex_secflavors[0] = AUTH_SYS;
|
||||||
/* FALLTHROUGH */
|
/* 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)):
|
case (sizeof(export)):
|
||||||
bcopy(bufp, &export, len);
|
bcopy(bufp, &export, len);
|
||||||
|
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);
|
export_error = vfs_export(mp, &export);
|
||||||
|
free(grps, M_TEMP);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
export_error = EINVAL;
|
export_error = EINVAL;
|
||||||
@ -2345,23 +2402,3 @@ kernel_vmount(int flags, ...)
|
|||||||
error = kernel_mount(ma, flags);
|
error = kernel_mount(ma, flags);
|
||||||
return (error);
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1735,7 +1735,8 @@ static int
|
|||||||
nlm_get_vfs_state(struct nlm_host *host, struct svc_req *rqstp,
|
nlm_get_vfs_state(struct nlm_host *host, struct svc_req *rqstp,
|
||||||
fhandle_t *fhp, struct vfs_state *vs, accmode_t accmode)
|
fhandle_t *fhp, struct vfs_state *vs, accmode_t accmode)
|
||||||
{
|
{
|
||||||
int error, exflags;
|
int error;
|
||||||
|
uint64_t exflags;
|
||||||
struct ucred *cred = NULL, *credanon = NULL;
|
struct ucred *cred = NULL, *credanon = NULL;
|
||||||
|
|
||||||
memset(vs, 0, sizeof(*vs));
|
memset(vs, 0, sizeof(*vs));
|
||||||
|
@ -498,14 +498,33 @@ struct oexport_args {
|
|||||||
char *ex_indexfile; /* index file for WebNFS URLs */
|
char *ex_indexfile; /* index file for WebNFS URLs */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not quite so old export arguments with 32bit ex_flags and xucred ex_anon.
|
||||||
|
*/
|
||||||
|
#define MAXSECFLAVORS 5
|
||||||
|
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 */
|
||||||
|
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 */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Export arguments for local filesystem mount calls.
|
* Export arguments for local filesystem mount calls.
|
||||||
*/
|
*/
|
||||||
#define MAXSECFLAVORS 5
|
#define MAXSECFLAVORS 5
|
||||||
struct export_args {
|
struct export_args {
|
||||||
int ex_flags; /* export related flags */
|
uint64_t ex_flags; /* export related flags */
|
||||||
uid_t ex_root; /* mapping for root uid */
|
uid_t ex_root; /* mapping for root uid */
|
||||||
struct xucred ex_anon; /* mapping for anonymous user */
|
uid_t ex_uid; /* mapping for anonymous user */
|
||||||
|
int ex_ngroups;
|
||||||
|
gid_t *ex_groups;
|
||||||
struct sockaddr *ex_addr; /* net address to which exported */
|
struct sockaddr *ex_addr; /* net address to which exported */
|
||||||
u_char ex_addrlen; /* and the net address length */
|
u_char ex_addrlen; /* and the net address length */
|
||||||
struct sockaddr *ex_mask; /* mask of valid bits in saddr */
|
struct sockaddr *ex_mask; /* mask of valid bits in saddr */
|
||||||
@ -694,8 +713,8 @@ typedef int vfs_vget_t(struct mount *mp, ino_t ino, int flags,
|
|||||||
typedef int vfs_fhtovp_t(struct mount *mp, struct fid *fhp,
|
typedef int vfs_fhtovp_t(struct mount *mp, struct fid *fhp,
|
||||||
int flags, struct vnode **vpp);
|
int flags, struct vnode **vpp);
|
||||||
typedef int vfs_checkexp_t(struct mount *mp, struct sockaddr *nam,
|
typedef int vfs_checkexp_t(struct mount *mp, struct sockaddr *nam,
|
||||||
int *extflagsp, struct ucred **credanonp,
|
uint64_t *extflagsp, struct ucred **credanonp,
|
||||||
int *numsecflavors, int **secflavors);
|
int *numsecflavors, int *secflavors);
|
||||||
typedef int vfs_init_t(struct vfsconf *);
|
typedef int vfs_init_t(struct vfsconf *);
|
||||||
typedef int vfs_uninit_t(struct vfsconf *);
|
typedef int vfs_uninit_t(struct vfsconf *);
|
||||||
typedef int vfs_extattrctl_t(struct mount *mp, int cmd,
|
typedef int vfs_extattrctl_t(struct mount *mp, int cmd,
|
||||||
@ -928,8 +947,6 @@ void vfs_mount_error(struct mount *, const char *, ...);
|
|||||||
void vfs_mountroot(void); /* mount our root filesystem */
|
void vfs_mountroot(void); /* mount our root filesystem */
|
||||||
void vfs_mountedfrom(struct mount *, const char *from);
|
void vfs_mountedfrom(struct mount *, const char *from);
|
||||||
void vfs_notify_upper(struct vnode *, int);
|
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_ref(struct mount *);
|
||||||
void vfs_rel(struct mount *);
|
void vfs_rel(struct mount *);
|
||||||
struct mount *vfs_mount_alloc(struct vnode *, struct vfsconf *, const char *,
|
struct mount *vfs_mount_alloc(struct vnode *, struct vfsconf *, const char *,
|
||||||
|
@ -596,7 +596,6 @@ static int
|
|||||||
ffs_cmount(struct mntarg *ma, void *data, uint64_t flags)
|
ffs_cmount(struct mntarg *ma, void *data, uint64_t flags)
|
||||||
{
|
{
|
||||||
struct ufs_args args;
|
struct ufs_args args;
|
||||||
struct export_args exp;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
@ -604,10 +603,9 @@ ffs_cmount(struct mntarg *ma, void *data, uint64_t flags)
|
|||||||
error = copyin(data, &args, sizeof args);
|
error = copyin(data, &args, sizeof args);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
vfs_oexport_conv(&args.export, &exp);
|
|
||||||
|
|
||||||
ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN);
|
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);
|
error = kernel_mount(ma, flags);
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
|
Loading…
Reference in New Issue
Block a user