Backout revision 1.58-1.61; Since we currently only have a way to unexport

per mount point, the way ``try to export and unexport an unnecessary
mount point later'' may leave unwanted information in the kernel, and
doesn't work if a mount point is default exported or publically exported.

To fix the race condtion, we need another way.
This commit is contained in:
enami 2000-02-16 04:08:40 +00:00
parent 4316d096db
commit 700450f288

View File

@ -1,7 +1,7 @@
/* $NetBSD: mountd.c,v 1.61 2000/02/16 01:27:14 dante Exp $ */
/* $NetBSD: mountd.c,v 1.62 2000/02/16 04:08:40 enami Exp $ */
/*
* Copyright (c) 1989, 1993, 2000
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@ -51,7 +51,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
#if 0
static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95";
#else
__RCSID("$NetBSD: mountd.c,v 1.61 2000/02/16 01:27:14 dante Exp $");
__RCSID("$NetBSD: mountd.c,v 1.62 2000/02/16 04:08:40 enami Exp $");
#endif
#endif /* not lint */
@ -176,15 +176,6 @@ struct fhreturn {
nfsfh_t fhr_fh;
};
union mount_args {
struct ufs_args ua;
struct iso_args ia;
struct mfs_args ma;
struct msdosfs_args da;
struct adosfs_args aa;
};
/* Global defs */
static char *add_expdir __P((struct dirlist **, char *, int));
static void add_dlist __P((struct dirlist **, struct dirlist *,
@ -200,9 +191,6 @@ static int do_mount __P((const char *, size_t, struct exportlist *,
static int do_opt __P((const char *, size_t, char **, char **,
struct exportlist *, struct grouplist *, int *, int *, struct ucred *));
static struct exportlist *ex_search __P((fsid_t *));
static int mount_unexport __P((struct statfs *));
static int mount_export __P((char *, int, struct statfs *,
union mount_args *));
static int parse_directory __P((const char *, size_t, struct grouplist *,
int, char *, struct exportlist **, struct statfs *));
static int parse_host_netgroup __P((const char *, size_t, struct exportlist *,
@ -835,9 +823,41 @@ get_exportlist(n)
grphead = NULL;
/*
* save off the current export lists for later
* And delete exports that are in the kernel for all local
* file systems.
* XXX: Should know how to handle all local exportable file systems
* instead of just MOUNT_FFS.
*/
num = getmntinfo(&fsp, MNT_NOWAIT);
for (i = 0; i < num; i++) {
union {
struct ufs_args ua;
struct iso_args ia;
struct mfs_args ma;
struct msdosfs_args da;
struct adosfs_args aa;
} targs;
if (!strncmp(fsp->f_fstypename, MOUNT_MFS, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_FFS, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_EXT2FS, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_MSDOS, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_ADOSFS, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_NULL, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_UMAP, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_UNION, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_CD9660, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_NTFS, MFSNAMELEN)) {
bzero((char *) &targs, sizeof(targs));
targs.ua.fspec = NULL;
targs.ua.export.ex_flags = MNT_DELEXPORT;
if (mount(fsp->f_fstypename, fsp->f_mntonname,
fsp->f_flags | MNT_UPDATE, &targs) == -1)
syslog(LOG_ERR, "Can't delete exports for %s",
fsp->f_mntonname);
}
fsp++;
}
/*
* Read in the exports file and build the list, calling
@ -1015,32 +1035,6 @@ nextline:
free(line);
}
(void)fclose(exp_file);
/*
* Ok, remove any filesystems that existed before that should
* not be there anymore.
*/
/*
* XXX: Should know how to handle all local exportable file systems
* instead of just MOUNT_FFS.
*/
for (i = 0; i < num; i++, fsp++) {
if (debug)
(void)fprintf(stderr,
"seeing if we want to delete %s.\n",
fsp->f_mntonname);
/*
* If we can find it in our internal list, we do not
* want to delete it from the kernel.
*/
if (ex_search(&fsp->f_fsid))
continue;
if (mount_unexport(fsp) == -1) {
syslog(LOG_ERR, "Can't delete exports for %s",
fsp->f_mntonname);
}
}
}
/*
@ -1659,92 +1653,6 @@ estrdup(s)
return n;
}
static int
mount_unexport(fsp)
struct statfs *fsp;
{
union mount_args targs;
if (!strncmp(fsp->f_fstypename, MOUNT_MFS, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_FFS, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_EXT2FS, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_MSDOS, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_ADOSFS, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_NULL, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_UMAP, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_UNION, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_CD9660, MFSNAMELEN) ||
!strncmp(fsp->f_fstypename, MOUNT_NTFS, MFSNAMELEN)) {
if (debug)
(void)fprintf(stderr,
"Deleting export for mount %s.\n",
fsp->f_mntonname);
memset(&targs, 0, sizeof(targs));
targs.ua.fspec = NULL;
targs.ua.export.ex_flags = MNT_DELEXPORT;
return (mount(fsp->f_fstypename, fsp->f_mntonname,
fsp->f_flags | MNT_UPDATE, &targs));
}
return (0);
}
#define MNTD_EXPORTED 0
#define MNTD_NO_PERM 1
#define MNTD_NO_REMOUNT 2
#define MNTD_UNSUCC 3
static int
mount_export(dirp, dirplen, fsb, mntargs)
char *dirp;
int dirplen;
struct statfs *fsb;
union mount_args *mntargs;
{
char *cp, savedc;
cp = NULL; /* First, cp points terminating NUL. */
/*
* XXX:
* Maybe I should just use the fsb->f_mntonname path instead
* of looping back up the dirp to the mount point??
* Also, needs to know how to export all types of local
* exportable file systems and not just MOUNT_FFS.
*/
while ((mount(fsb->f_fstypename, dirp,
fsb->f_flags | MNT_UPDATE, mntargs)) == -1) {
if (cp)
*cp-- = savedc;
else
cp = dirp + dirplen - 1;
if (errno == EPERM) {
return(MNTD_NO_PERM);
}
if (opt_flags & OP_ALLDIRS) {
return(MNTD_NO_REMOUNT);
}
/* back up over the last component */
while (*cp == '/' && cp > dirp)
cp--;
while (*(cp - 1) != '/' && cp > dirp)
cp--;
if (cp == dirp) {
if (debug)
(void)fprintf(stderr, "mnt unsucc\n");
fprintf(stderr, "3\n");
return (MNTD_UNSUCC);
}
savedc = *cp;
*cp = '\0';
}
return (MNTD_EXPORTED);
}
/*
* Do the mount syscall with the update flag to push the export info into
* the kernel.
@ -1761,10 +1669,18 @@ do_mount(line, lineno, ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
int dirplen;
struct statfs *fsb;
{
char *cp = NULL;
u_int32_t **addrp;
int done, error;
int done;
char savedc = '\0';
struct sockaddr_in sin, imask;
union mount_args args;
union {
struct ufs_args ua;
struct iso_args ia;
struct mfs_args ma;
struct msdosfs_args da;
struct adosfs_args aa;
} args;
u_int32_t net;
args.ua.fspec = 0;
@ -1829,53 +1745,58 @@ do_mount(line, lineno, ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
default:
syslog(LOG_ERR, "\"%s\", line %ld: Bad netgroup type",
line, (unsigned long)lineno);
if (cp)
*cp = savedc;
return (1);
};
if((error = mount_export(dirp, dirplen, fsb, &args))
!= MNTD_EXPORTED) {
if(error == MNTD_NO_REMOUNT) {
syslog(LOG_ERR, "\"%s\", line %ld: "
"Could not remount %s: %m",
line, (unsigned long)lineno, dirp);
return 1;
/*
* XXX:
* Maybe I should just use the fsb->f_mntonname path instead
* of looping back up the dirp to the mount point??
* Also, needs to know how to export all types of local
* exportable file systems and not just MOUNT_FFS.
*/
while (mount(fsb->f_fstypename, dirp,
fsb->f_flags | MNT_UPDATE, &args) == -1) {
if (cp)
*cp-- = savedc;
else
cp = dirp + dirplen - 1;
if (errno == EPERM) {
syslog(LOG_ERR,
"\"%s\", line %ld: Can't change attributes for %s to %s",
line, (unsigned long)lineno,
dirp, (grp->gr_type == GT_HOST) ?
grp->gr_ptr.gt_hostent->h_name :
(grp->gr_type == GT_NET) ?
grp->gr_ptr.gt_net.nt_name :
"Unknown");
return (1);
}
/*
* It may be just some export options are modified.
* Unexport and retry.
*/
if(mount_unexport(fsb)) {
if(mount_export(dirp, dirplen, fsb, &args)
!= MNTD_EXPORTED) {
switch(error) {
case MNTD_NO_PERM:
syslog(LOG_ERR,
"\"%s\", line %ld: "
"Can't change attributes "
"for %s to %s",
line, (unsigned long)lineno,
dirp,
(grp->gr_type == GT_HOST) ?
grp->gr_ptr.gt_hostent->h_name :
(grp->gr_type == GT_NET) ?
grp->gr_ptr.gt_net.nt_name :
"Unknown");
break;
case MNTD_UNSUCC:
syslog(LOG_ERR,
"\"%s\", line %ld: "
"Can't export %s",
line,
(unsigned long)lineno, dirp);
break;
}
return 1;
}
if (opt_flags & OP_ALLDIRS) {
syslog(LOG_ERR,
"\"%s\", line %ld: Could not remount %s: %m",
line, (unsigned long)lineno,
dirp);
return (1);
}
/* back up over the last component */
while (*cp == '/' && cp > dirp)
cp--;
while (*(cp - 1) != '/' && cp > dirp)
cp--;
if (cp == dirp) {
if (debug)
(void)fprintf(stderr, "mnt unsucc\n");
syslog(LOG_ERR,
"\"%s\", line %ld: Can't export %s",
line, (unsigned long)lineno, dirp);
return (1);
}
savedc = *cp;
*cp = '\0';
}
if (addrp) {
++addrp;
if (*addrp == NULL)
@ -1883,7 +1804,8 @@ do_mount(line, lineno, ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
} else
done = TRUE;
}
if (cp)
*cp = savedc;
return (0);
}