View | Details | Raw Unified | Return to bug 237860 | Differences between
and this patch

Collapse All | Expand All

(-)usr.sbin/mountd/mountd.c (-141 / +688 lines)
Lines 49-54 __FBSDID("$FreeBSD: head/usr.sbin/mountd Link Here
49
49
50
#include <sys/param.h>
50
#include <sys/param.h>
51
#include <sys/fcntl.h>
51
#include <sys/fcntl.h>
52
#include <sys/fnv_hash.h>
52
#include <sys/linker.h>
53
#include <sys/linker.h>
53
#include <sys/module.h>
54
#include <sys/module.h>
54
#include <sys/mount.h>
55
#include <sys/mount.h>
Lines 56-61 __FBSDID("$FreeBSD: head/usr.sbin/mountd Link Here
56
#include <sys/stat.h>
57
#include <sys/stat.h>
57
#include <sys/sysctl.h>
58
#include <sys/sysctl.h>
58
#include <sys/syslog.h>
59
#include <sys/syslog.h>
60
#include <sys/sdt.h>
59
61
60
#include <rpc/rpc.h>
62
#include <rpc/rpc.h>
61
#include <rpc/rpc_com.h>
63
#include <rpc/rpc_com.h>
Lines 114-123 struct dirlist { Link Here
114
struct exportlist {
116
struct exportlist {
115
	struct dirlist	*ex_dirl;
117
	struct dirlist	*ex_dirl;
116
	struct dirlist	*ex_defdir;
118
	struct dirlist	*ex_defdir;
119
	struct grouplist *ex_grphead;
117
	int		ex_flag;
120
	int		ex_flag;
118
	fsid_t		ex_fs;
121
	fsid_t		ex_fs;
119
	char		*ex_fsdir;
122
	char		*ex_fsdir;
120
	char		*ex_indexfile;
123
	char		*ex_indexfile;
124
	struct xucred	ex_defanon;
125
	int		ex_defexflags;
121
	int		ex_numsecflavors;
126
	int		ex_numsecflavors;
122
	int		ex_secflavors[MAXSECFLAVORS];
127
	int		ex_secflavors[MAXSECFLAVORS];
123
	int		ex_defnumsecflavors;
128
	int		ex_defnumsecflavors;
Lines 127-132 struct exportlist { Link Here
127
};
132
};
128
/* ex_flag bits */
133
/* ex_flag bits */
129
#define	EX_LINKED	0x1
134
#define	EX_LINKED	0x1
135
#define	EX_DONE		0x2
136
#define	EX_DEFSET	0x4
137
#define	EX_PUBLICFH	0x8
138
139
SLIST_HEAD(exportlisthead, exportlist);
130
140
131
struct netmsk {
141
struct netmsk {
132
	struct sockaddr_storage nt_net;
142
	struct sockaddr_storage nt_net;
Lines 143-148 struct grouplist { Link Here
143
	int gr_type;
153
	int gr_type;
144
	union grouptypes gr_ptr;
154
	union grouptypes gr_ptr;
145
	struct grouplist *gr_next;
155
	struct grouplist *gr_next;
156
	struct xucred gr_anon;
157
	int gr_exflags;
158
	int gr_flag;
146
	int gr_numsecflavors;
159
	int gr_numsecflavors;
147
	int gr_secflavors[MAXSECFLAVORS];
160
	int gr_secflavors[MAXSECFLAVORS];
148
};
161
};
Lines 153-158 struct grouplist { Link Here
153
#define	GT_DEFAULT	0x3
166
#define	GT_DEFAULT	0x3
154
#define GT_IGNORE	0x5
167
#define GT_IGNORE	0x5
155
168
169
/* Group flags */
170
#define	GR_FND		0x1
171
156
struct hostlist {
172
struct hostlist {
157
	int		 ht_flag;	/* Uses DP_xx bits */
173
	int		 ht_flag;	/* Uses DP_xx bits */
158
	struct grouplist *ht_grp;
174
	struct grouplist *ht_grp;
Lines 172-178 struct fhreturn { Link Here
172
/* Global defs */
188
/* Global defs */
173
static char	*add_expdir(struct dirlist **, char *, int);
189
static char	*add_expdir(struct dirlist **, char *, int);
174
static void	add_dlist(struct dirlist **, struct dirlist *,
190
static void	add_dlist(struct dirlist **, struct dirlist *,
175
		    struct grouplist *, int, struct exportlist *);
191
		    struct grouplist *, int, struct exportlist *,
192
		    struct xucred *, int);
176
static void	add_mlist(char *, char *);
193
static void	add_mlist(char *, char *);
177
static int	check_dirpath(char *);
194
static int	check_dirpath(char *);
178
static int	check_options(struct dirlist *);
195
static int	check_options(struct dirlist *);
Lines 185-201 static void complete_service(struct netc Link Here
185
static void	clearout_service(void);
202
static void	clearout_service(void);
186
static void	del_mlist(char *hostp, char *dirp);
203
static void	del_mlist(char *hostp, char *dirp);
187
static struct dirlist	*dirp_search(struct dirlist *, char *);
204
static struct dirlist	*dirp_search(struct dirlist *, char *);
205
static int	do_export_mount(struct exportlist *, struct statfs *);
188
static int	do_mount(struct exportlist *, struct grouplist *, int,
206
static int	do_mount(struct exportlist *, struct grouplist *, int,
189
		    struct xucred *, char *, int, struct statfs *);
207
		    struct xucred *, char *, int, struct statfs *, int, int *);
190
static int	do_opt(char **, char **, struct exportlist *,
208
static int	do_opt(char **, char **, struct exportlist *,
191
		    struct grouplist *, int *, int *, struct xucred *);
209
		    struct grouplist *, int *, int *, struct xucred *);
192
static struct exportlist	*ex_search(fsid_t *);
210
static struct exportlist	*ex_search(fsid_t *, struct exportlisthead *);
193
static struct exportlist	*get_exp(void);
211
static struct exportlist	*get_exp(void);
194
static void	free_dir(struct dirlist *);
212
static void	free_dir(struct dirlist *);
195
static void	free_exp(struct exportlist *);
213
static void	free_exp(struct exportlist *);
196
static void	free_grp(struct grouplist *);
214
static void	free_grp(struct grouplist *);
197
static void	free_host(struct hostlist *);
215
static void	free_host(struct hostlist *);
198
static void	get_exportlist(void);
216
static void	free_v4rootexp(void);
217
static void	get_exportlist_one(int);
218
static void	get_exportlist(int);
219
static void	insert_exports(struct exportlist *, struct exportlisthead *);
220
static void	free_exports(struct exportlisthead *);
221
static void	read_exportfile(int);
222
static int	compare_nmount_exportlist(struct iovec *, int, char *);
223
static int	compare_export(struct exportlist *, struct exportlist *);
224
static int	compare_cred(struct xucred *, struct xucred *);
225
static int	compare_secflavor(int *, int *, int);
226
static void	delete_export(struct iovec *, int, struct statfs *, char *);
199
static int	get_host(char *, struct grouplist *, struct grouplist *);
227
static int	get_host(char *, struct grouplist *, struct grouplist *);
200
static struct hostlist *get_ht(void);
228
static struct hostlist *get_ht(void);
201
static int	get_line(void);
229
static int	get_line(void);
Lines 204-210 static int get_net(char *, struct netmsk Link Here
204
static void	getexp_err(struct exportlist *, struct grouplist *, const char *);
232
static void	getexp_err(struct exportlist *, struct grouplist *, const char *);
205
static struct grouplist	*get_grp(void);
233
static struct grouplist	*get_grp(void);
206
static void	hang_dirp(struct dirlist *, struct grouplist *,
234
static void	hang_dirp(struct dirlist *, struct grouplist *,
207
				struct exportlist *, int);
235
		    struct exportlist *, int, struct xucred *, int);
208
static void	huphandler(int sig);
236
static void	huphandler(int sig);
209
static int	makemask(struct sockaddr_storage *ssp, int bitlen);
237
static int	makemask(struct sockaddr_storage *ssp, int bitlen);
210
static void	mntsrv(struct svc_req *, SVCXPRT *);
238
static void	mntsrv(struct svc_req *, SVCXPRT *);
Lines 227-235 static int xdr_fhs(XDR *, caddr_t); Link Here
227
static int	xdr_mlist(XDR *, caddr_t);
255
static int	xdr_mlist(XDR *, caddr_t);
228
static void	terminate(int);
256
static void	terminate(int);
229
257
230
static SLIST_HEAD(, exportlist) exphead = SLIST_HEAD_INITIALIZER(exphead);
258
#define	EXPHASH(f)	(fnv_32_buf((f), sizeof(fsid_t), 0) % exphashsize)
231
static SLIST_HEAD(, mountlist) mlhead = SLIST_HEAD_INITIALIZER(mlhead);
259
static struct exportlisthead *exphead = NULL;
232
static struct grouplist *grphead;
260
static struct exportlisthead *oldexphead = NULL;
261
static int exphashsize = 0;
262
static SLIST_HEAD(, mountlist) mlhead = SLIST_HEAD_INITIALIZER(&mlhead);
233
static char *exnames_default[2] = { _PATH_EXPORTS, NULL };
263
static char *exnames_default[2] = { _PATH_EXPORTS, NULL };
234
static char **exnames;
264
static char **exnames;
235
static char **hosts = NULL;
265
static char **hosts = NULL;
Lines 260-266 static int have_v6 = 1; Link Here
260
290
261
static int v4root_phase = 0;
291
static int v4root_phase = 0;
262
static char v4root_dirpath[PATH_MAX + 1];
292
static char v4root_dirpath[PATH_MAX + 1];
293
static struct exportlist *v4root_ep = NULL;
263
static int has_publicfh = 0;
294
static int has_publicfh = 0;
295
static int has_set_publicfh = 0;
264
296
265
static struct pidfh *pfh = NULL;
297
static struct pidfh *pfh = NULL;
266
/* Bits for opt_flags above */
298
/* Bits for opt_flags above */
Lines 282-287 static void SYSLOG(int, const char *, .. Link Here
282
#else
314
#else
283
static int debug = 0;
315
static int debug = 0;
284
#endif
316
#endif
317
#define	MOUNTD_PASSNO(format, ...)
318
#define	MOUNTD_COMPAREOK(format, ...)
319
#define	MOUNTD_PASSNO_0(format, ...)
320
#define	MOUNTD_EO_GET_EXPORTLIST(format, ...)
321
#define	MOUNTD_FS_HASH(format, ...)
322
#define	MOUNTD_FOREACH_EP(format, ...)
323
#define	MOUNTD_FOUND_OLD_EXP(format, ...)
324
#define	MOUNTD_SAME_FSDIR(format, ...)
325
#define	MOUNTD_EXDONE(format, ...)
326
#define	MOUNTD_NOT_FOUND_SO_EXPORT(format, ...)
327
#define	MOUNTD_NOT_DONE_DELETE(format, ...)
328
#define	MOUNTD_DO_DELETE(format, ...)
329
#define	MOUNTD_V4ROOT_EXPATH(format, ...)
330
#define	MOUNTD_DO_MOUNT_EXPORT(format, ...)
331
#define	MOUNTD_EX_DEFEXFLAGS(format, ...)
332
#define	MOUNTD_DO_MOUNT_GR_TYPE(format, ...)
333
#define	MOUNTD_DO_MOUNT_EXFLAGS(format, ...)
334
#define	MOUNTD_DO_MOUNT_NUMSEC(format, ...)
285
335
286
/*
336
/*
287
 * Similar to strsep(), but it allows for quoted strings
337
 * Similar to strsep(), but it allows for quoted strings
Lines 368-376 main(int argc, char **argv) Link Here
368
	in_port_t svcport;
418
	in_port_t svcport;
369
	int c, k, s;
419
	int c, k, s;
370
	int maxrec = RPC_MAXDATASIZE;
420
	int maxrec = RPC_MAXDATASIZE;
371
	int attempt_cnt, port_len, port_pos, ret;
421
	int attempt_cnt, passno, port_len, port_pos, ret;
372
	char **port_list;
422
	char **port_list;
373
423
424
	passno = 0;
374
	/* Check that another mountd isn't already running. */
425
	/* Check that another mountd isn't already running. */
375
	pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
426
	pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
376
	if (pfh == NULL) {
427
	if (pfh == NULL) {
Lines 385-391 main(int argc, char **argv) Link Here
385
	else
436
	else
386
		close(s);
437
		close(s);
387
438
388
	while ((c = getopt(argc, argv, "2deh:lnp:rS")) != -1)
439
	while ((c = getopt(argc, argv, "2deh:Ilnp:rS")) != -1)
389
		switch (c) {
440
		switch (c) {
390
		case '2':
441
		case '2':
391
			force_v2 = 1;
442
			force_v2 = 1;
Lines 437-442 main(int argc, char **argv) Link Here
437
		case 'S':
488
		case 'S':
438
			suspend_nfsd = 1;
489
			suspend_nfsd = 1;
439
			break;
490
			break;
491
		case 'I':
492
			passno = 1;
493
			break;
440
		default:
494
		default:
441
			usage();
495
			usage();
442
		}
496
		}
Lines 449-455 main(int argc, char **argv) Link Here
449
503
450
	argc -= optind;
504
	argc -= optind;
451
	argv += optind;
505
	argv += optind;
452
	grphead = (struct grouplist *)NULL;
453
	if (argc > 0)
506
	if (argc > 0)
454
		exnames = argv;
507
		exnames = argv;
455
	else
508
	else
Lines 457-463 main(int argc, char **argv) Link Here
457
	openlog("mountd", LOG_PID, LOG_DAEMON);
510
	openlog("mountd", LOG_PID, LOG_DAEMON);
458
	if (debug)
511
	if (debug)
459
		warnx("getting export list");
512
		warnx("getting export list");
460
	get_exportlist();
513
	get_exportlist(0);
461
	if (debug)
514
	if (debug)
462
		warnx("getting mount list");
515
		warnx("getting mount list");
463
	get_mountlist();
516
	get_mountlist();
Lines 628-634 main(int argc, char **argv) Link Here
628
	/* Expand svc_run() here so that we can call get_exportlist(). */
681
	/* Expand svc_run() here so that we can call get_exportlist(). */
629
	for (;;) {
682
	for (;;) {
630
		if (got_sighup) {
683
		if (got_sighup) {
631
			get_exportlist();
684
			get_exportlist(passno);
632
			got_sighup = 0;
685
			got_sighup = 0;
633
		}
686
		}
634
		readfds = svc_fdset;
687
		readfds = svc_fdset;
Lines 1087-1093 mntsrv(struct svc_req *rqstp, SVCXPRT *t Link Here
1087
		if (bad)
1140
		if (bad)
1088
			ep = NULL;
1141
			ep = NULL;
1089
		else
1142
		else
1090
			ep = ex_search(&fsb.f_fsid);
1143
			ep = ex_search(&fsb.f_fsid, exphead);
1091
		hostset = defset = 0;
1144
		hostset = defset = 0;
1092
		if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset,
1145
		if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset,
1093
		    &numsecflavors, &secflavorsp) ||
1146
		    &numsecflavors, &secflavorsp) ||
Lines 1302-1322 xdr_explist_common(XDR *xdrsp, caddr_t c Link Here
1302
	int false = 0;
1355
	int false = 0;
1303
	int putdef;
1356
	int putdef;
1304
	sigset_t sighup_mask;
1357
	sigset_t sighup_mask;
1358
	int i;
1305
1359
1306
	sigemptyset(&sighup_mask);
1360
	sigemptyset(&sighup_mask);
1307
	sigaddset(&sighup_mask, SIGHUP);
1361
	sigaddset(&sighup_mask, SIGHUP);
1308
	sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
1362
	sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
1309
1363
1310
	SLIST_FOREACH(ep, &exphead, entries) {
1364
	for (i = 0; i < exphashsize; i++)
1311
		putdef = 0;
1365
		SLIST_FOREACH(ep, &exphead[i], entries) {
1312
		if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir,
1366
			putdef = 0;
1313
			       &putdef, brief))
1367
			if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir,
1314
			goto errout;
1368
				       &putdef, brief))
1315
		if (ep->ex_defdir && putdef == 0 &&
1369
				goto errout;
1316
			put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL,
1370
			if (ep->ex_defdir && putdef == 0 &&
1317
			&putdef, brief))
1371
				put_exlist(ep->ex_defdir, xdrsp, NULL,
1318
			goto errout;
1372
				&putdef, brief))
1319
	}
1373
				goto errout;
1374
		}
1320
	sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
1375
	sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
1321
	if (!xdr_bool(xdrsp, &false))
1376
	if (!xdr_bool(xdrsp, &false))
1322
		return (0);
1377
		return (0);
Lines 1416-1425 static FILE *exp_file; Link Here
1416
 * Get the export list from one, currently open file
1471
 * Get the export list from one, currently open file
1417
 */
1472
 */
1418
static void
1473
static void
1419
get_exportlist_one(void)
1474
get_exportlist_one(int passno)
1420
{
1475
{
1421
	struct exportlist *ep;
1476
	struct exportlist *ep;
1422
	struct grouplist *grp, *tgrp;
1477
	struct grouplist *grp, *tgrp, *savgrp;
1423
	struct dirlist *dirhead;
1478
	struct dirlist *dirhead;
1424
	struct statfs fsb;
1479
	struct statfs fsb;
1425
	struct xucred anon;
1480
	struct xucred anon;
Lines 1540-1546 get_exportlist_one(void) Link Here
1540
					 * See if this directory is already
1595
					 * See if this directory is already
1541
					 * in the list.
1596
					 * in the list.
1542
					 */
1597
					 */
1543
					ep = ex_search(&fsb.f_fsid);
1598
					ep = ex_search(&fsb.f_fsid, exphead);
1544
					if (ep == (struct exportlist *)NULL) {
1599
					if (ep == (struct exportlist *)NULL) {
1545
					    ep = get_exp();
1600
					    ep = get_exp();
1546
					    ep->ex_fs = fsb.f_fsid;
1601
					    ep->ex_fs = fsb.f_fsid;
Lines 1653-1663 get_exportlist_one(void) Link Here
1653
		 * Loop through hosts, pushing the exports into the kernel.
1708
		 * Loop through hosts, pushing the exports into the kernel.
1654
		 * After loop, tgrp points to the start of the list and
1709
		 * After loop, tgrp points to the start of the list and
1655
		 * grp points to the last entry in the list.
1710
		 * grp points to the last entry in the list.
1711
		 * Do not do the do_mount() for passno == 1, since the
1712
		 * second pass will do it, as required.
1656
		 */
1713
		 */
1657
		grp = tgrp;
1714
		grp = tgrp;
1658
		do {
1715
		do {
1659
			if (do_mount(ep, grp, exflags, &anon, dirp, dirplen,
1716
			grp->gr_exflags = exflags;
1660
			    &fsb)) {
1717
			grp->gr_anon = anon;
1718
			if (passno == 0 && do_mount(ep, grp, exflags, &anon,
1719
			    dirp, dirplen, &fsb, ep->ex_numsecflavors,
1720
			    ep->ex_secflavors)) {
1661
				getexp_err(ep, tgrp, NULL);
1721
				getexp_err(ep, tgrp, NULL);
1662
				goto nextline;
1722
				goto nextline;
1663
			}
1723
			}
Lines 1668-1676 get_exportlist_one(void) Link Here
1668
		 */
1728
		 */
1669
		if (v4root_phase > 0 && v4root_phase <= 2) {
1729
		if (v4root_phase > 0 && v4root_phase <= 2) {
1670
			/*
1730
			/*
1671
			 * Since these structures aren't used by mountd,
1731
			 * These structures are used for the "-I" reload,
1732
			 * so save them for that case.  Otherwise, just
1672
			 * free them up now.
1733
			 * free them up now.
1673
			 */
1734
			 */
1735
			if (passno == 1 && ep != NULL) {
1736
				savgrp = tgrp;
1737
				while (tgrp != NULL) {
1738
					/*
1739
					 * Save the security flavors and exflags
1740
					 * for this host set in the groups.
1741
					 */
1742
					tgrp->gr_numsecflavors =
1743
					    ep->ex_numsecflavors;
1744
					if (ep->ex_numsecflavors > 0)
1745
						memcpy(tgrp->gr_secflavors,
1746
						    ep->ex_secflavors,
1747
						    sizeof(ep->ex_secflavors));
1748
					tgrp = tgrp->gr_next;
1749
				}
1750
				if (v4root_ep == NULL) {
1751
					v4root_ep = ep;
1752
					ep = NULL;	/* Don't free below. */
1753
				}
1754
				grp->gr_next = v4root_ep->ex_grphead;
1755
				v4root_ep->ex_grphead = savgrp;
1756
			}
1674
			if (ep != NULL)
1757
			if (ep != NULL)
1675
				free_exp(ep);
1758
				free_exp(ep);
1676
			while (tgrp != NULL) {
1759
			while (tgrp != NULL) {
Lines 1685-1701 get_exportlist_one(void) Link Here
1685
		 * Success. Update the data structures.
1768
		 * Success. Update the data structures.
1686
		 */
1769
		 */
1687
		if (has_host) {
1770
		if (has_host) {
1688
			hang_dirp(dirhead, tgrp, ep, opt_flags);
1771
			hang_dirp(dirhead, tgrp, ep, opt_flags, &anon, exflags);
1689
			grp->gr_next = grphead;
1772
			grp->gr_next = ep->ex_grphead;
1690
			grphead = tgrp;
1773
			ep->ex_grphead = tgrp;
1691
		} else {
1774
		} else {
1692
			hang_dirp(dirhead, (struct grouplist *)NULL, ep,
1775
			hang_dirp(dirhead, (struct grouplist *)NULL, ep,
1693
				opt_flags);
1776
				opt_flags, &anon, exflags);
1694
			free_grp(grp);
1777
			free_grp(grp);
1695
		}
1778
		}
1696
		dirhead = (struct dirlist *)NULL;
1779
		dirhead = (struct dirlist *)NULL;
1697
		if ((ep->ex_flag & EX_LINKED) == 0) {
1780
		if ((ep->ex_flag & EX_LINKED) == 0) {
1698
			SLIST_INSERT_HEAD(&exphead, ep, entries);
1781
			insert_exports(ep, exphead);
1699
1782
1700
			ep->ex_flag |= EX_LINKED;
1783
			ep->ex_flag |= EX_LINKED;
1701
		}
1784
		}
Lines 1712-1758 nextline: Link Here
1712
 * Get the export list from all specified files
1795
 * Get the export list from all specified files
1713
 */
1796
 */
1714
static void
1797
static void
1715
get_exportlist(void)
1798
get_exportlist(int passno)
1716
{
1799
{
1717
	struct exportlist *ep, *ep2;
1718
	struct grouplist *grp, *tgrp;
1719
	struct export_args export;
1800
	struct export_args export;
1720
	struct iovec *iov;
1801
	struct iovec *iov;
1721
	struct statfs *fsp, *mntbufp;
1802
	struct statfs *mntbufp;
1722
	struct xvfsconf vfc;
1723
	char errmsg[255];
1803
	char errmsg[255];
1724
	int num, i;
1804
	int num, i;
1725
	int iovlen;
1805
	int iovlen;
1726
	int done;
1727
	struct nfsex_args eargs;
1806
	struct nfsex_args eargs;
1728
1807
1729
	if (suspend_nfsd != 0)
1808
	MOUNTD_PASSNO("passno", passno);
1730
		(void)nfssvc(NFSSVC_SUSPENDNFSD, NULL);
1731
	v4root_dirpath[0] = '\0';
1809
	v4root_dirpath[0] = '\0';
1810
	free_v4rootexp();
1811
	if (passno == 1) {
1812
		/*
1813
		 * Save the current lists as old ones, so that the new lists
1814
		 * can be compared with the old ones in the 2nd pass.
1815
		 */
1816
		for (i = 0; i < exphashsize; i++) {
1817
			SLIST_FIRST(&oldexphead[i]) = SLIST_FIRST(&exphead[i]);
1818
			SLIST_INIT(&exphead[i]);
1819
		}
1820
1821
		/* Note that the public fh has not yet been set. */
1822
		has_set_publicfh = 0;
1823
1824
		/* Read the export file(s) and process them */
1825
		read_exportfile(passno);
1826
	} else {
1827
		/*
1828
		 * Just make the old lists empty.
1829
		 * exphashsize == 0 for the first call, before oldexphead
1830
		 * has been initialized-->loop won't be executed.
1831
		 */
1832
		for (i = 0; i < exphashsize; i++)
1833
			SLIST_INIT(&oldexphead[i]);
1834
	}
1835
1732
	bzero(&export, sizeof(export));
1836
	bzero(&export, sizeof(export));
1733
	export.ex_flags = MNT_DELEXPORT;
1837
	export.ex_flags = MNT_DELEXPORT;
1734
	iov = NULL;
1838
	iov = NULL;
1735
	iovlen = 0;
1839
	iovlen = 0;
1736
	bzero(errmsg, sizeof(errmsg));
1840
	bzero(errmsg, sizeof(errmsg));
1737
1841
1842
	if (suspend_nfsd != 0)
1843
		(void)nfssvc(NFSSVC_SUSPENDNFSD, NULL);
1738
	/*
1844
	/*
1739
	 * First, get rid of the old list
1845
	 * Delete the old V4 root dir.
1740
	 */
1741
	SLIST_FOREACH_SAFE(ep, &exphead, entries, ep2) {
1742
		SLIST_REMOVE(&exphead, ep, exportlist, entries);
1743
		free_exp(ep);
1744
	}
1745
1746
	grp = grphead;
1747
	while (grp) {
1748
		tgrp = grp;
1749
		grp = grp->gr_next;
1750
		free_grp(tgrp);
1751
	}
1752
	grphead = (struct grouplist *)NULL;
1753
1754
	/*
1755
	 * and the old V4 root dir.
1756
	 */
1846
	 */
1757
	bzero(&eargs, sizeof (eargs));
1847
	bzero(&eargs, sizeof (eargs));
1758
	eargs.export.ex_flags = MNT_DELEXPORT;
1848
	eargs.export.ex_flags = MNT_DELEXPORT;
Lines 1760-1826 get_exportlist(void) Link Here
1760
	    errno != ENOENT)
1850
	    errno != ENOENT)
1761
		syslog(LOG_ERR, "Can't delete exports for V4:");
1851
		syslog(LOG_ERR, "Can't delete exports for V4:");
1762
1852
1763
	/*
1853
	build_iovec(&iov, &iovlen, "fstype", NULL, 0);
1764
	 * and clear flag that notes if a public fh has been exported.
1854
	build_iovec(&iov, &iovlen, "fspath", NULL, 0);
1765
	 */
1855
	build_iovec(&iov, &iovlen, "from", NULL, 0);
1766
	has_publicfh = 0;
1856
	build_iovec(&iov, &iovlen, "update", NULL, 0);
1857
	build_iovec(&iov, &iovlen, "export", &export,
1858
	    sizeof(export));
1859
	build_iovec(&iov, &iovlen, "errmsg", errmsg,
1860
	    sizeof(errmsg));
1767
1861
1768
	/*
1862
	/*
1769
	 * And delete exports that are in the kernel for all local
1863
	 * For passno == 1, compare the old and new lists updating the kernel
1770
	 * filesystems.
1864
	 * exports for any cases that have changed.
1771
	 * XXX: Should know how to handle all local exportable filesystems.
1865
	 * This call is doing the second pass through the lists.
1866
	 * If it fails, fall back on the bulk reload.
1772
	 */
1867
	 */
1773
	num = getmntinfo(&mntbufp, MNT_NOWAIT);
1868
	if (passno == 1 && compare_nmount_exportlist(iov, iovlen, errmsg) ==
1774
1869
	    0) {
1775
	if (num > 0) {
1870
		MOUNTD_COMPAREOK("compareok");
1776
		build_iovec(&iov, &iovlen, "fstype", NULL, 0);
1871
		/* Free up the old lists. */
1777
		build_iovec(&iov, &iovlen, "fspath", NULL, 0);
1872
		free_exports(oldexphead);
1778
		build_iovec(&iov, &iovlen, "from", NULL, 0);
1873
	} else {
1779
		build_iovec(&iov, &iovlen, "update", NULL, 0);
1874
		MOUNTD_PASSNO_0("doing passno=0");
1780
		build_iovec(&iov, &iovlen, "export", &export, sizeof(export));
1875
		/*
1781
		build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
1876
		 * Clear flag that notes if a public fh has been exported.
1782
	}
1877
		 * It is set by do_mount() if MNT_EXPUBLIC is set for the entry.
1878
		 */
1879
		has_publicfh = 0;
1783
1880
1784
	for (i = 0; i < num; i++) {
1881
		/* exphead == NULL if not yet allocated (first call). */
1785
		fsp = &mntbufp[i];
1882
		if (exphead != NULL) {
1786
		if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) {
1883
			/*
1787
			syslog(LOG_ERR, "getvfsbyname() failed for %s",
1884
			 * First, get rid of the old lists.
1788
			    fsp->f_fstypename);
1885
			 */
1789
			continue;
1886
			free_exports(exphead);
1887
			free_exports(oldexphead);
1790
		}
1888
		}
1791
1889
1792
		/*
1890
		/*
1793
		 * We do not need to delete "export" flag from
1891
		 * And delete exports that are in the kernel for all local
1794
		 * filesystems that do not have it set.
1892
		 * filesystems.
1795
		 */
1893
		 * XXX: Should know how to handle all local exportable
1796
		if (!(fsp->f_flags & MNT_EXPORTED))
1894
		 * filesystems.
1797
		    continue;
1895
		 */
1798
		/*
1896
		num = getmntinfo(&mntbufp, MNT_NOWAIT);
1799
		 * Do not delete export for network filesystem by
1897
1800
		 * passing "export" arg to nmount().
1898
		/* Allocate hash tables, for first call. */
1801
		 * It only makes sense to do this for local filesystems.
1899
		if (exphead == NULL) {
1802
		 */
1900
			/* Target an average linked list length of 10. */
1803
		if (vfc.vfc_flags & VFCF_NETWORK)
1901
			exphashsize = num / 10;
1804
			continue;
1902
			if (exphashsize < 1)
1805
1903
				exphashsize = 1;
1806
		iov[1].iov_base = fsp->f_fstypename;
1904
			else if (exphashsize > 100000)
1807
		iov[1].iov_len = strlen(fsp->f_fstypename) + 1;
1905
				exphashsize = 100000;
1808
		iov[3].iov_base = fsp->f_mntonname;
1906
			exphead = malloc(exphashsize * sizeof(*exphead));
1809
		iov[3].iov_len = strlen(fsp->f_mntonname) + 1;
1907
			oldexphead = malloc(exphashsize * sizeof(*oldexphead));
1810
		iov[5].iov_base = fsp->f_mntfromname;
1908
			if (exphead == NULL || oldexphead == NULL)
1811
		iov[5].iov_len = strlen(fsp->f_mntfromname) + 1;
1909
				errx(1, "Can't malloc hash tables");
1812
		errmsg[0] = '\0';
1910
1813
1911
			for (i = 0; i < exphashsize; i++) {
1814
		/*
1912
				SLIST_INIT(&exphead[i]);
1815
		 * EXDEV is returned when path exists but is not a
1913
				SLIST_INIT(&oldexphead[i]);
1816
		 * mount point.  May happens if raced with unmount.
1914
			}
1817
		 */
1818
		if (nmount(iov, iovlen, fsp->f_flags) < 0 &&
1819
		    errno != ENOENT && errno != ENOTSUP && errno != EXDEV) {
1820
			syslog(LOG_ERR,
1821
			    "can't delete exports for %s: %m %s",
1822
			    fsp->f_mntonname, errmsg);
1823
		}
1915
		}
1916
	
1917
		for (i = 0; i < num; i++)
1918
			delete_export(iov, iovlen, &mntbufp[i], errmsg);
1919
1920
1921
		/* Read the export file(s) and process them */
1922
		read_exportfile(0);
1824
	}
1923
	}
1825
1924
1826
	if (iov != NULL) {
1925
	if (iov != NULL) {
Lines 1838-1843 get_exportlist(void) Link Here
1838
	}
1937
	}
1839
1938
1840
	/*
1939
	/*
1940
	 * If there was no public fh, clear any previous one set.
1941
	 */
1942
	if (has_publicfh == 0) {
1943
		(void) nfssvc(NFSSVC_NOPUBLICFH, NULL);
1944
	}
1945
1946
	/* Resume the nfsd. If they weren't suspended, this is harmless. */
1947
	(void)nfssvc(NFSSVC_RESUMENFSD, NULL);
1948
	MOUNTD_EO_GET_EXPORTLIST("eo get exportlist");
1949
}
1950
1951
/*
1952
 * Insert an export entry in the appropriate list.
1953
 */
1954
static void
1955
insert_exports(struct exportlist *ep, struct exportlisthead *exhp)
1956
{
1957
	uint32_t i;
1958
1959
	i = EXPHASH(&ep->ex_fs);
1960
	MOUNTD_FS_HASH("fs hash", ep->ex_fsdir, i);
1961
	SLIST_INSERT_HEAD(&exhp[i], ep, entries);
1962
}
1963
1964
/*
1965
 * Free up the exports lists passed in as arguments.
1966
 */
1967
static void
1968
free_exports(struct exportlisthead *exhp)
1969
{
1970
	struct exportlist *ep, *ep2;
1971
	int i;
1972
1973
	for (i = 0; i < exphashsize; i++) {
1974
		SLIST_FOREACH_SAFE(ep, &exhp[i], entries, ep2) {
1975
			SLIST_REMOVE(&exhp[i], ep, exportlist, entries);
1976
			free_exp(ep);
1977
		}
1978
		SLIST_INIT(&exhp[i]);
1979
	}
1980
}
1981
1982
/*
1983
 * Read the exports file(s) and call get_exportlist_one() for each line.
1984
 */
1985
static void
1986
read_exportfile(int passno)
1987
{
1988
	int done, i;
1989
1990
	/*
1841
	 * Read in the exports file and build the list, calling
1991
	 * Read in the exports file and build the list, calling
1842
	 * nmount() as we go along to push the export rules into the kernel.
1992
	 * nmount() as we go along to push the export rules into the kernel.
1843
	 */
1993
	 */
Lines 1849-1855 get_exportlist(void) Link Here
1849
			syslog(LOG_WARNING, "can't open %s", exnames[i]);
1999
			syslog(LOG_WARNING, "can't open %s", exnames[i]);
1850
			continue;
2000
			continue;
1851
		}
2001
		}
1852
		get_exportlist_one();
2002
		get_exportlist_one(passno);
1853
		fclose(exp_file);
2003
		fclose(exp_file);
1854
		done++;
2004
		done++;
1855
	}
2005
	}
Lines 1857-1871 get_exportlist(void) Link Here
1857
		syslog(LOG_ERR, "can't open any exports file");
2007
		syslog(LOG_ERR, "can't open any exports file");
1858
		exit(2);
2008
		exit(2);
1859
	}
2009
	}
2010
}
2011
2012
/*
2013
 * Compare the export lists against the old ones and do nmount() operations
2014
 * for any cases that have changed.  This avoids doing nmount() for entries
2015
 * that have not changed.
2016
 * Return 0 upon success, 1 otherwise.
2017
 */
2018
static int
2019
compare_nmount_exportlist(struct iovec *iov, int iovlen, char *errmsg)
2020
{
2021
	struct exportlist *ep, *oep;
2022
	struct grouplist *grp;
2023
	struct statfs fs, ofs;
2024
	int i, ret;
1860
2025
1861
	/*
2026
	/*
1862
	 * If there was no public fh, clear any previous one set.
2027
	 * Loop through the current list and look for an entry in the old
2028
	 * list.
2029
	 * If found, check to see if it the same.
2030
	 *        If it is not the same, delete and re-export.
2031
	 *        Then mark it done on the old list.
2032
	 * else (not found)
2033
	 *        export it.
2034
	 * Any entries left in the old list after processing must have their
2035
	 * exports deleted.
1863
	 */
2036
	 */
1864
	if (has_publicfh == 0)
2037
	for (i = 0; i < exphashsize; i++)
1865
		(void) nfssvc(NFSSVC_NOPUBLICFH, NULL);
2038
		SLIST_FOREACH(ep, &exphead[i], entries) {
2039
			MOUNTD_FOREACH_EP("foreach ep", ep->ex_fsdir);
2040
			oep = ex_search(&ep->ex_fs, oldexphead);
2041
			if (oep != NULL) {
2042
				/*
2043
				 * Check the mount paths are the same.
2044
				 * If not, return 1 so that the reload of the
2045
				 * exports will be done in bulk, the
2046
				 * passno == 0 way.
2047
				 */
2048
				MOUNTD_FOUND_OLD_EXP("found old exp");
2049
				if (strcmp(ep->ex_fsdir, oep->ex_fsdir) != 0)
2050
					return (1);
2051
				MOUNTD_SAME_FSDIR("same fsdir");
2052
				/*
2053
				 * Test to see if the entry is the same.
2054
				 * If not the same delete exports and
2055
				 * re-export.
2056
				 */
2057
				if (compare_export(ep, oep) != 0) {
2058
					/*
2059
					 * Clear has_publicfh if if was set
2060
					 * in the old exports, but only if it
2061
					 * has not been set during processing of
2062
					 * the exports for this pass, as
2063
					 * indicated by has_set_publicfh.
2064
					 */
2065
					if (has_set_publicfh == 0 &&
2066
					    (oep->ex_flag & EX_PUBLICFH) != 0)
2067
						has_publicfh = 0;
1866
2068
1867
	/* Resume the nfsd. If they weren't suspended, this is harmless. */
2069
					/* Delete and re-export. */
1868
	(void)nfssvc(NFSSVC_RESUMENFSD, NULL);
2070
					if (statfs(ep->ex_fsdir, &fs) < 0)
2071
						return (1);
2072
					delete_export(iov, iovlen, &fs, errmsg);
2073
					ret = do_export_mount(ep, &fs);
2074
					if (ret != 0)
2075
						return (ret);
2076
				}
2077
				oep->ex_flag |= EX_DONE;
2078
				MOUNTD_EXDONE("exdone");
2079
			} else {
2080
				MOUNTD_NOT_FOUND_SO_EXPORT(
2081
				    "not found so export");
2082
				/* Not found, so do export. */
2083
				if (statfs(ep->ex_fsdir, &fs) < 0)
2084
					return (1);
2085
				ret = do_export_mount(ep, &fs);
2086
				if (ret != 0)
2087
					return (ret);
2088
			}
2089
		}
2090
2091
	/* Delete exports not done. */
2092
	for (i = 0; i < exphashsize; i++)
2093
		SLIST_FOREACH(oep, &oldexphead[i], entries) {
2094
			if ((oep->ex_flag & EX_DONE) == 0) {
2095
				MOUNTD_NOT_DONE_DELETE("not done delete",
2096
					oep->ex_fsdir);
2097
				if (statfs(oep->ex_fsdir, &ofs) >= 0 &&
2098
				    oep->ex_fs.val[0] == ofs.f_fsid.val[0] &&
2099
				    oep->ex_fs.val[1] == ofs.f_fsid.val[1]) {
2100
					MOUNTD_DO_DELETE("do_delete");
2101
					/*
2102
					 * Clear has_publicfh if if was set
2103
					 * in the old exports, but only if it
2104
					 * has not been set during processing of
2105
					 * the exports for this pass, as
2106
					 * indicated by has_set_publicfh.
2107
					 */
2108
					if (has_set_publicfh == 0 &&
2109
					    (oep->ex_flag & EX_PUBLICFH) != 0)
2110
						has_publicfh = 0;
2111
2112
					delete_export(iov, iovlen, &ofs,
2113
					    errmsg);
2114
				}
2115
			}
2116
		}
2117
2118
	/* Do the V4 root exports, as required. */
2119
	grp = NULL;
2120
	if (v4root_ep != NULL)
2121
		grp = v4root_ep->ex_grphead;
2122
	v4root_phase = 2;
2123
	while (v4root_ep != NULL && grp != NULL) {
2124
		MOUNTD_V4ROOT_EXPATH("v4root expath", v4root_dirpath);
2125
		ret = do_mount(v4root_ep, grp, grp->gr_exflags, &grp->gr_anon,
2126
		    v4root_dirpath, strlen(v4root_dirpath), &fs,
2127
		    grp->gr_numsecflavors, grp->gr_secflavors);
2128
		if (ret != 0) {
2129
			v4root_phase = 0;
2130
			return (ret);
2131
		}
2132
		grp = grp->gr_next;
2133
	}
2134
	v4root_phase = 0;
2135
	free_v4rootexp();
2136
	return (0);
2137
}
2138
2139
/*
2140
 * Compare old and current exportlist entries for the fsid and return 0
2141
 * if they are the same, 1 otherwise.
2142
 */
2143
static int
2144
compare_export(struct exportlist *ep, struct exportlist *oep)
2145
{
2146
	struct grouplist *grp, *ogrp;
2147
2148
	if (strcmp(ep->ex_fsdir, oep->ex_fsdir) != 0)
2149
		return (1);
2150
	if ((ep->ex_flag & EX_DEFSET) != (oep->ex_flag & EX_DEFSET))
2151
		return (1);
2152
	if ((ep->ex_defdir != NULL && oep->ex_defdir == NULL) ||
2153
	    (ep->ex_defdir == NULL && oep->ex_defdir != NULL))
2154
		return (1);
2155
	if (ep->ex_defdir != NULL && (ep->ex_defdir->dp_flag & DP_DEFSET) !=
2156
	    (oep->ex_defdir->dp_flag & DP_DEFSET))
2157
		return (1);
2158
	if ((ep->ex_flag & EX_DEFSET) != 0 && (ep->ex_defnumsecflavors !=
2159
	    oep->ex_defnumsecflavors || ep->ex_defexflags !=
2160
	    oep->ex_defexflags || compare_cred(&ep->ex_defanon,
2161
	    &oep->ex_defanon) != 0 || compare_secflavor(ep->ex_defsecflavors,
2162
	    oep->ex_defsecflavors, ep->ex_defnumsecflavors) != 0))
2163
		return (1);
2164
2165
	/* Now, check all the groups. */
2166
	for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp = ogrp->gr_next)
2167
		ogrp->gr_flag = 0;
2168
	for (grp = ep->ex_grphead; grp != NULL; grp = grp->gr_next) {
2169
		for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp =
2170
		    ogrp->gr_next)
2171
			if ((ogrp->gr_flag & GR_FND) == 0 &&
2172
			    grp->gr_numsecflavors == ogrp->gr_numsecflavors &&
2173
			    grp->gr_exflags == ogrp->gr_exflags &&
2174
			    compare_cred(&grp->gr_anon, &ogrp->gr_anon) == 0 &&
2175
			    compare_secflavor(grp->gr_secflavors,
2176
			    ogrp->gr_secflavors, grp->gr_numsecflavors) == 0)
2177
				break;
2178
		if (ogrp != NULL)
2179
			ogrp->gr_flag |= GR_FND;
2180
		else
2181
			return (1);
2182
	}
2183
	for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp = ogrp->gr_next)
2184
		if ((ogrp->gr_flag & GR_FND) == 0)
2185
			return (1);
2186
	return (0);
2187
}
2188
2189
/*
2190
 * Compare to struct xucred's.  Return 0 if the same and 1 otherwise.
2191
 */
2192
static int
2193
compare_cred(struct xucred *cr0, struct xucred *cr1)
2194
{
2195
	int fnd, grp_fnd[XU_NGROUPS], i, j;
2196
2197
	if (cr0->cr_uid != cr1->cr_uid || cr0->cr_ngroups != cr1->cr_ngroups)
2198
		return (1);
2199
2200
	/* Handle common cases. */
2201
	if (cr0->cr_ngroups == 0)
2202
		return (0);
2203
	if (cr0->cr_ngroups == 1) {
2204
		if (cr0->cr_groups[0] == cr1->cr_groups[0])
2205
			return (0);
2206
		return (1);
2207
	}
2208
	if (memcmp(cr0->cr_groups, cr1->cr_groups, sizeof(*cr0->cr_groups) *
2209
	    cr0->cr_ngroups) == 0)
2210
		return (0);
2211
2212
	for (i = 0; i < cr0->cr_ngroups; i++)
2213
		grp_fnd[i] = 0;
2214
	/*
2215
	 * Search through the old and new groups lists, noting matches.
2216
	 * Since there is no ordering and duplicates can exist in the lists,
2217
	 * the algorithm is inefficient.  However cr_ngroups is small and
2218
	 * the common cases are handled above.
2219
	 */
2220
	for (i = 0; i < cr0->cr_ngroups; i++) {
2221
		fnd = 0;
2222
		for (j = 0; j < cr0->cr_ngroups; j++) {
2223
			if (cr0->cr_groups[i] == cr1->cr_groups[j]) {
2224
				grp_fnd[j] = 1;
2225
				fnd = 1;
2226
			}
2227
		}
2228
		if (fnd == 0)
2229
			return (1);
2230
	}
2231
	for (i = 0; i < cr0->cr_ngroups; i++)
2232
		if (grp_fnd[i] == 0)
2233
			return (1);
2234
	return (0);
2235
}
2236
2237
/*
2238
 * Compare two lists of security flavors.  Return 0 if the same and 1 otherwise.
2239
 * This is almost identical to compare_cred(), but I didn't factor out
2240
 * the algorithm, since compare_cred() may need to change if/when more than
2241
 * XU_NGROUPS groups are supported.
2242
 */
2243
static int
2244
compare_secflavor(int *sec1, int *sec2, int nsec)
2245
{
2246
	int fnd, sec_fnd[MAXSECFLAVORS], i, j;
2247
2248
	/* Handle common cases first. */
2249
	if (nsec == 0)
2250
		return (0);
2251
	if (nsec == 1) {
2252
		if (sec1[0] == sec2[0])
2253
			return (0);
2254
		return (1);
2255
	}
2256
	if (memcmp(sec1, sec2, sizeof(*sec1) * nsec) == 0)
2257
		return (0);
2258
2259
	for (i = 0; i < nsec; i++)
2260
		sec_fnd[i] = 0;
2261
	/*
2262
	 * Search the new group list starting at the same position in the
2263
	 * Search through the old and new secflavors lists, noting matches.
2264
	 * Since there is no ordering and duplicates can exist in the lists,
2265
	 * the algorithm is inefficient.  However nsec is small and
2266
	 * the common cases are handled above.
2267
	 */
2268
	for (i = 0; i < nsec; i++) {
2269
		fnd = 0;
2270
		for (j = 0; j < nsec; j++) {
2271
			if (sec1[i] == sec2[j]) {
2272
				sec_fnd[j] = 1;
2273
				fnd = 1;
2274
			}
2275
		}
2276
		if (fnd == 0)
2277
			return (1);
2278
	}
2279
	for (i = 0; i < nsec; i++)
2280
		if (sec_fnd[i] == 0)
2281
			return (1);
2282
	return (0);
2283
}
2284
2285
/*
2286
 * Delete an exports entry.
2287
 */
2288
static void
2289
delete_export(struct iovec *iov, int iovlen, struct statfs *fsp, char *errmsg)
2290
{
2291
	struct xvfsconf vfc;
2292
2293
	if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) {
2294
		syslog(LOG_ERR, "getvfsbyname() failed for %s",
2295
		    fsp->f_fstypename);
2296
		return;
2297
	}
2298
	
2299
	/*
2300
	 * We do not need to delete "export" flag from
2301
	 * filesystems that do not have it set.
2302
	 */
2303
	if (!(fsp->f_flags & MNT_EXPORTED))
2304
		return;
2305
	/*
2306
	 * Do not delete export for network filesystem by
2307
	 * passing "export" arg to nmount().
2308
	 * It only makes sense to do this for local filesystems.
2309
	 */
2310
	if (vfc.vfc_flags & VFCF_NETWORK)
2311
		return;
2312
	
2313
	iov[1].iov_base = fsp->f_fstypename;
2314
	iov[1].iov_len = strlen(fsp->f_fstypename) + 1;
2315
	iov[3].iov_base = fsp->f_mntonname;
2316
	iov[3].iov_len = strlen(fsp->f_mntonname) + 1;
2317
	iov[5].iov_base = fsp->f_mntfromname;
2318
	iov[5].iov_len = strlen(fsp->f_mntfromname) + 1;
2319
	errmsg[0] = '\0';
2320
	
2321
	/*
2322
	 * EXDEV is returned when path exists but is not a
2323
	 * mount point.  May happens if raced with unmount.
2324
	 */
2325
	if (nmount(iov, iovlen, fsp->f_flags) < 0 && errno != ENOENT &&
2326
	    errno != ENOTSUP && errno != EXDEV) {
2327
		syslog(LOG_ERR,
2328
		    "can't delete exports for %s: %m %s",
2329
		    fsp->f_mntonname, errmsg);
2330
	}
1869
}
2331
}
1870
2332
1871
/*
2333
/*
Lines 1924-1934 getexp_err(struct exportlist *ep, struct Link Here
1924
 * Search the export list for a matching fs.
2386
 * Search the export list for a matching fs.
1925
 */
2387
 */
1926
static struct exportlist *
2388
static struct exportlist *
1927
ex_search(fsid_t *fsid)
2389
ex_search(fsid_t *fsid, struct exportlisthead *exhp)
1928
{
2390
{
1929
	struct exportlist *ep;
2391
	struct exportlist *ep;
2392
	uint32_t i;
1930
2393
1931
	SLIST_FOREACH(ep, &exphead, entries) {
2394
	i = EXPHASH(fsid);
2395
	SLIST_FOREACH(ep, &exhp[i], entries) {
1932
		if (ep->ex_fs.val[0] == fsid->val[0] &&
2396
		if (ep->ex_fs.val[0] == fsid->val[0] &&
1933
		    ep->ex_fs.val[1] == fsid->val[1])
2397
		    ep->ex_fs.val[1] == fsid->val[1])
1934
			return (ep);
2398
			return (ep);
Lines 1965-1971 add_expdir(struct dirlist **dpp, char *c Link Here
1965
 */
2429
 */
1966
static void
2430
static void
1967
hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
2431
hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
1968
	int flags)
2432
	int flags, struct xucred *anoncrp, int exflags)
1969
{
2433
{
1970
	struct hostlist *hp;
2434
	struct hostlist *hp;
1971
	struct dirlist *dp2;
2435
	struct dirlist *dp2;
Lines 1976-1987 hang_dirp(struct dirlist *dp, struct gro Link Here
1976
		else
2440
		else
1977
			ep->ex_defdir = dp;
2441
			ep->ex_defdir = dp;
1978
		if (grp == (struct grouplist *)NULL) {
2442
		if (grp == (struct grouplist *)NULL) {
2443
			ep->ex_flag |= EX_DEFSET;
1979
			ep->ex_defdir->dp_flag |= DP_DEFSET;
2444
			ep->ex_defdir->dp_flag |= DP_DEFSET;
1980
			/* Save the default security flavors list. */
2445
			/* Save the default security flavors list. */
1981
			ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2446
			ep->ex_defnumsecflavors = ep->ex_numsecflavors;
1982
			if (ep->ex_numsecflavors > 0)
2447
			if (ep->ex_numsecflavors > 0)
1983
				memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2448
				memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
1984
				    sizeof(ep->ex_secflavors));
2449
				    sizeof(ep->ex_secflavors));
2450
			ep->ex_defanon = *anoncrp;
2451
			ep->ex_defexflags = exflags;
1985
		} else while (grp) {
2452
		} else while (grp) {
1986
			hp = get_ht();
2453
			hp = get_ht();
1987
			hp->ht_grp = grp;
2454
			hp->ht_grp = grp;
Lines 2001-2007 hang_dirp(struct dirlist *dp, struct gro Link Here
2001
		 */
2468
		 */
2002
		while (dp) {
2469
		while (dp) {
2003
			dp2 = dp->dp_left;
2470
			dp2 = dp->dp_left;
2004
			add_dlist(&ep->ex_dirl, dp, grp, flags, ep);
2471
			add_dlist(&ep->ex_dirl, dp, grp, flags, ep, anoncrp,
2472
			    exflags);
2005
			dp = dp2;
2473
			dp = dp2;
2006
		}
2474
		}
2007
	}
2475
	}
Lines 2013-2019 hang_dirp(struct dirlist *dp, struct gro Link Here
2013
 */
2481
 */
2014
static void
2482
static void
2015
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
2483
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
2016
	int flags, struct exportlist *ep)
2484
	int flags, struct exportlist *ep, struct xucred *anoncrp, int exflags)
2017
{
2485
{
2018
	struct dirlist *dp;
2486
	struct dirlist *dp;
2019
	struct hostlist *hp;
2487
	struct hostlist *hp;
Lines 2023-2032 add_dlist(struct dirlist **dpp, struct d Link Here
2023
	if (dp) {
2491
	if (dp) {
2024
		cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
2492
		cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
2025
		if (cmp > 0) {
2493
		if (cmp > 0) {
2026
			add_dlist(&dp->dp_left, newdp, grp, flags, ep);
2494
			add_dlist(&dp->dp_left, newdp, grp, flags, ep, anoncrp,
2495
			    exflags);
2027
			return;
2496
			return;
2028
		} else if (cmp < 0) {
2497
		} else if (cmp < 0) {
2029
			add_dlist(&dp->dp_right, newdp, grp, flags, ep);
2498
			add_dlist(&dp->dp_right, newdp, grp, flags, ep, anoncrp,
2499
			    exflags);
2030
			return;
2500
			return;
2031
		} else
2501
		} else
2032
			free((caddr_t)newdp);
2502
			free((caddr_t)newdp);
Lines 2053-2064 add_dlist(struct dirlist **dpp, struct d Link Here
2053
			grp = grp->gr_next;
2523
			grp = grp->gr_next;
2054
		} while (grp);
2524
		} while (grp);
2055
	} else {
2525
	} else {
2526
		ep->ex_flag |= EX_DEFSET;
2056
		dp->dp_flag |= DP_DEFSET;
2527
		dp->dp_flag |= DP_DEFSET;
2057
		/* Save the default security flavors list. */
2528
		/* Save the default security flavors list. */
2058
		ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2529
		ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2059
		if (ep->ex_numsecflavors > 0)
2530
		if (ep->ex_numsecflavors > 0)
2060
			memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2531
			memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2061
			    sizeof(ep->ex_secflavors));
2532
			    sizeof(ep->ex_secflavors));
2533
		ep->ex_defanon = *anoncrp;
2534
		ep->ex_defexflags = exflags;
2062
	}
2535
	}
2063
}
2536
}
2064
2537
Lines 2403-2408 get_host(char *cp, struct grouplist *grp Link Here
2403
static void
2876
static void
2404
free_exp(struct exportlist *ep)
2877
free_exp(struct exportlist *ep)
2405
{
2878
{
2879
	struct grouplist *grp, *tgrp;
2406
2880
2407
	if (ep->ex_defdir) {
2881
	if (ep->ex_defdir) {
2408
		free_host(ep->ex_defdir->dp_hosts);
2882
		free_host(ep->ex_defdir->dp_hosts);
Lines 2413-2422 free_exp(struct exportlist *ep) Link Here
2413
	if (ep->ex_indexfile)
2887
	if (ep->ex_indexfile)
2414
		free(ep->ex_indexfile);
2888
		free(ep->ex_indexfile);
2415
	free_dir(ep->ex_dirl);
2889
	free_dir(ep->ex_dirl);
2890
	grp = ep->ex_grphead;
2891
	while (grp) {
2892
		tgrp = grp;
2893
		grp = grp->gr_next;
2894
		free_grp(tgrp);
2895
	}
2416
	free((caddr_t)ep);
2896
	free((caddr_t)ep);
2417
}
2897
}
2418
2898
2419
/*
2899
/*
2900
 * Free up the v4root exports.
2901
 */
2902
static void
2903
free_v4rootexp(void)
2904
{
2905
2906
	if (v4root_ep != NULL) {
2907
		free_exp(v4root_ep);
2908
		v4root_ep = NULL;
2909
	}
2910
}
2911
2912
/*
2420
 * Free hosts.
2913
 * Free hosts.
2421
 */
2914
 */
2422
static void
2915
static void
Lines 2456-2467 out_of_mem(void) Link Here
2456
}
2949
}
2457
2950
2458
/*
2951
/*
2952
 * Call do_mount() from the struct exportlist, for each case needed.
2953
 */
2954
static int
2955
do_export_mount(struct exportlist *ep, struct statfs *fsp)
2956
{
2957
	struct grouplist *grp, defgrp;
2958
	int ret;
2959
	size_t dirlen;
2960
2961
	MOUNTD_DO_MOUNT_EXPORT("do mount export", ep->ex_fsdir);
2962
	dirlen = strlen(ep->ex_fsdir);
2963
	if ((ep->ex_flag & EX_DEFSET) != 0) {
2964
		defgrp.gr_type = GT_DEFAULT;
2965
		defgrp.gr_next = NULL;
2966
		/* We have an entry for all other hosts/nets. */
2967
		MOUNTD_EX_DEFEXFLAGS("ex defexflags", ep->ex_defexflags);
2968
		ret = do_mount(ep, &defgrp, ep->ex_defexflags, &ep->ex_defanon,
2969
		    ep->ex_fsdir, dirlen, fsp, ep->ex_defnumsecflavors,
2970
		    ep->ex_defsecflavors);
2971
		if (ret != 0)
2972
			return (ret);
2973
	}
2974
2975
	/* Do a mount for each group. */
2976
	grp = ep->ex_grphead;
2977
	while (grp != NULL) {
2978
		MOUNTD_DO_MOUNT_GR_TYPE("do mount gr type", grp->gr_type,
2979
		    grp->gr_exflags);
2980
		ret = do_mount(ep, grp, grp->gr_exflags, &grp->gr_anon,
2981
		    ep->ex_fsdir, dirlen, fsp, grp->gr_numsecflavors,
2982
		    grp->gr_secflavors);
2983
		if (ret != 0)
2984
			return (ret);
2985
		grp = grp->gr_next;
2986
	}
2987
	return (0);
2988
}
2989
2990
/*
2459
 * Do the nmount() syscall with the update flag to push the export info into
2991
 * Do the nmount() syscall with the update flag to push the export info into
2460
 * the kernel.
2992
 * the kernel.
2461
 */
2993
 */
2462
static int
2994
static int
2463
do_mount(struct exportlist *ep, struct grouplist *grp, int exflags,
2995
do_mount(struct exportlist *ep, struct grouplist *grp, int exflags,
2464
    struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb)
2996
    struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb,
2997
    int numsecflavors, int *secflavors)
2465
{
2998
{
2466
	struct statfs fsb1;
2999
	struct statfs fsb1;
2467
	struct addrinfo *ai;
3000
	struct addrinfo *ai;
Lines 2487-2500 do_mount(struct exportlist *ep, struct g Link Here
2487
	bzero(errmsg, sizeof(errmsg));
3020
	bzero(errmsg, sizeof(errmsg));
2488
	eap->ex_flags = exflags;
3021
	eap->ex_flags = exflags;
2489
	eap->ex_anon = *anoncrp;
3022
	eap->ex_anon = *anoncrp;
3023
	MOUNTD_DO_MOUNT_EXFLAGS("do mount exflags", exflags);
2490
	eap->ex_indexfile = ep->ex_indexfile;
3024
	eap->ex_indexfile = ep->ex_indexfile;
2491
	if (grp->gr_type == GT_HOST)
3025
	if (grp->gr_type == GT_HOST)
2492
		ai = grp->gr_ptr.gt_addrinfo;
3026
		ai = grp->gr_ptr.gt_addrinfo;
2493
	else
3027
	else
2494
		ai = NULL;
3028
		ai = NULL;
2495
	eap->ex_numsecflavors = ep->ex_numsecflavors;
3029
	eap->ex_numsecflavors = numsecflavors;
3030
	MOUNTD_DO_MOUNT_NUMSEC("do mount numsec", numsecflavors);
2496
	for (i = 0; i < eap->ex_numsecflavors; i++)
3031
	for (i = 0; i < eap->ex_numsecflavors; i++)
2497
		eap->ex_secflavors[i] = ep->ex_secflavors[i];
3032
		eap->ex_secflavors[i] = secflavors[i];
2498
	if (eap->ex_numsecflavors == 0) {
3033
	if (eap->ex_numsecflavors == 0) {
2499
		eap->ex_numsecflavors = 1;
3034
		eap->ex_numsecflavors = 1;
2500
		eap->ex_secflavors[0] = AUTH_SYS;
3035
		eap->ex_secflavors[0] = AUTH_SYS;
Lines 2658-2665 do_mount(struct exportlist *ep, struct g Link Here
2658
			else if (nfssvc(NFSSVC_PUBLICFH, (caddr_t)&fh) < 0)
3193
			else if (nfssvc(NFSSVC_PUBLICFH, (caddr_t)&fh) < 0)
2659
				syslog(LOG_ERR,
3194
				syslog(LOG_ERR,
2660
				    "Can't set public fh for %s", public_name);
3195
				    "Can't set public fh for %s", public_name);
2661
			else
3196
			else {
2662
				has_publicfh = 1;
3197
				has_publicfh = 1;
3198
				has_set_publicfh = 1;
3199
				ep->ex_flag |= EX_PUBLICFH;
3200
			}
2663
		}
3201
		}
2664
skip:
3202
skip:
2665
		if (ai != NULL)
3203
		if (ai != NULL)
Lines 2824-2841 static void Link Here
2824
nextfield(char **cp, char **endcp)
3362
nextfield(char **cp, char **endcp)
2825
{
3363
{
2826
	char *p;
3364
	char *p;
3365
	char quot = 0;
2827
3366
2828
	p = *cp;
3367
	p = *cp;
2829
	while (*p == ' ' || *p == '\t')
3368
	while (*p == ' ' || *p == '\t')
2830
		p++;
3369
		p++;
2831
	if (*p == '\n' || *p == '\0')
3370
	*cp = p;
2832
		*cp = *endcp = p;
3371
	while (*p != '\0') {
2833
	else {
3372
		if (quot) {
2834
		*cp = p++;
3373
			if (*p == quot)
2835
		while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
3374
				quot = 0;
2836
			p++;
3375
		} else {
2837
		*endcp = p;
3376
			if (*p == '\\' && *(p + 1) != '\0')
2838
	}
3377
				p++;
3378
			else if (*p == '\'' || *p == '"')
3379
				quot = *p;
3380
			else if (*p == ' ' || *p == '\t')
3381
				break;
3382
		}
3383
		p++;
3384
	};
3385
	*endcp = p;
2839
}
3386
}
2840
3387
2841
/*
3388
/*
Lines 2907-2914 parsecred(char *namelist, struct xucred Link Here
2907
	/*
3454
	/*
2908
	 * Get the user's password table entry.
3455
	 * Get the user's password table entry.
2909
	 */
3456
	 */
2910
	names = strsep_quote(&namelist, " \t\n");
3457
	names = namelist;
2911
	name = strsep(&names, ":");
3458
	name = strsep_quote(&names, ":");
2912
	/* Bug?  name could be NULL here */
3459
	/* Bug?  name could be NULL here */
2913
	if (isdigit(*name) || *name == '-')
3460
	if (isdigit(*name) || *name == '-')
2914
		pw = getpwuid(atoi(name));
3461
		pw = getpwuid(atoi(name));
Lines 2952-2958 parsecred(char *namelist, struct xucred Link Here
2952
	}
3499
	}
2953
	cr->cr_ngroups = 0;
3500
	cr->cr_ngroups = 0;
2954
	while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) {
3501
	while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) {
2955
		name = strsep(&names, ":");
3502
		name = strsep_quote(&names, ":");
2956
		if (isdigit(*name) || *name == '-') {
3503
		if (isdigit(*name) || *name == '-') {
2957
			cr->cr_groups[cr->cr_ngroups++] = atoi(name);
3504
			cr->cr_groups[cr->cr_ngroups++] = atoi(name);
2958
		} else {
3505
		} else {

Return to bug 237860