aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/mountd
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2020-10-24 22:48:28 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2020-10-24 22:48:28 +0000
commitbde6f938bfe0243072f8799aaa6589557b01faab (patch)
treeff800e203e8fcd8a54abffcebcfae2a9acd3a3b5 /usr.sbin/mountd
parentae37905b93d1fcb4e798fad7ac3b869198fd917f (diff)
downloadsrc-bde6f938bfe0243072f8799aaa6589557b01faab.tar.gz
src-bde6f938bfe0243072f8799aaa6589557b01faab.zip
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
Notes
Notes: svn path=/head/; revision=367026
Diffstat (limited to 'usr.sbin/mountd')
-rw-r--r--usr.sbin/mountd/mountd.c325
1 files changed, 184 insertions, 141 deletions
diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c
index e5a41934b827..76972c66a6ed 100644
--- a/usr.sbin/mountd/mountd.c
+++ b/usr.sbin/mountd/mountd.c
@@ -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);
}
}
}