Subject: kern/5603: NULLFS and UMAPFS export
To: None <gnats-bugs@gnats.netbsd.org>
From: None <perseant@hitl.washington.edu>
List: netbsd-bugs
Date: 06/17/1998 16:44:20
>Number: 5603
>Category: kern
>Synopsis: It would be nice to allow exports of NULLFS-derived filesystems
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Wed Jun 17 16:50:00 1998
>Last-Modified:
>Originator: Konrad Schroder
>Organization:
Konrad Schroder http://www.hitl.washington.edu/people/perseant/
System Administrator perseant@hitl.washington.edu
Human Interface Technology Lab Voice: (206) 616-1478
Box 352142, University of Washington, 98195, USA FAX: (206) 543-5380
>Release: 1.3.2, though AFAICT nullfs and umapfs haven't changed since
>Environment:
System: NetBSD scratchy 1.3.2 NetBSD 1.3.2 (HITL_GENERIC) #11: Wed Jun 17 11:59:35 PDT 1998 perseant@ftp:/usr/src/sys/arch/sparc/compile/HITL_GENERIC sparc
>Description:
It would be nice if nullfs and friends, particularly umap, could
be exported.
We have a need to export Umap filesystems between departments
which represent different administrative domains (and so inevitably
different sets of UID/GIDs). This is essentially the same
scenario as one of the main examples of umap in the Red Daemon Book,
and the patch to allow this is relatively simple.
Currently, we are using an exported umapfs in production; though
I have successfully copied kernel sources into and successfully
done a "make depend && make" on an exported nullfs, I have not
done further testing.
The patch below can only determine stale filehandles correctly if
the underlying filesystem is an FFS, which, although sufficient
for my site, is a gross hack. Breaking out the determination
of filehandle staleness (or possibly of filesystem mountedness) from
VFS_FHTOVP into, say, VOP_STALE would provide a more general solution.
I'd be happy to implement that, if it is desired.
Union would also be desirable to export, though I've left that
for later.
>How-To-Repeat:
>Fix:
*** sys/miscfs/umapfs.dist/umap.h Mon Oct 6 04:26:46 1997
--- sys/miscfs/umapfs/umap.h Tue Jun 9 13:07:58 1998
***************
*** 47,50 ****
--- 47,52 ----
struct umap_args {
char *target; /* Target of loopback */
+ /* XXX It is a silent requirement of mountd that this be second */
+ struct export_args export; /* network export information */
int nentries; /* # of entries in user map array */
int gnentries; /* # of entries in group map array */
***************
*** 53,56 ****
--- 55,59 ----
};
+ #ifdef _KERNEL
struct umap_mount {
struct mount *umapm_vfs;
***************
*** 62,68 ****
u_long info_gmapdata[GMAPFILEENTRIES][2]; /*mapping data for
group mapping in ficus */
};
- #ifdef _KERNEL
/*
* A cache of vnode references
--- 65,71 ----
u_long info_gmapdata[GMAPFILEENTRIES][2]; /*mapping data for
group mapping in ficus */
+ struct netexport umapm_export; /* export information */
};
/*
* A cache of vnode references
*** sys/miscfs/umapfs.dist/umap_subr.c Thu Sep 11 04:20:58 1997
--- sys/miscfs/umapfs/umap_subr.c Tue Jun 9 11:57:10 1998
***************
*** 434,446 ****
structure. */
! i = 0;
! while (credp->cr_groups[i] != 0) {
gid = (gid_t) umap_findid(credp->cr_groups[i],
groupmap, gnentries);
-
if (gid != -1)
! credp->cr_groups[i++] = gid;
else
! credp->cr_groups[i++] = NULLGROUP;
}
}
--- 434,444 ----
structure. */
! for(i=0; i<credp->cr_ngroups; i++) {
gid = (gid_t) umap_findid(credp->cr_groups[i],
groupmap, gnentries);
if(gid != -1)
! credp->cr_groups[i] = gid;
else
! credp->cr_groups[i] = NULLGROUP;
}
}
*** sys/miscfs/umapfs.dist/umap_vfsops.c Mon Oct 6 04:26:46 1997
--- sys/miscfs/umapfs/umap_vfsops.c Tue Jun 9 13:07:33 1998
***************
*** 55,58 ****
--- 55,64 ----
#include <miscfs/umapfs/umap.h>
+ #include <ufs/ufs/quota.h>
+ #include <ufs/ufs/ufsmount.h>
+ #include <ufs/ufs/inode.h>
+ #include <ufs/ufs/dir.h>
+ #include <ufs/ufs/ufs_extern.h>
+
int umapfs_mount __P((struct mount *, const char *, void *,
struct nameidata *, struct proc *));
***************
*** 86,103 ****
size_t size;
int error;
-
#ifdef UMAPFS_DIAGNOSTIC
printf("umapfs_mount(mp = %p)\n", mp);
#endif
/*
- * Update is a no-op
- */
- if (mp->mnt_flag & MNT_UPDATE) {
- return (EOPNOTSUPP);
- /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/
- }
-
- /*
* Get argument
*/
--- 92,102 ----
size_t size;
int error;
#ifdef UMAPFS_DIAGNOSTIC
+ int i;
+
printf("umapfs_mount(mp = %p)\n", mp);
#endif
/*
* Get argument
*/
***************
*** 107,110 ****
--- 106,123 ----
/*
+ * Update is a no-op, unless it is an export and we're allowing those
+ */
+ if (mp->mnt_flag & MNT_UPDATE) {
+ if(args.target == 0) {
+ #ifdef UMAPFS_DIAGNOSTIC
+ printf("target = 0, processing export\n");
+ #endif /* UMAPFS_DIAGNOSTIC */
+ return (vfs_export(mp, &(MOUNTTOUMAPMOUNT(mp)->umapm_export), &args.export));
+ }
+ return (EOPNOTSUPP);
+ /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/
+ }
+
+ /*
* Find lower node
*/
***************
*** 154,158 ****
printf("umap_mount:nentries %d\n",args.nentries);
for (i = 0; i < args.nentries; i++)
! printf(" %d maps to %d\n", amp->info_mapdata[i][0],
amp->info_mapdata[i][1]);
#endif
--- 167,171 ----
printf("umap_mount:nentries %d\n",args.nentries);
for (i = 0; i < args.nentries; i++)
! printf(" %ld maps to %ld\n", amp->info_mapdata[i][0],
amp->info_mapdata[i][1]);
#endif
***************
*** 166,170 ****
printf("umap_mount:gnentries %d\n",args.gnentries);
for (i = 0; i < args.gnentries; i++)
! printf("\tgroup %d maps to %d\n",
amp->info_gmapdata[i][0],
amp->info_gmapdata[i][1]);
--- 179,183 ----
printf("umap_mount:gnentries %d\n",args.gnentries);
for (i = 0; i < args.gnentries; i++)
! printf("\tgroup %ld maps to %ld\n",
amp->info_gmapdata[i][0],
amp->info_gmapdata[i][1]);
***************
*** 384,389 ****
struct vnode **vpp;
{
! return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp));
}
--- 397,410 ----
struct vnode **vpp;
{
+ int ret;
+ struct vnode *nvp;
! ret = VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, &nvp);
! /*
! * XXX - This only works because locking gets transparently
! * passed on to the lower layer! --ks
! */
! umap_node_create(mp,nvp,vpp);
! return ret;
}
***************
*** 397,402 ****
struct ucred**credanonp;
{
! return (EOPNOTSUPP);
}
--- 418,457 ----
struct ucred**credanonp;
{
+ int error;
+ struct netcred *np;
+ struct vnode *nvp;
! /* adapted from ufs_check_export */
!
! np = vfs_export_lookup(mp, &(MOUNTTOUMAPMOUNT(mp)->umapm_export), nam);
! if (np == NULL)
! return (EACCES);
! if ((error = VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs,
! ((struct ufid *)fidp)->ufid_ino, &nvp)) != 0) {
! *vpp = NULLVP;
! return (error);
! }
! /* XXXX - KS - this is a kludge; we really want a VOP_STALE instead */
! if(nvp->v_tag == VT_UFS || nvp->v_tag == VT_LFS) {
! struct inode *ip;
!
! ip = VTOI(nvp);
! if (ip->i_ffs_mode == 0 || ip->i_ffs_gen != ((struct ufid *)fidp)->ufid_gen) {
! vput(nvp);
! *vpp = NULLVP;
! #ifdef UMAPFS_DIAGNOSTIC
! printf("ffs_mode = %d,",ip->i_ffs_mode);
! printf(" ffs_gen = %d, nfs_gen = %d\n",
! ip->i_ffs_gen, ((struct ufid *)fidp)->ufid_gen);
! #endif
! return (ESTALE);
! }
! }
!
! umap_node_create(mp,nvp,vpp);
! *exflagsp = np->netc_exflags;
! *credanonp = &np->netc_anon;
!
! return 0;
}
***************
*** 406,411 ****
struct fid *fhp;
{
! return (EOPNOTSUPP);
}
--- 461,468 ----
struct fid *fhp;
{
+ int ret;
! ret = VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp);
! return ret;
}
*** sys/miscfs/umapfs.dist/umap_vnops.c Mon Oct 6 04:26:46 1997
--- sys/miscfs/umapfs/umap_vnops.c Thu Jun 4 10:03:01 1998
***************
*** 151,163 ****
*/
! if (i && (*this_vp_p)->v_op != umap_vnodeop_p) {
old_vps[i] = NULL;
} else {
old_vps[i] = *this_vp_p;
*(vps_p[i]) = UMAPVPTOLOWERVP(*this_vp_p);
! if (reles & 1)
VREF(*this_vp_p);
}
!
}
--- 151,163 ----
*/
! if (i && ((*this_vp_p) == NULLVP || (*this_vp_p)->v_op != umap_vnodeop_p)) {
old_vps[i] = NULL;
} else {
old_vps[i] = *this_vp_p;
*(vps_p[i]) = UMAPVPTOLOWERVP(*this_vp_p);
! if (reles & 1) {
VREF(*this_vp_p);
}
! }
}
***************
*** 178,184 ****
credp = *credpp;
! if (umap_bug_bypass && credp->cr_uid != 0)
! printf("umap_bypass: user was %d, group %d\n",
credp->cr_uid, credp->cr_gid);
/* Map all ids in the credential structure. */
--- 178,190 ----
credp = *credpp;
! if (umap_bug_bypass && credp->cr_uid != 0) {
! printf("umap_bypass: user was %d, group %d (",
credp->cr_uid, credp->cr_gid);
+ for(i=0; i<credp->cr_ngroups; i++) {
+ printf("%d%s", credp->cr_groups[i],
+ (i==credp->cr_ngroups-1?"":","));
+ }
+ printf(")\n");
+ }
/* Map all ids in the credential structure. */
***************
*** 186,192 ****
umap_mapids(vp1->v_mount, credp);
! if (umap_bug_bypass && credp->cr_uid != 0)
printf("umap_bypass: user now %d, group %d\n",
credp->cr_uid, credp->cr_gid);
}
--- 192,204 ----
umap_mapids(vp1->v_mount, credp);
! if (umap_bug_bypass && credp->cr_uid != 0) {
printf("umap_bypass: user now %d, group %d\n",
credp->cr_uid, credp->cr_gid);
+ for(i=0; i<credp->cr_ngroups; i++) {
+ printf("%d%s", credp->cr_groups[i],
+ (i==credp->cr_ngroups-1?"":","));
+ }
+ printf(")\n");
+ }
}
*** sys/miscfs/nullfs.dist/null.h Wed Jun 17 11:15:19 1998
--- sys/miscfs/nullfs/null.h Wed Jun 17 11:54:49 1998
***************
*** 42,45 ****
--- 42,47 ----
struct null_args {
char *target; /* Target of loopback */
+ /* XXX It is a silent requirement of mountd that this be second */
+ struct export_args export; /* network export information */
};
***************
*** 47,56 ****
struct mount *nullm_vfs;
struct vnode *nullm_rootvp; /* Reference to root null_node */
};
- #ifdef _KERNEL
/*
* A cache of vnode references
*/
struct null_node {
LIST_ENTRY(null_node) null_hash; /* Hash list */
--- 49,59 ----
struct mount *nullm_vfs;
struct vnode *nullm_rootvp; /* Reference to root null_node */
+ struct netexport nullm_export; /* export information */
};
/*
* A cache of vnode references
*/
+ #ifdef _KERNEL
struct null_node {
LIST_ENTRY(null_node) null_hash; /* Hash list */
*** sys/miscfs/nullfs.dist/null_vfsops.c Wed Jun 17 11:15:19 1998
--- sys/miscfs/nullfs/null_vfsops.c Wed Jun 17 11:57:50 1998
***************
*** 56,59 ****
--- 56,65 ----
#include <miscfs/nullfs/null.h>
+ #include <ufs/ufs/quota.h>
+ #include <ufs/ufs/ufsmount.h>
+ #include <ufs/ufs/inode.h>
+ #include <ufs/ufs/dir.h>
+ #include <ufs/ufs/ufs_extern.h>
+
int nullfs_mount __P((struct mount *, const char *, void *,
struct nameidata *, struct proc *));
***************
*** 92,103 ****
/*
- * Update is a no-op
- */
- if (mp->mnt_flag & MNT_UPDATE) {
- return (EOPNOTSUPP);
- /* return VFS_MOUNT(MOUNTTONULLMOUNT(mp)->nullm_vfs, path, data, ndp, p);*/
- }
-
- /*
* Get argument
*/
--- 98,101 ----
***************
*** 107,110 ****
--- 105,122 ----
/*
+ * Update is a no-op, unless it is an export and we're allowing those
+ */
+ if (mp->mnt_flag & MNT_UPDATE) {
+ if(args.target == 0) {
+ #ifdef NULLFS_DIAGNOSTIC
+ printf("target = 0, processing export\n");
+ #endif /* NULLFS_DIAGNOSTIC */
+ return (vfs_export(mp, &(MOUNTTONULLMOUNT(mp)->nullm_export), &args.export));
+ }
+ return (EOPNOTSUPP);
+ /* return (VFS_MOUNT(MOUNTTONULLMOUNT(mp)->nullm_vfs, path, data, ndp, p));*/
+ }
+
+ /*
* Find lower node
*/
***************
*** 342,347 ****
struct vnode **vpp;
{
! return VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, vpp);
}
--- 354,363 ----
struct vnode **vpp;
{
+ int ret;
+ struct vnode *nvp;
! ret = VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, &nvp);
! null_node_create(mp,nvp,vpp,1);
! return ret;
}
***************
*** 355,360 ****
struct ucred**credanonp;
{
! return (EOPNOTSUPP);
}
--- 375,414 ----
struct ucred**credanonp;
{
+ int error;
+ struct netcred *np;
+ struct vnode *nvp;
! /* adapted from ufs_check_export */
!
! np = vfs_export_lookup(mp, &(MOUNTTONULLMOUNT(mp)->nullm_export), nam);
! if (np == NULL)
! return (EACCES);
! if ((error = VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs,
! ((struct ufid *)fidp)->ufid_ino, &nvp)) != 0) {
! *vpp = NULLVP;
! return (error);
! }
! /* XXXX - KS - this is a kludge; we really want a VOP_STALE instead */
! if(nvp->v_tag == VT_UFS || nvp->v_tag == VT_LFS) {
! struct inode *ip;
!
! ip = VTOI(nvp);
! if (ip->i_ffs_mode == 0 || ip->i_ffs_gen != ((struct ufid *)fidp)->ufid_gen) {
! vput(nvp);
! *vpp = NULLVP;
! #ifdef NULLFS_DIAGNOSTIC
! printf("ffs_mode = %d,",ip->i_ffs_mode);
! printf(" ffs_gen = %d, nfs_gen = %d\n",
! ip->i_ffs_gen, ((struct ufid *)fidp)->ufid_gen);
! #endif
! return (ESTALE);
! }
! }
!
! null_node_create(mp,nvp,vpp,1);
! *exflagsp = np->netc_exflags;
! *credanonp = &np->netc_anon;
!
! return 0;
}
***************
*** 364,369 ****
struct fid *fhp;
{
! return (EOPNOTSUPP);
}
--- 418,425 ----
struct fid *fhp;
{
+ int ret;
! ret = VFS_VPTOFH(NULLVPTOLOWERVP(vp), fhp);
! return ret;
}
*** usr.sbin/mountd/mountd.c.current Sun Mar 1 04:24:40 1998
--- usr.sbin/mountd/mountd.c Tue Jun 9 13:05:34 1998
***************
*** 715,718 ****
--- 708,712 ----
!strncmp(fsp->f_fstypename, MOUNT_MSDOS, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_ADOSFS, MFSNAMELEN) ||
+ !strncmp(fsp->f_fstypename, MOUNT_UMAP, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_CD9660, MFSNAMELEN)) {
bzero((char *)&targs, sizeof(targs));
>Audit-Trail:
>Unformatted: