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

Collapse All | Expand All

(-)usr.sbin/mountd/Makefile (-1 / +1 lines)
Lines 2-8 Link Here
2
# $FreeBSD: head/usr.sbin/mountd/Makefile 314659 2017-03-04 11:38:03Z ngie $
2
# $FreeBSD: head/usr.sbin/mountd/Makefile 314659 2017-03-04 11:38:03Z ngie $
3
3
4
PROG=	mountd
4
PROG=	mountd
5
SRCS=	mountd.c getmntopts.c
5
SRCS=	mountd.c getmntopts.c mountd_dt.d
6
MAN=	exports.5 netgroup.5 mountd.8
6
MAN=	exports.5 netgroup.5 mountd.8
7
7
8
MOUNT=  ${SRCTOP}/sbin/mount
8
MOUNT=  ${SRCTOP}/sbin/mount
(-)usr.sbin/mountd/mountd.8 (-2 / +12 lines)
Lines 28-34 Link Here
28
.\"     @(#)mountd.8	8.4 (Berkeley) 4/28/95
28
.\"     @(#)mountd.8	8.4 (Berkeley) 4/28/95
29
.\" $FreeBSD: head/usr.sbin/mountd/mountd.8 314436 2017-02-28 23:42:47Z imp $
29
.\" $FreeBSD: head/usr.sbin/mountd/mountd.8 314436 2017-02-28 23:42:47Z imp $
30
.\"
30
.\"
31
.Dd October 24, 2016
31
.Dd May 22, 2019
32
.Dt MOUNTD 8
32
.Dt MOUNTD 8
33
.Os
33
.Os
34
.Sh NAME
34
.Sh NAME
Lines 38-44 Link Here
38
mount requests
38
mount requests
39
.Sh SYNOPSIS
39
.Sh SYNOPSIS
40
.Nm
40
.Nm
41
.Op Fl 2delnrS
41
.Op Fl 2deIlnrS
42
.Op Fl h Ar bindip
42
.Op Fl h Ar bindip
43
.Op Fl p Ar port
43
.Op Fl p Ar port
44
.Op Ar exportsfile ...
44
.Op Ar exportsfile ...
Lines 87-92 will automatically add Link Here
87
and if IPv6 is enabled,
87
and if IPv6 is enabled,
88
.Li ::1
88
.Li ::1
89
to the list.
89
to the list.
90
.It Fl I
91
Make a reload of the exports file(s) be done via a comparison between the
92
current and new exports entries, only doing system calls to update the kernel
93
exports for cases that have changed.
94
This can reduce the number of system calls being done significantly for
95
a large number of exported file systems, when only a small number of changes
96
to the exports have been made.
97
For a server with 10,000 exported file systems, this can reduce the duration
98
during which the nfsd threads are suspended during the reload from seconds
99
to milliseconds.
90
.It Fl l
100
.It Fl l
91
Cause all succeeded
101
Cause all succeeded
92
.Nm
102
.Nm
(-)usr.sbin/mountd/mountd.c (-141 / +670 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 85-90 __FBSDID("$FreeBSD: head/usr.sbin/mountd Link Here
85
#include <unistd.h>
87
#include <unistd.h>
86
#include "pathnames.h"
88
#include "pathnames.h"
87
#include "mntopts.h"
89
#include "mntopts.h"
90
#include "mountd_dt.h"
88
91
89
#ifdef DEBUG
92
#ifdef DEBUG
90
#include <stdarg.h>
93
#include <stdarg.h>
Lines 114-123 struct dirlist { Link Here
114
struct exportlist {
117
struct exportlist {
115
	struct dirlist	*ex_dirl;
118
	struct dirlist	*ex_dirl;
116
	struct dirlist	*ex_defdir;
119
	struct dirlist	*ex_defdir;
120
	struct grouplist *ex_grphead;
117
	int		ex_flag;
121
	int		ex_flag;
118
	fsid_t		ex_fs;
122
	fsid_t		ex_fs;
119
	char		*ex_fsdir;
123
	char		*ex_fsdir;
120
	char		*ex_indexfile;
124
	char		*ex_indexfile;
125
	struct xucred	ex_defanon;
126
	int		ex_defexflags;
121
	int		ex_numsecflavors;
127
	int		ex_numsecflavors;
122
	int		ex_secflavors[MAXSECFLAVORS];
128
	int		ex_secflavors[MAXSECFLAVORS];
123
	int		ex_defnumsecflavors;
129
	int		ex_defnumsecflavors;
Lines 127-132 struct exportlist { Link Here
127
};
133
};
128
/* ex_flag bits */
134
/* ex_flag bits */
129
#define	EX_LINKED	0x1
135
#define	EX_LINKED	0x1
136
#define	EX_DONE		0x2
137
#define	EX_DEFSET	0x4
138
#define	EX_PUBLICFH	0x8
139
140
SLIST_HEAD(exportlisthead, exportlist);
130
141
131
struct netmsk {
142
struct netmsk {
132
	struct sockaddr_storage nt_net;
143
	struct sockaddr_storage nt_net;
Lines 143-148 struct grouplist { Link Here
143
	int gr_type;
154
	int gr_type;
144
	union grouptypes gr_ptr;
155
	union grouptypes gr_ptr;
145
	struct grouplist *gr_next;
156
	struct grouplist *gr_next;
157
	struct xucred gr_anon;
158
	int gr_exflags;
159
	int gr_flag;
146
	int gr_numsecflavors;
160
	int gr_numsecflavors;
147
	int gr_secflavors[MAXSECFLAVORS];
161
	int gr_secflavors[MAXSECFLAVORS];
148
};
162
};
Lines 153-158 struct grouplist { Link Here
153
#define	GT_DEFAULT	0x3
167
#define	GT_DEFAULT	0x3
154
#define GT_IGNORE	0x5
168
#define GT_IGNORE	0x5
155
169
170
/* Group flags */
171
#define	GR_FND		0x1
172
156
struct hostlist {
173
struct hostlist {
157
	int		 ht_flag;	/* Uses DP_xx bits */
174
	int		 ht_flag;	/* Uses DP_xx bits */
158
	struct grouplist *ht_grp;
175
	struct grouplist *ht_grp;
Lines 172-178 struct fhreturn { Link Here
172
/* Global defs */
189
/* Global defs */
173
static char	*add_expdir(struct dirlist **, char *, int);
190
static char	*add_expdir(struct dirlist **, char *, int);
174
static void	add_dlist(struct dirlist **, struct dirlist *,
191
static void	add_dlist(struct dirlist **, struct dirlist *,
175
		    struct grouplist *, int, struct exportlist *);
192
		    struct grouplist *, int, struct exportlist *,
193
		    struct xucred *, int);
176
static void	add_mlist(char *, char *);
194
static void	add_mlist(char *, char *);
177
static int	check_dirpath(char *);
195
static int	check_dirpath(char *);
178
static int	check_options(struct dirlist *);
196
static int	check_options(struct dirlist *);
Lines 185-201 static void complete_service(struct netc Link Here
185
static void	clearout_service(void);
203
static void	clearout_service(void);
186
static void	del_mlist(char *hostp, char *dirp);
204
static void	del_mlist(char *hostp, char *dirp);
187
static struct dirlist	*dirp_search(struct dirlist *, char *);
205
static struct dirlist	*dirp_search(struct dirlist *, char *);
206
static int	do_export_mount(struct exportlist *, struct statfs *);
188
static int	do_mount(struct exportlist *, struct grouplist *, int,
207
static int	do_mount(struct exportlist *, struct grouplist *, int,
189
		    struct xucred *, char *, int, struct statfs *);
208
		    struct xucred *, char *, int, struct statfs *, int, int *);
190
static int	do_opt(char **, char **, struct exportlist *,
209
static int	do_opt(char **, char **, struct exportlist *,
191
		    struct grouplist *, int *, int *, struct xucred *);
210
		    struct grouplist *, int *, int *, struct xucred *);
192
static struct exportlist	*ex_search(fsid_t *);
211
static struct exportlist	*ex_search(fsid_t *, struct exportlisthead *);
193
static struct exportlist	*get_exp(void);
212
static struct exportlist	*get_exp(void);
194
static void	free_dir(struct dirlist *);
213
static void	free_dir(struct dirlist *);
195
static void	free_exp(struct exportlist *);
214
static void	free_exp(struct exportlist *);
196
static void	free_grp(struct grouplist *);
215
static void	free_grp(struct grouplist *);
197
static void	free_host(struct hostlist *);
216
static void	free_host(struct hostlist *);
198
static void	get_exportlist(void);
217
static void	free_v4rootexp(void);
218
static void	get_exportlist_one(int);
219
static void	get_exportlist(int);
220
static void	insert_exports(struct exportlist *, struct exportlisthead *);
221
static void	free_exports(struct exportlisthead *);
222
static void	read_exportfile(int);
223
static int	compare_nmount_exportlist(struct iovec *, int, char *);
224
static int	compare_export(struct exportlist *, struct exportlist *);
225
static int	compare_cred(struct xucred *, struct xucred *);
226
static int	compare_secflavor(int *, int *, int);
227
static void	delete_export(struct iovec *, int, struct statfs *, char *);
199
static int	get_host(char *, struct grouplist *, struct grouplist *);
228
static int	get_host(char *, struct grouplist *, struct grouplist *);
200
static struct hostlist *get_ht(void);
229
static struct hostlist *get_ht(void);
201
static int	get_line(void);
230
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 *);
233
static void	getexp_err(struct exportlist *, struct grouplist *, const char *);
205
static struct grouplist	*get_grp(void);
234
static struct grouplist	*get_grp(void);
206
static void	hang_dirp(struct dirlist *, struct grouplist *,
235
static void	hang_dirp(struct dirlist *, struct grouplist *,
207
				struct exportlist *, int);
236
		    struct exportlist *, int, struct xucred *, int);
208
static void	huphandler(int sig);
237
static void	huphandler(int sig);
209
static int	makemask(struct sockaddr_storage *ssp, int bitlen);
238
static int	makemask(struct sockaddr_storage *ssp, int bitlen);
210
static void	mntsrv(struct svc_req *, SVCXPRT *);
239
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);
256
static int	xdr_mlist(XDR *, caddr_t);
228
static void	terminate(int);
257
static void	terminate(int);
229
258
230
static SLIST_HEAD(, exportlist) exphead = SLIST_HEAD_INITIALIZER(exphead);
259
#define	EXPHASH(f)	(fnv_32_buf((f), sizeof(fsid_t), 0) % exphashsize)
231
static SLIST_HEAD(, mountlist) mlhead = SLIST_HEAD_INITIALIZER(mlhead);
260
static struct exportlisthead *exphead = NULL;
232
static struct grouplist *grphead;
261
static struct exportlisthead *oldexphead = NULL;
262
static int exphashsize = 0;
263
static SLIST_HEAD(, mountlist) mlhead = SLIST_HEAD_INITIALIZER(&mlhead);
233
static char *exnames_default[2] = { _PATH_EXPORTS, NULL };
264
static char *exnames_default[2] = { _PATH_EXPORTS, NULL };
234
static char **exnames;
265
static char **exnames;
235
static char **hosts = NULL;
266
static char **hosts = NULL;
Lines 260-266 static int have_v6 = 1; Link Here
260
291
261
static int v4root_phase = 0;
292
static int v4root_phase = 0;
262
static char v4root_dirpath[PATH_MAX + 1];
293
static char v4root_dirpath[PATH_MAX + 1];
294
static struct exportlist *v4root_ep = NULL;
263
static int has_publicfh = 0;
295
static int has_publicfh = 0;
296
static int has_set_publicfh = 0;
264
297
265
static struct pidfh *pfh = NULL;
298
static struct pidfh *pfh = NULL;
266
/* Bits for opt_flags above */
299
/* Bits for opt_flags above */
Lines 368-376 main(int argc, char **argv) Link Here
368
	in_port_t svcport;
401
	in_port_t svcport;
369
	int c, k, s;
402
	int c, k, s;
370
	int maxrec = RPC_MAXDATASIZE;
403
	int maxrec = RPC_MAXDATASIZE;
371
	int attempt_cnt, port_len, port_pos, ret;
404
	int attempt_cnt, passno, port_len, port_pos, ret;
372
	char **port_list;
405
	char **port_list;
373
406
407
	passno = 0;
374
	/* Check that another mountd isn't already running. */
408
	/* Check that another mountd isn't already running. */
375
	pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
409
	pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
376
	if (pfh == NULL) {
410
	if (pfh == NULL) {
Lines 385-391 main(int argc, char **argv) Link Here
385
	else
419
	else
386
		close(s);
420
		close(s);
387
421
388
	while ((c = getopt(argc, argv, "2deh:lnp:rS")) != -1)
422
	while ((c = getopt(argc, argv, "2deh:Ilnp:rS")) != -1)
389
		switch (c) {
423
		switch (c) {
390
		case '2':
424
		case '2':
391
			force_v2 = 1;
425
			force_v2 = 1;
Lines 437-442 main(int argc, char **argv) Link Here
437
		case 'S':
471
		case 'S':
438
			suspend_nfsd = 1;
472
			suspend_nfsd = 1;
439
			break;
473
			break;
474
		case 'I':
475
			passno = 1;
476
			break;
440
		default:
477
		default:
441
			usage();
478
			usage();
442
		}
479
		}
Lines 449-455 main(int argc, char **argv) Link Here
449
486
450
	argc -= optind;
487
	argc -= optind;
451
	argv += optind;
488
	argv += optind;
452
	grphead = (struct grouplist *)NULL;
453
	if (argc > 0)
489
	if (argc > 0)
454
		exnames = argv;
490
		exnames = argv;
455
	else
491
	else
Lines 457-463 main(int argc, char **argv) Link Here
457
	openlog("mountd", LOG_PID, LOG_DAEMON);
493
	openlog("mountd", LOG_PID, LOG_DAEMON);
458
	if (debug)
494
	if (debug)
459
		warnx("getting export list");
495
		warnx("getting export list");
460
	get_exportlist();
496
	get_exportlist(0);
461
	if (debug)
497
	if (debug)
462
		warnx("getting mount list");
498
		warnx("getting mount list");
463
	get_mountlist();
499
	get_mountlist();
Lines 628-634 main(int argc, char **argv) Link Here
628
	/* Expand svc_run() here so that we can call get_exportlist(). */
664
	/* Expand svc_run() here so that we can call get_exportlist(). */
629
	for (;;) {
665
	for (;;) {
630
		if (got_sighup) {
666
		if (got_sighup) {
631
			get_exportlist();
667
			get_exportlist(passno);
632
			got_sighup = 0;
668
			got_sighup = 0;
633
		}
669
		}
634
		readfds = svc_fdset;
670
		readfds = svc_fdset;
Lines 1087-1093 mntsrv(struct svc_req *rqstp, SVCXPRT *t Link Here
1087
		if (bad)
1123
		if (bad)
1088
			ep = NULL;
1124
			ep = NULL;
1089
		else
1125
		else
1090
			ep = ex_search(&fsb.f_fsid);
1126
			ep = ex_search(&fsb.f_fsid, exphead);
1091
		hostset = defset = 0;
1127
		hostset = defset = 0;
1092
		if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset,
1128
		if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset,
1093
		    &numsecflavors, &secflavorsp) ||
1129
		    &numsecflavors, &secflavorsp) ||
Lines 1302-1322 xdr_explist_common(XDR *xdrsp, caddr_t c Link Here
1302
	int false = 0;
1338
	int false = 0;
1303
	int putdef;
1339
	int putdef;
1304
	sigset_t sighup_mask;
1340
	sigset_t sighup_mask;
1341
	int i;
1305
1342
1306
	sigemptyset(&sighup_mask);
1343
	sigemptyset(&sighup_mask);
1307
	sigaddset(&sighup_mask, SIGHUP);
1344
	sigaddset(&sighup_mask, SIGHUP);
1308
	sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
1345
	sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
1309
1346
1310
	SLIST_FOREACH(ep, &exphead, entries) {
1347
	for (i = 0; i < exphashsize; i++)
1311
		putdef = 0;
1348
		SLIST_FOREACH(ep, &exphead[i], entries) {
1312
		if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir,
1349
			putdef = 0;
1313
			       &putdef, brief))
1350
			if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir,
1314
			goto errout;
1351
				       &putdef, brief))
1315
		if (ep->ex_defdir && putdef == 0 &&
1352
				goto errout;
1316
			put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL,
1353
			if (ep->ex_defdir && putdef == 0 &&
1317
			&putdef, brief))
1354
				put_exlist(ep->ex_defdir, xdrsp, NULL,
1318
			goto errout;
1355
				&putdef, brief))
1319
	}
1356
				goto errout;
1357
		}
1320
	sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
1358
	sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
1321
	if (!xdr_bool(xdrsp, &false))
1359
	if (!xdr_bool(xdrsp, &false))
1322
		return (0);
1360
		return (0);
Lines 1416-1425 static FILE *exp_file; Link Here
1416
 * Get the export list from one, currently open file
1454
 * Get the export list from one, currently open file
1417
 */
1455
 */
1418
static void
1456
static void
1419
get_exportlist_one(void)
1457
get_exportlist_one(int passno)
1420
{
1458
{
1421
	struct exportlist *ep;
1459
	struct exportlist *ep;
1422
	struct grouplist *grp, *tgrp;
1460
	struct grouplist *grp, *tgrp, *savgrp;
1423
	struct dirlist *dirhead;
1461
	struct dirlist *dirhead;
1424
	struct statfs fsb;
1462
	struct statfs fsb;
1425
	struct xucred anon;
1463
	struct xucred anon;
Lines 1540-1546 get_exportlist_one(void) Link Here
1540
					 * See if this directory is already
1578
					 * See if this directory is already
1541
					 * in the list.
1579
					 * in the list.
1542
					 */
1580
					 */
1543
					ep = ex_search(&fsb.f_fsid);
1581
					ep = ex_search(&fsb.f_fsid, exphead);
1544
					if (ep == (struct exportlist *)NULL) {
1582
					if (ep == (struct exportlist *)NULL) {
1545
					    ep = get_exp();
1583
					    ep = get_exp();
1546
					    ep->ex_fs = fsb.f_fsid;
1584
					    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.
1691
		 * Loop through hosts, pushing the exports into the kernel.
1654
		 * After loop, tgrp points to the start of the list and
1692
		 * After loop, tgrp points to the start of the list and
1655
		 * grp points to the last entry in the list.
1693
		 * grp points to the last entry in the list.
1694
		 * Do not do the do_mount() for passno == 1, since the
1695
		 * second pass will do it, as required.
1656
		 */
1696
		 */
1657
		grp = tgrp;
1697
		grp = tgrp;
1658
		do {
1698
		do {
1659
			if (do_mount(ep, grp, exflags, &anon, dirp, dirplen,
1699
			grp->gr_exflags = exflags;
1660
			    &fsb)) {
1700
			grp->gr_anon = anon;
1701
			if (passno == 0 && do_mount(ep, grp, exflags, &anon,
1702
			    dirp, dirplen, &fsb, ep->ex_numsecflavors,
1703
			    ep->ex_secflavors)) {
1661
				getexp_err(ep, tgrp, NULL);
1704
				getexp_err(ep, tgrp, NULL);
1662
				goto nextline;
1705
				goto nextline;
1663
			}
1706
			}
Lines 1668-1676 get_exportlist_one(void) Link Here
1668
		 */
1711
		 */
1669
		if (v4root_phase > 0 && v4root_phase <= 2) {
1712
		if (v4root_phase > 0 && v4root_phase <= 2) {
1670
			/*
1713
			/*
1671
			 * Since these structures aren't used by mountd,
1714
			 * These structures are used for the "-I" reload,
1715
			 * so save them for that case.  Otherwise, just
1672
			 * free them up now.
1716
			 * free them up now.
1673
			 */
1717
			 */
1718
			if (passno == 1 && ep != NULL) {
1719
				savgrp = tgrp;
1720
				while (tgrp != NULL) {
1721
					/*
1722
					 * Save the security flavors and exflags
1723
					 * for this host set in the groups.
1724
					 */
1725
					tgrp->gr_numsecflavors =
1726
					    ep->ex_numsecflavors;
1727
					if (ep->ex_numsecflavors > 0)
1728
						memcpy(tgrp->gr_secflavors,
1729
						    ep->ex_secflavors,
1730
						    sizeof(ep->ex_secflavors));
1731
					tgrp = tgrp->gr_next;
1732
				}
1733
				if (v4root_ep == NULL) {
1734
					v4root_ep = ep;
1735
					ep = NULL;	/* Don't free below. */
1736
				}
1737
				grp->gr_next = v4root_ep->ex_grphead;
1738
				v4root_ep->ex_grphead = savgrp;
1739
			}
1674
			if (ep != NULL)
1740
			if (ep != NULL)
1675
				free_exp(ep);
1741
				free_exp(ep);
1676
			while (tgrp != NULL) {
1742
			while (tgrp != NULL) {
Lines 1685-1701 get_exportlist_one(void) Link Here
1685
		 * Success. Update the data structures.
1751
		 * Success. Update the data structures.
1686
		 */
1752
		 */
1687
		if (has_host) {
1753
		if (has_host) {
1688
			hang_dirp(dirhead, tgrp, ep, opt_flags);
1754
			hang_dirp(dirhead, tgrp, ep, opt_flags, &anon, exflags);
1689
			grp->gr_next = grphead;
1755
			grp->gr_next = ep->ex_grphead;
1690
			grphead = tgrp;
1756
			ep->ex_grphead = tgrp;
1691
		} else {
1757
		} else {
1692
			hang_dirp(dirhead, (struct grouplist *)NULL, ep,
1758
			hang_dirp(dirhead, (struct grouplist *)NULL, ep,
1693
				opt_flags);
1759
				opt_flags, &anon, exflags);
1694
			free_grp(grp);
1760
			free_grp(grp);
1695
		}
1761
		}
1696
		dirhead = (struct dirlist *)NULL;
1762
		dirhead = (struct dirlist *)NULL;
1697
		if ((ep->ex_flag & EX_LINKED) == 0) {
1763
		if ((ep->ex_flag & EX_LINKED) == 0) {
1698
			SLIST_INSERT_HEAD(&exphead, ep, entries);
1764
			insert_exports(ep, exphead);
1699
1765
1700
			ep->ex_flag |= EX_LINKED;
1766
			ep->ex_flag |= EX_LINKED;
1701
		}
1767
		}
Lines 1712-1758 nextline: Link Here
1712
 * Get the export list from all specified files
1778
 * Get the export list from all specified files
1713
 */
1779
 */
1714
static void
1780
static void
1715
get_exportlist(void)
1781
get_exportlist(int passno)
1716
{
1782
{
1717
	struct exportlist *ep, *ep2;
1718
	struct grouplist *grp, *tgrp;
1719
	struct export_args export;
1783
	struct export_args export;
1720
	struct iovec *iov;
1784
	struct iovec *iov;
1721
	struct statfs *fsp, *mntbufp;
1785
	struct statfs *mntbufp;
1722
	struct xvfsconf vfc;
1723
	char errmsg[255];
1786
	char errmsg[255];
1724
	int num, i;
1787
	int num, i;
1725
	int iovlen;
1788
	int iovlen;
1726
	int done;
1727
	struct nfsex_args eargs;
1789
	struct nfsex_args eargs;
1728
1790
1729
	if (suspend_nfsd != 0)
1791
	MOUNTD_PASSNO("passno", passno);
1730
		(void)nfssvc(NFSSVC_SUSPENDNFSD, NULL);
1731
	v4root_dirpath[0] = '\0';
1792
	v4root_dirpath[0] = '\0';
1793
	free_v4rootexp();
1794
	if (passno == 1) {
1795
		/*
1796
		 * Save the current lists as old ones, so that the new lists
1797
		 * can be compared with the old ones in the 2nd pass.
1798
		 */
1799
		for (i = 0; i < exphashsize; i++) {
1800
			SLIST_FIRST(&oldexphead[i]) = SLIST_FIRST(&exphead[i]);
1801
			SLIST_INIT(&exphead[i]);
1802
		}
1803
1804
		/* Note that the public fh has not yet been set. */
1805
		has_set_publicfh = 0;
1806
1807
		/* Read the export file(s) and process them */
1808
		read_exportfile(passno);
1809
	} else {
1810
		/*
1811
		 * Just make the old lists empty.
1812
		 * exphashsize == 0 for the first call, before oldexphead
1813
		 * has been initialized-->loop won't be executed.
1814
		 */
1815
		for (i = 0; i < exphashsize; i++)
1816
			SLIST_INIT(&oldexphead[i]);
1817
	}
1818
1732
	bzero(&export, sizeof(export));
1819
	bzero(&export, sizeof(export));
1733
	export.ex_flags = MNT_DELEXPORT;
1820
	export.ex_flags = MNT_DELEXPORT;
1734
	iov = NULL;
1821
	iov = NULL;
1735
	iovlen = 0;
1822
	iovlen = 0;
1736
	bzero(errmsg, sizeof(errmsg));
1823
	bzero(errmsg, sizeof(errmsg));
1737
1824
1825
	if (suspend_nfsd != 0)
1826
		(void)nfssvc(NFSSVC_SUSPENDNFSD, NULL);
1738
	/*
1827
	/*
1739
	 * First, get rid of the old list
1828
	 * 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
	 */
1829
	 */
1757
	bzero(&eargs, sizeof (eargs));
1830
	bzero(&eargs, sizeof (eargs));
1758
	eargs.export.ex_flags = MNT_DELEXPORT;
1831
	eargs.export.ex_flags = MNT_DELEXPORT;
Lines 1760-1826 get_exportlist(void) Link Here
1760
	    errno != ENOENT)
1833
	    errno != ENOENT)
1761
		syslog(LOG_ERR, "Can't delete exports for V4:");
1834
		syslog(LOG_ERR, "Can't delete exports for V4:");
1762
1835
1763
	/*
1836
	build_iovec(&iov, &iovlen, "fstype", NULL, 0);
1764
	 * and clear flag that notes if a public fh has been exported.
1837
	build_iovec(&iov, &iovlen, "fspath", NULL, 0);
1765
	 */
1838
	build_iovec(&iov, &iovlen, "from", NULL, 0);
1766
	has_publicfh = 0;
1839
	build_iovec(&iov, &iovlen, "update", NULL, 0);
1840
	build_iovec(&iov, &iovlen, "export", &export,
1841
	    sizeof(export));
1842
	build_iovec(&iov, &iovlen, "errmsg", errmsg,
1843
	    sizeof(errmsg));
1767
1844
1768
	/*
1845
	/*
1769
	 * And delete exports that are in the kernel for all local
1846
	 * For passno == 1, compare the old and new lists updating the kernel
1770
	 * filesystems.
1847
	 * exports for any cases that have changed.
1771
	 * XXX: Should know how to handle all local exportable filesystems.
1848
	 * This call is doing the second pass through the lists.
1849
	 * If it fails, fall back on the bulk reload.
1772
	 */
1850
	 */
1773
	num = getmntinfo(&mntbufp, MNT_NOWAIT);
1851
	if (passno == 1 && compare_nmount_exportlist(iov, iovlen, errmsg) ==
1774
1852
	    0) {
1775
	if (num > 0) {
1853
		MOUNTD_COMPAREOK("compareok");
1776
		build_iovec(&iov, &iovlen, "fstype", NULL, 0);
1854
		/* Free up the old lists. */
1777
		build_iovec(&iov, &iovlen, "fspath", NULL, 0);
1855
		free_exports(oldexphead);
1778
		build_iovec(&iov, &iovlen, "from", NULL, 0);
1856
	} else {
1779
		build_iovec(&iov, &iovlen, "update", NULL, 0);
1857
		MOUNTD_PASSNO_0("doing passno=0");
1780
		build_iovec(&iov, &iovlen, "export", &export, sizeof(export));
1858
		/*
1781
		build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
1859
		 * Clear flag that notes if a public fh has been exported.
1782
	}
1860
		 * It is set by do_mount() if MNT_EXPUBLIC is set for the entry.
1861
		 */
1862
		has_publicfh = 0;
1783
1863
1784
	for (i = 0; i < num; i++) {
1864
		/* exphead == NULL if not yet allocated (first call). */
1785
		fsp = &mntbufp[i];
1865
		if (exphead != NULL) {
1786
		if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) {
1866
			/*
1787
			syslog(LOG_ERR, "getvfsbyname() failed for %s",
1867
			 * First, get rid of the old lists.
1788
			    fsp->f_fstypename);
1868
			 */
1789
			continue;
1869
			free_exports(exphead);
1870
			free_exports(oldexphead);
1790
		}
1871
		}
1791
1872
1792
		/*
1873
		/*
1793
		 * We do not need to delete "export" flag from
1874
		 * And delete exports that are in the kernel for all local
1794
		 * filesystems that do not have it set.
1875
		 * filesystems.
1795
		 */
1876
		 * XXX: Should know how to handle all local exportable
1796
		if (!(fsp->f_flags & MNT_EXPORTED))
1877
		 * filesystems.
1797
		    continue;
1878
		 */
1798
		/*
1879
		num = getmntinfo(&mntbufp, MNT_NOWAIT);
1799
		 * Do not delete export for network filesystem by
1880
1800
		 * passing "export" arg to nmount().
1881
		/* Allocate hash tables, for first call. */
1801
		 * It only makes sense to do this for local filesystems.
1882
		if (exphead == NULL) {
1802
		 */
1883
			/* Target an average linked list length of 10. */
1803
		if (vfc.vfc_flags & VFCF_NETWORK)
1884
			exphashsize = num / 10;
1804
			continue;
1885
			if (exphashsize < 1)
1805
1886
				exphashsize = 1;
1806
		iov[1].iov_base = fsp->f_fstypename;
1887
			else if (exphashsize > 100000)
1807
		iov[1].iov_len = strlen(fsp->f_fstypename) + 1;
1888
				exphashsize = 100000;
1808
		iov[3].iov_base = fsp->f_mntonname;
1889
			exphead = malloc(exphashsize * sizeof(*exphead));
1809
		iov[3].iov_len = strlen(fsp->f_mntonname) + 1;
1890
			oldexphead = malloc(exphashsize * sizeof(*oldexphead));
1810
		iov[5].iov_base = fsp->f_mntfromname;
1891
			if (exphead == NULL || oldexphead == NULL)
1811
		iov[5].iov_len = strlen(fsp->f_mntfromname) + 1;
1892
				errx(1, "Can't malloc hash tables");
1812
		errmsg[0] = '\0';
1893
1813
1894
			for (i = 0; i < exphashsize; i++) {
1814
		/*
1895
				SLIST_INIT(&exphead[i]);
1815
		 * EXDEV is returned when path exists but is not a
1896
				SLIST_INIT(&oldexphead[i]);
1816
		 * mount point.  May happens if raced with unmount.
1897
			}
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
		}
1898
		}
1899
	
1900
		for (i = 0; i < num; i++)
1901
			delete_export(iov, iovlen, &mntbufp[i], errmsg);
1902
1903
1904
		/* Read the export file(s) and process them */
1905
		read_exportfile(0);
1824
	}
1906
	}
1825
1907
1826
	if (iov != NULL) {
1908
	if (iov != NULL) {
Lines 1838-1843 get_exportlist(void) Link Here
1838
	}
1920
	}
1839
1921
1840
	/*
1922
	/*
1923
	 * If there was no public fh, clear any previous one set.
1924
	 */
1925
	if (has_publicfh == 0)
1926
		(void) nfssvc(NFSSVC_NOPUBLICFH, NULL);
1927
1928
	/* Resume the nfsd. If they weren't suspended, this is harmless. */
1929
	(void)nfssvc(NFSSVC_RESUMENFSD, NULL);
1930
	MOUNTD_EO_GET_EXPORTLIST("eo get exportlist");
1931
}
1932
1933
/*
1934
 * Insert an export entry in the appropriate list.
1935
 */
1936
static void
1937
insert_exports(struct exportlist *ep, struct exportlisthead *exhp)
1938
{
1939
	uint32_t i;
1940
1941
	i = EXPHASH(&ep->ex_fs);
1942
	MOUNTD_FS_HASH("fs hash", ep->ex_fsdir, i);
1943
	SLIST_INSERT_HEAD(&exhp[i], ep, entries);
1944
}
1945
1946
/*
1947
 * Free up the exports lists passed in as arguments.
1948
 */
1949
static void
1950
free_exports(struct exportlisthead *exhp)
1951
{
1952
	struct exportlist *ep, *ep2;
1953
	int i;
1954
1955
	for (i = 0; i < exphashsize; i++) {
1956
		SLIST_FOREACH_SAFE(ep, &exhp[i], entries, ep2) {
1957
			SLIST_REMOVE(&exhp[i], ep, exportlist, entries);
1958
			free_exp(ep);
1959
		}
1960
		SLIST_INIT(&exhp[i]);
1961
	}
1962
}
1963
1964
/*
1965
 * Read the exports file(s) and call get_exportlist_one() for each line.
1966
 */
1967
static void
1968
read_exportfile(int passno)
1969
{
1970
	int done, i;
1971
1972
	/*
1841
	 * Read in the exports file and build the list, calling
1973
	 * Read in the exports file and build the list, calling
1842
	 * nmount() as we go along to push the export rules into the kernel.
1974
	 * nmount() as we go along to push the export rules into the kernel.
1843
	 */
1975
	 */
Lines 1849-1855 get_exportlist(void) Link Here
1849
			syslog(LOG_WARNING, "can't open %s", exnames[i]);
1981
			syslog(LOG_WARNING, "can't open %s", exnames[i]);
1850
			continue;
1982
			continue;
1851
		}
1983
		}
1852
		get_exportlist_one();
1984
		get_exportlist_one(passno);
1853
		fclose(exp_file);
1985
		fclose(exp_file);
1854
		done++;
1986
		done++;
1855
	}
1987
	}
Lines 1857-1871 get_exportlist(void) Link Here
1857
		syslog(LOG_ERR, "can't open any exports file");
1989
		syslog(LOG_ERR, "can't open any exports file");
1858
		exit(2);
1990
		exit(2);
1859
	}
1991
	}
1992
}
1993
1994
/*
1995
 * Compare the export lists against the old ones and do nmount() operations
1996
 * for any cases that have changed.  This avoids doing nmount() for entries
1997
 * that have not changed.
1998
 * Return 0 upon success, 1 otherwise.
1999
 */
2000
static int
2001
compare_nmount_exportlist(struct iovec *iov, int iovlen, char *errmsg)
2002
{
2003
	struct exportlist *ep, *oep;
2004
	struct grouplist *grp;
2005
	struct statfs fs, ofs;
2006
	int i, ret;
1860
2007
1861
	/*
2008
	/*
1862
	 * If there was no public fh, clear any previous one set.
2009
	 * Loop through the current list and look for an entry in the old
2010
	 * list.
2011
	 * If found, check to see if it the same.
2012
	 *        If it is not the same, delete and re-export.
2013
	 *        Then mark it done on the old list.
2014
	 * else (not found)
2015
	 *        export it.
2016
	 * Any entries left in the old list after processing must have their
2017
	 * exports deleted.
1863
	 */
2018
	 */
1864
	if (has_publicfh == 0)
2019
	for (i = 0; i < exphashsize; i++)
1865
		(void) nfssvc(NFSSVC_NOPUBLICFH, NULL);
2020
		SLIST_FOREACH(ep, &exphead[i], entries) {
2021
			MOUNTD_FOREACH_EP("foreach ep", ep->ex_fsdir);
2022
			oep = ex_search(&ep->ex_fs, oldexphead);
2023
			if (oep != NULL) {
2024
				/*
2025
				 * Check the mount paths are the same.
2026
				 * If not, return 1 so that the reload of the
2027
				 * exports will be done in bulk, the
2028
				 * passno == 0 way.
2029
				 */
2030
				MOUNTD_FOUND_OLD_EXP("found old exp");
2031
				if (strcmp(ep->ex_fsdir, oep->ex_fsdir) != 0)
2032
					return (1);
2033
				MOUNTD_SAME_FSDIR("same fsdir");
2034
				/*
2035
				 * Test to see if the entry is the same.
2036
				 * If not the same delete exports and
2037
				 * re-export.
2038
				 */
2039
				if (compare_export(ep, oep) != 0) {
2040
					/*
2041
					 * Clear has_publicfh if if was set
2042
					 * in the old exports, but only if it
2043
					 * has not been set during processing of
2044
					 * the exports for this pass, as
2045
					 * indicated by has_set_publicfh.
2046
					 */
2047
					if (has_set_publicfh == 0 &&
2048
					    (oep->ex_flag & EX_PUBLICFH) != 0)
2049
						has_publicfh = 0;
1866
2050
1867
	/* Resume the nfsd. If they weren't suspended, this is harmless. */
2051
					/* Delete and re-export. */
1868
	(void)nfssvc(NFSSVC_RESUMENFSD, NULL);
2052
					if (statfs(ep->ex_fsdir, &fs) < 0)
2053
						return (1);
2054
					delete_export(iov, iovlen, &fs, errmsg);
2055
					ret = do_export_mount(ep, &fs);
2056
					if (ret != 0)
2057
						return (ret);
2058
				}
2059
				oep->ex_flag |= EX_DONE;
2060
				MOUNTD_EXDONE("exdone");
2061
			} else {
2062
				MOUNTD_NOT_FOUND_SO_EXPORT(
2063
				    "not found so export");
2064
				/* Not found, so do export. */
2065
				if (statfs(ep->ex_fsdir, &fs) < 0)
2066
					return (1);
2067
				ret = do_export_mount(ep, &fs);
2068
				if (ret != 0)
2069
					return (ret);
2070
			}
2071
		}
2072
2073
	/* Delete exports not done. */
2074
	for (i = 0; i < exphashsize; i++)
2075
		SLIST_FOREACH(oep, &oldexphead[i], entries) {
2076
			if ((oep->ex_flag & EX_DONE) == 0) {
2077
				MOUNTD_NOT_DONE_DELETE("not done delete",
2078
					oep->ex_fsdir);
2079
				if (statfs(oep->ex_fsdir, &ofs) >= 0 &&
2080
				    oep->ex_fs.val[0] == ofs.f_fsid.val[0] &&
2081
				    oep->ex_fs.val[1] == ofs.f_fsid.val[1]) {
2082
					MOUNTD_DO_DELETE("do_delete");
2083
					/*
2084
					 * Clear has_publicfh if if was set
2085
					 * in the old exports, but only if it
2086
					 * has not been set during processing of
2087
					 * the exports for this pass, as
2088
					 * indicated by has_set_publicfh.
2089
					 */
2090
					if (has_set_publicfh == 0 &&
2091
					    (oep->ex_flag & EX_PUBLICFH) != 0)
2092
						has_publicfh = 0;
2093
2094
					delete_export(iov, iovlen, &ofs,
2095
					    errmsg);
2096
				}
2097
			}
2098
		}
2099
2100
	/* Do the V4 root exports, as required. */
2101
	grp = NULL;
2102
	if (v4root_ep != NULL)
2103
		grp = v4root_ep->ex_grphead;
2104
	v4root_phase = 2;
2105
	while (v4root_ep != NULL && grp != NULL) {
2106
		MOUNTD_V4ROOT_EXPATH("v4root expath", v4root_dirpath);
2107
		ret = do_mount(v4root_ep, grp, grp->gr_exflags, &grp->gr_anon,
2108
		    v4root_dirpath, strlen(v4root_dirpath), &fs,
2109
		    grp->gr_numsecflavors, grp->gr_secflavors);
2110
		if (ret != 0) {
2111
			v4root_phase = 0;
2112
			return (ret);
2113
		}
2114
		grp = grp->gr_next;
2115
	}
2116
	v4root_phase = 0;
2117
	free_v4rootexp();
2118
	return (0);
2119
}
2120
2121
/*
2122
 * Compare old and current exportlist entries for the fsid and return 0
2123
 * if they are the same, 1 otherwise.
2124
 */
2125
static int
2126
compare_export(struct exportlist *ep, struct exportlist *oep)
2127
{
2128
	struct grouplist *grp, *ogrp;
2129
2130
	if (strcmp(ep->ex_fsdir, oep->ex_fsdir) != 0)
2131
		return (1);
2132
	if ((ep->ex_flag & EX_DEFSET) != (oep->ex_flag & EX_DEFSET))
2133
		return (1);
2134
	if ((ep->ex_defdir != NULL && oep->ex_defdir == NULL) ||
2135
	    (ep->ex_defdir == NULL && oep->ex_defdir != NULL))
2136
		return (1);
2137
	if (ep->ex_defdir != NULL && (ep->ex_defdir->dp_flag & DP_DEFSET) !=
2138
	    (oep->ex_defdir->dp_flag & DP_DEFSET))
2139
		return (1);
2140
	if ((ep->ex_flag & EX_DEFSET) != 0 && (ep->ex_defnumsecflavors !=
2141
	    oep->ex_defnumsecflavors || ep->ex_defexflags !=
2142
	    oep->ex_defexflags || compare_cred(&ep->ex_defanon,
2143
	    &oep->ex_defanon) != 0 || compare_secflavor(ep->ex_defsecflavors,
2144
	    oep->ex_defsecflavors, ep->ex_defnumsecflavors) != 0))
2145
		return (1);
2146
2147
	/* Now, check all the groups. */
2148
	for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp = ogrp->gr_next)
2149
		ogrp->gr_flag = 0;
2150
	for (grp = ep->ex_grphead; grp != NULL; grp = grp->gr_next) {
2151
		for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp =
2152
		    ogrp->gr_next)
2153
			if ((ogrp->gr_flag & GR_FND) == 0 &&
2154
			    grp->gr_numsecflavors == ogrp->gr_numsecflavors &&
2155
			    grp->gr_exflags == ogrp->gr_exflags &&
2156
			    compare_cred(&grp->gr_anon, &ogrp->gr_anon) == 0 &&
2157
			    compare_secflavor(grp->gr_secflavors,
2158
			    ogrp->gr_secflavors, grp->gr_numsecflavors) == 0)
2159
				break;
2160
		if (ogrp != NULL)
2161
			ogrp->gr_flag |= GR_FND;
2162
		else
2163
			return (1);
2164
	}
2165
	for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp = ogrp->gr_next)
2166
		if ((ogrp->gr_flag & GR_FND) == 0)
2167
			return (1);
2168
	return (0);
2169
}
2170
2171
/*
2172
 * Compare to struct xucred's.  Return 0 if the same and 1 otherwise.
2173
 */
2174
static int
2175
compare_cred(struct xucred *cr0, struct xucred *cr1)
2176
{
2177
	int fnd, grp_fnd[XU_NGROUPS], i, j;
2178
2179
	if (cr0->cr_uid != cr1->cr_uid || cr0->cr_ngroups != cr1->cr_ngroups)
2180
		return (1);
2181
2182
	/* Handle common cases. */
2183
	if (cr0->cr_ngroups == 0)
2184
		return (0);
2185
	if (cr0->cr_ngroups == 1) {
2186
		if (cr0->cr_groups[0] == cr1->cr_groups[0])
2187
			return (0);
2188
		return (1);
2189
	}
2190
	if (memcmp(cr0->cr_groups, cr1->cr_groups, sizeof(*cr0->cr_groups) *
2191
	    cr0->cr_ngroups) == 0)
2192
		return (0);
2193
2194
	for (i = 0; i < cr0->cr_ngroups; i++)
2195
		grp_fnd[i] = 0;
2196
	/*
2197
	 * Search through the old and new groups lists, noting matches.
2198
	 * Since there is no ordering and duplicates can exist in the lists,
2199
	 * the algorithm is inefficient.  However cr_ngroups is small and
2200
	 * the common cases are handled above.
2201
	 */
2202
	for (i = 0; i < cr0->cr_ngroups; i++) {
2203
		fnd = 0;
2204
		for (j = 0; j < cr0->cr_ngroups; j++) {
2205
			if (cr0->cr_groups[i] == cr1->cr_groups[j]) {
2206
				grp_fnd[j] = 1;
2207
				fnd = 1;
2208
			}
2209
		}
2210
		if (fnd == 0)
2211
			return (1);
2212
	}
2213
	for (i = 0; i < cr0->cr_ngroups; i++)
2214
		if (grp_fnd[i] == 0)
2215
			return (1);
2216
	return (0);
2217
}
2218
2219
/*
2220
 * Compare two lists of security flavors.  Return 0 if the same and 1 otherwise.
2221
 * This is almost identical to compare_cred(), but I didn't factor out
2222
 * the algorithm, since compare_cred() may need to change if/when more than
2223
 * XU_NGROUPS groups are supported.
2224
 */
2225
static int
2226
compare_secflavor(int *sec1, int *sec2, int nsec)
2227
{
2228
	int fnd, sec_fnd[MAXSECFLAVORS], i, j;
2229
2230
	/* Handle common cases first. */
2231
	if (nsec == 0)
2232
		return (0);
2233
	if (nsec == 1) {
2234
		if (sec1[0] == sec2[0])
2235
			return (0);
2236
		return (1);
2237
	}
2238
	if (memcmp(sec1, sec2, sizeof(*sec1) * nsec) == 0)
2239
		return (0);
2240
2241
	for (i = 0; i < nsec; i++)
2242
		sec_fnd[i] = 0;
2243
	/*
2244
	 * Search the new group list starting at the same position in the
2245
	 * Search through the old and new secflavors lists, noting matches.
2246
	 * Since there is no ordering and duplicates can exist in the lists,
2247
	 * the algorithm is inefficient.  However nsec is small and
2248
	 * the common cases are handled above.
2249
	 */
2250
	for (i = 0; i < nsec; i++) {
2251
		fnd = 0;
2252
		for (j = 0; j < nsec; j++) {
2253
			if (sec1[i] == sec2[j]) {
2254
				sec_fnd[j] = 1;
2255
				fnd = 1;
2256
			}
2257
		}
2258
		if (fnd == 0)
2259
			return (1);
2260
	}
2261
	for (i = 0; i < nsec; i++)
2262
		if (sec_fnd[i] == 0)
2263
			return (1);
2264
	return (0);
2265
}
2266
2267
/*
2268
 * Delete an exports entry.
2269
 */
2270
static void
2271
delete_export(struct iovec *iov, int iovlen, struct statfs *fsp, char *errmsg)
2272
{
2273
	struct xvfsconf vfc;
2274
2275
	if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) {
2276
		syslog(LOG_ERR, "getvfsbyname() failed for %s",
2277
		    fsp->f_fstypename);
2278
		return;
2279
	}
2280
	
2281
	/*
2282
	 * We do not need to delete "export" flag from
2283
	 * filesystems that do not have it set.
2284
	 */
2285
	if (!(fsp->f_flags & MNT_EXPORTED))
2286
		return;
2287
	/*
2288
	 * Do not delete export for network filesystem by
2289
	 * passing "export" arg to nmount().
2290
	 * It only makes sense to do this for local filesystems.
2291
	 */
2292
	if (vfc.vfc_flags & VFCF_NETWORK)
2293
		return;
2294
	
2295
	iov[1].iov_base = fsp->f_fstypename;
2296
	iov[1].iov_len = strlen(fsp->f_fstypename) + 1;
2297
	iov[3].iov_base = fsp->f_mntonname;
2298
	iov[3].iov_len = strlen(fsp->f_mntonname) + 1;
2299
	iov[5].iov_base = fsp->f_mntfromname;
2300
	iov[5].iov_len = strlen(fsp->f_mntfromname) + 1;
2301
	errmsg[0] = '\0';
2302
	
2303
	/*
2304
	 * EXDEV is returned when path exists but is not a
2305
	 * mount point.  May happens if raced with unmount.
2306
	 */
2307
	if (nmount(iov, iovlen, fsp->f_flags) < 0 && errno != ENOENT &&
2308
	    errno != ENOTSUP && errno != EXDEV) {
2309
		syslog(LOG_ERR,
2310
		    "can't delete exports for %s: %m %s",
2311
		    fsp->f_mntonname, errmsg);
2312
	}
1869
}
2313
}
1870
2314
1871
/*
2315
/*
Lines 1924-1934 getexp_err(struct exportlist *ep, struct Link Here
1924
 * Search the export list for a matching fs.
2368
 * Search the export list for a matching fs.
1925
 */
2369
 */
1926
static struct exportlist *
2370
static struct exportlist *
1927
ex_search(fsid_t *fsid)
2371
ex_search(fsid_t *fsid, struct exportlisthead *exhp)
1928
{
2372
{
1929
	struct exportlist *ep;
2373
	struct exportlist *ep;
2374
	uint32_t i;
1930
2375
1931
	SLIST_FOREACH(ep, &exphead, entries) {
2376
	i = EXPHASH(fsid);
2377
	SLIST_FOREACH(ep, &exhp[i], entries) {
1932
		if (ep->ex_fs.val[0] == fsid->val[0] &&
2378
		if (ep->ex_fs.val[0] == fsid->val[0] &&
1933
		    ep->ex_fs.val[1] == fsid->val[1])
2379
		    ep->ex_fs.val[1] == fsid->val[1])
1934
			return (ep);
2380
			return (ep);
Lines 1965-1971 add_expdir(struct dirlist **dpp, char *c Link Here
1965
 */
2411
 */
1966
static void
2412
static void
1967
hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
2413
hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
1968
	int flags)
2414
	int flags, struct xucred *anoncrp, int exflags)
1969
{
2415
{
1970
	struct hostlist *hp;
2416
	struct hostlist *hp;
1971
	struct dirlist *dp2;
2417
	struct dirlist *dp2;
Lines 1976-1987 hang_dirp(struct dirlist *dp, struct gro Link Here
1976
		else
2422
		else
1977
			ep->ex_defdir = dp;
2423
			ep->ex_defdir = dp;
1978
		if (grp == (struct grouplist *)NULL) {
2424
		if (grp == (struct grouplist *)NULL) {
2425
			ep->ex_flag |= EX_DEFSET;
1979
			ep->ex_defdir->dp_flag |= DP_DEFSET;
2426
			ep->ex_defdir->dp_flag |= DP_DEFSET;
1980
			/* Save the default security flavors list. */
2427
			/* Save the default security flavors list. */
1981
			ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2428
			ep->ex_defnumsecflavors = ep->ex_numsecflavors;
1982
			if (ep->ex_numsecflavors > 0)
2429
			if (ep->ex_numsecflavors > 0)
1983
				memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2430
				memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
1984
				    sizeof(ep->ex_secflavors));
2431
				    sizeof(ep->ex_secflavors));
2432
			ep->ex_defanon = *anoncrp;
2433
			ep->ex_defexflags = exflags;
1985
		} else while (grp) {
2434
		} else while (grp) {
1986
			hp = get_ht();
2435
			hp = get_ht();
1987
			hp->ht_grp = grp;
2436
			hp->ht_grp = grp;
Lines 2001-2007 hang_dirp(struct dirlist *dp, struct gro Link Here
2001
		 */
2450
		 */
2002
		while (dp) {
2451
		while (dp) {
2003
			dp2 = dp->dp_left;
2452
			dp2 = dp->dp_left;
2004
			add_dlist(&ep->ex_dirl, dp, grp, flags, ep);
2453
			add_dlist(&ep->ex_dirl, dp, grp, flags, ep, anoncrp,
2454
			    exflags);
2005
			dp = dp2;
2455
			dp = dp2;
2006
		}
2456
		}
2007
	}
2457
	}
Lines 2013-2019 hang_dirp(struct dirlist *dp, struct gro Link Here
2013
 */
2463
 */
2014
static void
2464
static void
2015
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
2465
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
2016
	int flags, struct exportlist *ep)
2466
	int flags, struct exportlist *ep, struct xucred *anoncrp, int exflags)
2017
{
2467
{
2018
	struct dirlist *dp;
2468
	struct dirlist *dp;
2019
	struct hostlist *hp;
2469
	struct hostlist *hp;
Lines 2023-2032 add_dlist(struct dirlist **dpp, struct d Link Here
2023
	if (dp) {
2473
	if (dp) {
2024
		cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
2474
		cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
2025
		if (cmp > 0) {
2475
		if (cmp > 0) {
2026
			add_dlist(&dp->dp_left, newdp, grp, flags, ep);
2476
			add_dlist(&dp->dp_left, newdp, grp, flags, ep, anoncrp,
2477
			    exflags);
2027
			return;
2478
			return;
2028
		} else if (cmp < 0) {
2479
		} else if (cmp < 0) {
2029
			add_dlist(&dp->dp_right, newdp, grp, flags, ep);
2480
			add_dlist(&dp->dp_right, newdp, grp, flags, ep, anoncrp,
2481
			    exflags);
2030
			return;
2482
			return;
2031
		} else
2483
		} else
2032
			free((caddr_t)newdp);
2484
			free((caddr_t)newdp);
Lines 2053-2064 add_dlist(struct dirlist **dpp, struct d Link Here
2053
			grp = grp->gr_next;
2505
			grp = grp->gr_next;
2054
		} while (grp);
2506
		} while (grp);
2055
	} else {
2507
	} else {
2508
		ep->ex_flag |= EX_DEFSET;
2056
		dp->dp_flag |= DP_DEFSET;
2509
		dp->dp_flag |= DP_DEFSET;
2057
		/* Save the default security flavors list. */
2510
		/* Save the default security flavors list. */
2058
		ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2511
		ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2059
		if (ep->ex_numsecflavors > 0)
2512
		if (ep->ex_numsecflavors > 0)
2060
			memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2513
			memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2061
			    sizeof(ep->ex_secflavors));
2514
			    sizeof(ep->ex_secflavors));
2515
		ep->ex_defanon = *anoncrp;
2516
		ep->ex_defexflags = exflags;
2062
	}
2517
	}
2063
}
2518
}
2064
2519
Lines 2403-2408 get_host(char *cp, struct grouplist *grp Link Here
2403
static void
2858
static void
2404
free_exp(struct exportlist *ep)
2859
free_exp(struct exportlist *ep)
2405
{
2860
{
2861
	struct grouplist *grp, *tgrp;
2406
2862
2407
	if (ep->ex_defdir) {
2863
	if (ep->ex_defdir) {
2408
		free_host(ep->ex_defdir->dp_hosts);
2864
		free_host(ep->ex_defdir->dp_hosts);
Lines 2413-2422 free_exp(struct exportlist *ep) Link Here
2413
	if (ep->ex_indexfile)
2869
	if (ep->ex_indexfile)
2414
		free(ep->ex_indexfile);
2870
		free(ep->ex_indexfile);
2415
	free_dir(ep->ex_dirl);
2871
	free_dir(ep->ex_dirl);
2872
	grp = ep->ex_grphead;
2873
	while (grp) {
2874
		tgrp = grp;
2875
		grp = grp->gr_next;
2876
		free_grp(tgrp);
2877
	}
2416
	free((caddr_t)ep);
2878
	free((caddr_t)ep);
2417
}
2879
}
2418
2880
2419
/*
2881
/*
2882
 * Free up the v4root exports.
2883
 */
2884
static void
2885
free_v4rootexp(void)
2886
{
2887
2888
	if (v4root_ep != NULL) {
2889
		free_exp(v4root_ep);
2890
		v4root_ep = NULL;
2891
	}
2892
}
2893
2894
/*
2420
 * Free hosts.
2895
 * Free hosts.
2421
 */
2896
 */
2422
static void
2897
static void
Lines 2456-2467 out_of_mem(void) Link Here
2456
}
2931
}
2457
2932
2458
/*
2933
/*
2934
 * Call do_mount() from the struct exportlist, for each case needed.
2935
 */
2936
static int
2937
do_export_mount(struct exportlist *ep, struct statfs *fsp)
2938
{
2939
	struct grouplist *grp, defgrp;
2940
	int ret;
2941
	size_t dirlen;
2942
2943
	MOUNTD_DO_MOUNT_EXPORT("do mount export", ep->ex_fsdir);
2944
	dirlen = strlen(ep->ex_fsdir);
2945
	if ((ep->ex_flag & EX_DEFSET) != 0) {
2946
		defgrp.gr_type = GT_DEFAULT;
2947
		defgrp.gr_next = NULL;
2948
		/* We have an entry for all other hosts/nets. */
2949
		MOUNTD_EX_DEFEXFLAGS("ex defexflags", ep->ex_defexflags);
2950
		ret = do_mount(ep, &defgrp, ep->ex_defexflags, &ep->ex_defanon,
2951
		    ep->ex_fsdir, dirlen, fsp, ep->ex_defnumsecflavors,
2952
		    ep->ex_defsecflavors);
2953
		if (ret != 0)
2954
			return (ret);
2955
	}
2956
2957
	/* Do a mount for each group. */
2958
	grp = ep->ex_grphead;
2959
	while (grp != NULL) {
2960
		MOUNTD_DO_MOUNT_GR_TYPE("do mount gr type", grp->gr_type,
2961
		    grp->gr_exflags);
2962
		ret = do_mount(ep, grp, grp->gr_exflags, &grp->gr_anon,
2963
		    ep->ex_fsdir, dirlen, fsp, grp->gr_numsecflavors,
2964
		    grp->gr_secflavors);
2965
		if (ret != 0)
2966
			return (ret);
2967
		grp = grp->gr_next;
2968
	}
2969
	return (0);
2970
}
2971
2972
/*
2459
 * Do the nmount() syscall with the update flag to push the export info into
2973
 * Do the nmount() syscall with the update flag to push the export info into
2460
 * the kernel.
2974
 * the kernel.
2461
 */
2975
 */
2462
static int
2976
static int
2463
do_mount(struct exportlist *ep, struct grouplist *grp, int exflags,
2977
do_mount(struct exportlist *ep, struct grouplist *grp, int exflags,
2464
    struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb)
2978
    struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb,
2979
    int numsecflavors, int *secflavors)
2465
{
2980
{
2466
	struct statfs fsb1;
2981
	struct statfs fsb1;
2467
	struct addrinfo *ai;
2982
	struct addrinfo *ai;
Lines 2487-2500 do_mount(struct exportlist *ep, struct g Link Here
2487
	bzero(errmsg, sizeof(errmsg));
3002
	bzero(errmsg, sizeof(errmsg));
2488
	eap->ex_flags = exflags;
3003
	eap->ex_flags = exflags;
2489
	eap->ex_anon = *anoncrp;
3004
	eap->ex_anon = *anoncrp;
3005
	MOUNTD_DO_MOUNT_EXFLAGS("do mount exflags", exflags);
2490
	eap->ex_indexfile = ep->ex_indexfile;
3006
	eap->ex_indexfile = ep->ex_indexfile;
2491
	if (grp->gr_type == GT_HOST)
3007
	if (grp->gr_type == GT_HOST)
2492
		ai = grp->gr_ptr.gt_addrinfo;
3008
		ai = grp->gr_ptr.gt_addrinfo;
2493
	else
3009
	else
2494
		ai = NULL;
3010
		ai = NULL;
2495
	eap->ex_numsecflavors = ep->ex_numsecflavors;
3011
	eap->ex_numsecflavors = numsecflavors;
3012
	MOUNTD_DO_MOUNT_NUMSEC("do mount numsec", numsecflavors);
2496
	for (i = 0; i < eap->ex_numsecflavors; i++)
3013
	for (i = 0; i < eap->ex_numsecflavors; i++)
2497
		eap->ex_secflavors[i] = ep->ex_secflavors[i];
3014
		eap->ex_secflavors[i] = secflavors[i];
2498
	if (eap->ex_numsecflavors == 0) {
3015
	if (eap->ex_numsecflavors == 0) {
2499
		eap->ex_numsecflavors = 1;
3016
		eap->ex_numsecflavors = 1;
2500
		eap->ex_secflavors[0] = AUTH_SYS;
3017
		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)
3175
			else if (nfssvc(NFSSVC_PUBLICFH, (caddr_t)&fh) < 0)
2659
				syslog(LOG_ERR,
3176
				syslog(LOG_ERR,
2660
				    "Can't set public fh for %s", public_name);
3177
				    "Can't set public fh for %s", public_name);
2661
			else
3178
			else {
2662
				has_publicfh = 1;
3179
				has_publicfh = 1;
3180
				has_set_publicfh = 1;
3181
				ep->ex_flag |= EX_PUBLICFH;
3182
			}
2663
		}
3183
		}
2664
skip:
3184
skip:
2665
		if (ai != NULL)
3185
		if (ai != NULL)
Lines 2824-2841 static void Link Here
2824
nextfield(char **cp, char **endcp)
3344
nextfield(char **cp, char **endcp)
2825
{
3345
{
2826
	char *p;
3346
	char *p;
3347
	char quot = 0;
2827
3348
2828
	p = *cp;
3349
	p = *cp;
2829
	while (*p == ' ' || *p == '\t')
3350
	while (*p == ' ' || *p == '\t')
2830
		p++;
3351
		p++;
2831
	if (*p == '\n' || *p == '\0')
3352
	*cp = p;
2832
		*cp = *endcp = p;
3353
	while (*p != '\0') {
2833
	else {
3354
		if (quot) {
2834
		*cp = p++;
3355
			if (*p == quot)
2835
		while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
3356
				quot = 0;
2836
			p++;
3357
		} else {
2837
		*endcp = p;
3358
			if (*p == '\\' && *(p + 1) != '\0')
2838
	}
3359
				p++;
3360
			else if (*p == '\'' || *p == '"')
3361
				quot = *p;
3362
			else if (*p == ' ' || *p == '\t')
3363
				break;
3364
		}
3365
		p++;
3366
	};
3367
	*endcp = p;
2839
}
3368
}
2840
3369
2841
/*
3370
/*
Lines 2907-2914 parsecred(char *namelist, struct xucred Link Here
2907
	/*
3436
	/*
2908
	 * Get the user's password table entry.
3437
	 * Get the user's password table entry.
2909
	 */
3438
	 */
2910
	names = strsep_quote(&namelist, " \t\n");
3439
	names = namelist;
2911
	name = strsep(&names, ":");
3440
	name = strsep_quote(&names, ":");
2912
	/* Bug?  name could be NULL here */
3441
	/* Bug?  name could be NULL here */
2913
	if (isdigit(*name) || *name == '-')
3442
	if (isdigit(*name) || *name == '-')
2914
		pw = getpwuid(atoi(name));
3443
		pw = getpwuid(atoi(name));
Lines 2952-2958 parsecred(char *namelist, struct xucred Link Here
2952
	}
3481
	}
2953
	cr->cr_ngroups = 0;
3482
	cr->cr_ngroups = 0;
2954
	while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) {
3483
	while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) {
2955
		name = strsep(&names, ":");
3484
		name = strsep_quote(&names, ":");
2956
		if (isdigit(*name) || *name == '-') {
3485
		if (isdigit(*name) || *name == '-') {
2957
			cr->cr_groups[cr->cr_ngroups++] = atoi(name);
3486
			cr->cr_groups[cr->cr_ngroups++] = atoi(name);
2958
		} else {
3487
		} else {
(-)usr.sbin/mountd/mountd_dt.d (+22 lines)
Line 0 Link Here
1
/* $FreeBSD$ */
2
3
provider mountd {
4
	probe passno(char *, int);
5
	probe compareok(char *);
6
	probe passno_0(char *);
7
	probe eo_get_exportlist(char *);
8
	probe fs_hash(char *, char *, uint32_t);
9
	probe foreach_ep(char *, char *);
10
	probe found_old_exp(char *);
11
	probe same_fsdir(char *);
12
	probe exdone(char *);
13
	probe not_found_so_export(char *);
14
	probe not_done_delete(char *, char *);
15
	probe do_delete(char *);
16
	probe v4root_expath(char *, char *);
17
	probe do_mount_export(char *, char *);
18
	probe ex_defexflags(char *, int);
19
	probe do_mount_gr_type(char *, int, int);
20
	probe do_mount_exflags(char *, int);
21
	probe do_mount_numsec(char *, int);
22
};

Return to bug 237860