Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 24 Oct 2020 22:48:28 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r367026 - head/usr.sbin/mountd
Message-ID:  <202010242248.09OMmSfj036699@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sat Oct 24 22:48:28 2020
New Revision: 367026
URL: https://svnweb.freebsd.org/changeset/base/367026

Log:
  Add "-R" option to tell mountd to not register with rpcbind.
  
  rpcbind is now considered a security risk for some sites.
  Since an NFSv4 only NFS server does not need rpcbind,
  it makes sense to have an option that implements this.
  
  This patch adds a "-R" option that disables the Mount
  protocol (not used by NFSv4) and does not register
  with rpcbind.
  
  Changes are required to /etc/rc.d/mountd and /etc/rc.d/nfsd.
  Those will be in a separate commit.
  
  Reviewed by:	freqlabs, asomers
  MFC after:	2 weeks
  Differential Revision:	https://reviews.freebsd.org/D26746

Modified:
  head/usr.sbin/mountd/mountd.c

Modified: head/usr.sbin/mountd/mountd.c
==============================================================================
--- head/usr.sbin/mountd/mountd.c	Sat Oct 24 22:36:20 2020	(r367025)
+++ head/usr.sbin/mountd/mountd.c	Sat Oct 24 22:48:28 2020	(r367026)
@@ -427,8 +427,10 @@ main(int argc, char **argv)
 	uint64_t curtime, nexttime;
 	struct timeval tv;
 	struct timespec tp;
-	sigset_t sighup_mask;
+	sigset_t sig_mask, sighup_mask;
+	int enable_rpcbind;
 
+	enable_rpcbind = 1;
 	/* Check that another mountd isn't already running. */
 	pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
 	if (pfh == NULL) {
@@ -443,7 +445,7 @@ main(int argc, char **argv)
 	else
 		close(s);
 
-	while ((c = getopt(argc, argv, "2deh:lnp:rS")) != -1)
+	while ((c = getopt(argc, argv, "2deh:lnp:RrS")) != -1)
 		switch (c) {
 		case '2':
 			force_v2 = 1;
@@ -454,6 +456,10 @@ main(int argc, char **argv)
 		case 'n':
 			resvport_only = 0;
 			break;
+		case 'R':
+			/* Do not support Mount protocol */
+			enable_rpcbind = 0;
+			break;
 		case 'r':
 			dir_only = 0;
 			break;
@@ -498,6 +504,21 @@ main(int argc, char **argv)
 		default:
 			usage();
 		}
+	if (enable_rpcbind == 0) {
+		if (svcport_str != NULL) {
+			warnx("-p option not compatible with -R, ignored");
+			free(svcport_str);
+			svcport_str = NULL;
+		}
+		if (nhosts > 0) {
+			warnx("-h option not compatible with -R, ignored");
+			for (k = 0; k < nhosts; k++) 
+				free(hosts[k]);
+			free(hosts);
+			hosts = NULL;
+			nhosts = 0;
+		}
+	}
 
 	if (modfind("nfsd") < 0) {
 		/* Not present in kernel, try loading it */
@@ -531,58 +552,61 @@ main(int argc, char **argv)
 
 	pidfile_write(pfh);
 
-	rpcb_unset(MOUNTPROG, MOUNTVERS, NULL);
-	rpcb_unset(MOUNTPROG, MOUNTVERS3, NULL);
-	rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
+	if (enable_rpcbind != 0) {
+		rpcb_unset(MOUNTPROG, MOUNTVERS, NULL);
+		rpcb_unset(MOUNTPROG, MOUNTVERS3, NULL);
+		rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
 
-	if (!resvport_only) {
-		if (sysctlbyname("vfs.nfsd.nfs_privport", NULL, NULL,
-		    &resvport_only, sizeof(resvport_only)) != 0 &&
-		    errno != ENOENT) {
-			syslog(LOG_ERR, "sysctl: %m");
-			exit(1);
+		if (!resvport_only) {
+			if (sysctlbyname("vfs.nfsd.nfs_privport", NULL, NULL,
+			    &resvport_only, sizeof(resvport_only)) != 0 &&
+			    errno != ENOENT) {
+				syslog(LOG_ERR, "sysctl: %m");
+				exit(1);
+			}
 		}
-	}
 
-	/*
-	 * If no hosts were specified, add a wildcard entry to bind to
-	 * INADDR_ANY. Otherwise make sure 127.0.0.1 and ::1 are added to the
-	 * list.
-	 */
-	if (nhosts == 0) {
-		hosts = malloc(sizeof(char *));
-		if (hosts == NULL)
-			out_of_mem();
-		hosts[0] = "*";
-		nhosts = 1;
-	} else {
-		hosts_bak = hosts;
-		if (have_v6) {
-			hosts_bak = realloc(hosts, (nhosts + 2) *
-			    sizeof(char *));
-			if (hosts_bak == NULL) {
-				for (k = 0; k < nhosts; k++)
-					free(hosts[k]);
-		    		free(hosts);
-		    		out_of_mem();
-			} else
-				hosts = hosts_bak;
-			nhosts += 2;
-			hosts[nhosts - 2] = "::1";
-		} else {
-			hosts_bak = realloc(hosts, (nhosts + 1) * sizeof(char *));
-			if (hosts_bak == NULL) {
-				for (k = 0; k < nhosts; k++)
-					free(hosts[k]);
-				free(hosts);
+		/*
+		 * If no hosts were specified, add a wildcard entry to bind to
+		 * INADDR_ANY. Otherwise make sure 127.0.0.1 and ::1 are added
+		 * to the list.
+		 */
+		if (nhosts == 0) {
+			hosts = malloc(sizeof(char *));
+			if (hosts == NULL)
 				out_of_mem();
+			hosts[0] = "*";
+			nhosts = 1;
+		} else {
+			hosts_bak = hosts;
+			if (have_v6) {
+				hosts_bak = realloc(hosts, (nhosts + 2) *
+				    sizeof(char *));
+				if (hosts_bak == NULL) {
+					for (k = 0; k < nhosts; k++)
+						free(hosts[k]);
+			    		free(hosts);
+			    		out_of_mem();
+				} else
+					hosts = hosts_bak;
+				nhosts += 2;
+				hosts[nhosts - 2] = "::1";
 			} else {
-				nhosts += 1;
-				hosts = hosts_bak;
+				hosts_bak = realloc(hosts, (nhosts + 1) *
+				    sizeof(char *));
+				if (hosts_bak == NULL) {
+					for (k = 0; k < nhosts; k++)
+						free(hosts[k]);
+					free(hosts);
+					out_of_mem();
+				} else {
+					nhosts += 1;
+					hosts = hosts_bak;
+				}
 			}
-		}
 
-		hosts[nhosts - 1] = "127.0.0.1";
+			hosts[nhosts - 1] = "127.0.0.1";
+		}
 	}
 
 	attempt_cnt = 1;
@@ -590,96 +614,109 @@ main(int argc, char **argv)
 	sock_fd = NULL;
 	port_list = NULL;
 	port_len = 0;
-	nc_handle = setnetconfig();
-	while ((nconf = getnetconfig(nc_handle))) {
-		if (nconf->nc_flag & NC_VISIBLE) {
-			if (have_v6 == 0 && strcmp(nconf->nc_protofmly,
-			    "inet6") == 0) {
-				/* DO NOTHING */
-			} else {
-				ret = create_service(nconf);
-				if (ret == 1)
-					/* Ignore this call */
-					continue;
-				if (ret < 0) {
-					/*
-					 * Failed to bind port, so close off
-					 * all sockets created and try again
-					 * if the port# was dynamically
-					 * assigned via bind(2).
-					 */
-					clearout_service();
-					if (mallocd_svcport != 0 &&
-					    attempt_cnt < GETPORT_MAXTRY) {
-						free(svcport_str);
+	if (enable_rpcbind != 0) {
+		nc_handle = setnetconfig();
+		while ((nconf = getnetconfig(nc_handle))) {
+			if (nconf->nc_flag & NC_VISIBLE) {
+				if (have_v6 == 0 && strcmp(nconf->nc_protofmly,
+				    "inet6") == 0) {
+					/* DO NOTHING */
+				} else {
+					ret = create_service(nconf);
+					if (ret == 1)
+						/* Ignore this call */
+						continue;
+					if (ret < 0) {
+						/*
+						 * Failed to bind port, so close
+						 * off all sockets created and
+						 * try again if the port# was
+						 * dynamically assigned via
+						 * bind(2).
+						 */
+						clearout_service();
+						if (mallocd_svcport != 0 &&
+						    attempt_cnt <
+						    GETPORT_MAXTRY) {
+							free(svcport_str);
+							svcport_str = NULL;
+							mallocd_svcport = 0;
+						} else {
+							errno = EADDRINUSE;
+							syslog(LOG_ERR,
+							    "bindresvport_sa:"
+							    " %m");
+							exit(1);
+						}
+
+						/*
+						 * Start over at the first
+						 * service.
+						 */
+						free(sock_fd);
+						sock_fdcnt = 0;
+						sock_fd = NULL;
+						nc_handle = setnetconfig();
+						attempt_cnt++;
+					} else if (mallocd_svcport != 0 &&
+					    attempt_cnt == GETPORT_MAXTRY) {
+						/*
+						 * For the last attempt, allow
+						 * different port #s for each
+						 * nconf by saving the
+						 * svcport_str setting it back
+						 * to NULL.
+						 */
+						port_list = realloc(port_list,
+						    (port_len + 1) *
+						    sizeof(char *));
+						if (port_list == NULL)
+							out_of_mem();
+						port_list[port_len++] =
+						    svcport_str;
 						svcport_str = NULL;
 						mallocd_svcport = 0;
-					} else {
-						errno = EADDRINUSE;
-						syslog(LOG_ERR,
-						    "bindresvport_sa: %m");
-						exit(1);
 					}
-
-					/* Start over at the first service. */
-					free(sock_fd);
-					sock_fdcnt = 0;
-					sock_fd = NULL;
-					nc_handle = setnetconfig();
-					attempt_cnt++;
-				} else if (mallocd_svcport != 0 &&
-				    attempt_cnt == GETPORT_MAXTRY) {
-					/*
-					 * For the last attempt, allow
-					 * different port #s for each nconf
-					 * by saving the svcport_str and
-					 * setting it back to NULL.
-					 */
-					port_list = realloc(port_list,
-					    (port_len + 1) * sizeof(char *));
-					if (port_list == NULL)
-						out_of_mem();
-					port_list[port_len++] = svcport_str;
-					svcport_str = NULL;
-					mallocd_svcport = 0;
 				}
 			}
 		}
-	}
 
-	/*
-	 * Successfully bound the ports, so call complete_service() to
-	 * do the rest of the setup on the service(s).
-	 */
-	sock_fdpos = 0;
-	port_pos = 0;
-	nc_handle = setnetconfig();
-	while ((nconf = getnetconfig(nc_handle))) {
-		if (nconf->nc_flag & NC_VISIBLE) {
-			if (have_v6 == 0 && strcmp(nconf->nc_protofmly,
-			    "inet6") == 0) {
-				/* DO NOTHING */
-			} else if (port_list != NULL) {
-				if (port_pos >= port_len) {
-					syslog(LOG_ERR, "too many port#s");
-					exit(1);
-				}
-				complete_service(nconf, port_list[port_pos++]);
-			} else
-				complete_service(nconf, svcport_str);
+		/*
+		 * Successfully bound the ports, so call complete_service() to
+		 * do the rest of the setup on the service(s).
+		 */
+		sock_fdpos = 0;
+		port_pos = 0;
+		nc_handle = setnetconfig();
+		while ((nconf = getnetconfig(nc_handle))) {
+			if (nconf->nc_flag & NC_VISIBLE) {
+				if (have_v6 == 0 && strcmp(nconf->nc_protofmly,
+				    "inet6") == 0) {
+					/* DO NOTHING */
+				} else if (port_list != NULL) {
+					if (port_pos >= port_len) {
+						syslog(LOG_ERR, "too many"
+						    " port#s");
+						exit(1);
+					}
+					complete_service(nconf,
+					    port_list[port_pos++]);
+				} else
+					complete_service(nconf, svcport_str);
+			}
 		}
-	}
-	endnetconfig(nc_handle);
-	free(sock_fd);
-	if (port_list != NULL) {
-		for (port_pos = 0; port_pos < port_len; port_pos++)
-			free(port_list[port_pos]);
-		free(port_list);
-	}
+		endnetconfig(nc_handle);
+		free(sock_fd);
+		if (port_list != NULL) {
+			for (port_pos = 0; port_pos < port_len; port_pos++)
+				free(port_list[port_pos]);
+			free(port_list);
+		}
 
-	if (xcreated == 0) {
-		syslog(LOG_ERR, "could not create any services");
-		exit(1);
+		if (xcreated == 0) {
+			syslog(LOG_ERR, "could not create any services");
+			exit(1);
+		}
 	}
 
 	/* Expand svc_run() here so that we can call get_exportlist(). */
@@ -690,7 +727,7 @@ main(int argc, char **argv)
 		clock_gettime(CLOCK_MONOTONIC, &tp);
 		curtime = tp.tv_sec;
 		curtime = curtime * 1000000 + tp.tv_nsec / 1000;
-		sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
+		sigprocmask(SIG_BLOCK, &sighup_mask, &sig_mask);
 		if (got_sighup && curtime >= nexttime) {
 			got_sighup = 0;
 			sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
@@ -713,22 +750,28 @@ main(int argc, char **argv)
 			tv.tv_usec = 0;
 		else
 			tv.tv_usec = RELOADDELAY;
-		readfds = svc_fdset;
-		switch (select(svc_maxfd + 1, &readfds, NULL, NULL, &tv)) {
-		case -1:
-			if (errno == EINTR) {
+		if (enable_rpcbind != 0) {
+			readfds = svc_fdset;
+			switch (select(svc_maxfd + 1, &readfds, NULL, NULL,
+			    &tv)) {
+			case -1:
+				if (errno == EINTR) {
+					/* Allow a reload now. */
+					nexttime = 0;
+					continue;
+				}
+				syslog(LOG_ERR, "mountd died: select: %m");
+				exit(1);
+			case 0:
 				/* Allow a reload now. */
 				nexttime = 0;
 				continue;
+			default:
+				svc_getreqset(&readfds);
 			}
-			syslog(LOG_ERR, "mountd died: select: %m");
-			exit(1);
-		case 0:
-			/* Allow a reload now. */
-			nexttime = 0;
-			continue;
-		default:
-			svc_getreqset(&readfds);
+		} else {
+			/* Simply wait for a signal. */
+			sigsuspend(&sig_mask);
 		}
 	}
 } 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202010242248.09OMmSfj036699>