diff options
author | iedowse <iedowse@FreeBSD.org> | 2001-04-21 00:55:17 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2001-04-21 00:55:17 +0000 |
commit | 439a88e5fd41053348c67e3cd4a183aceb2721ac (patch) | |
tree | bdba062d32ca83c3e6775c7aebc548d278469bb4 /usr.sbin/mountd | |
parent | 4afc893059960f8a18555e9e7eddb210fca8edec (diff) | |
download | FreeBSD-src-439a88e5fd41053348c67e3cd4a183aceb2721ac.zip FreeBSD-src-439a88e5fd41053348c67e3cd4a183aceb2721ac.tar.gz |
Fix a long-standing bug relating to the handling of SIGHUP: mountd
would call malloc, stdio and other library functions from the signal
handler which is not safe due to reentrancy problems.
Instead, add a simple handler that just sets a flag, and call the
more complex function from main() when necessary. Unfortunately to
be able to check this flag, we must expand the svc_run() call, but
the RPC library makes that relatively easy to do.
Diffstat (limited to 'usr.sbin/mountd')
-rw-r--r-- | usr.sbin/mountd/mountd.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c index a8e113c..f1c56ff 100644 --- a/usr.sbin/mountd/mountd.c +++ b/usr.sbin/mountd/mountd.c @@ -188,6 +188,7 @@ void getexp_err __P((struct exportlist *, struct grouplist *)); struct grouplist *get_grp __P((void)); void hang_dirp __P((struct dirlist *, struct grouplist *, struct exportlist *, int)); +void huphandler(int sig); void mntsrv __P((struct svc_req *, SVCXPRT *)); void nextfield __P((char **, char **)); void out_of_mem __P((void)); @@ -222,6 +223,7 @@ int force_v2 = 0; int resvport_only = 1; int dir_only = 1; int log = 0; +int got_sighup = 0; int opt_flags; static int have_v6 = 1; @@ -261,6 +263,7 @@ main(argc, argv) int argc; char **argv; { + fd_set readfds; SVCXPRT *udptransp, *tcptransp, *udp6transp, *tcp6transp; struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf; int udpsock, tcpsock, udp6sock, tcp6sock; @@ -337,7 +340,7 @@ main(argc, argv) signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); } - signal(SIGHUP, (void (*) __P((int))) get_exportlist); + signal(SIGHUP, huphandler); signal(SIGTERM, terminate); { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); if (pidfile != NULL) { @@ -475,9 +478,26 @@ skip_v6: syslog(LOG_ERR, "could not create any services"); exit(1); } - svc_run(); - syslog(LOG_ERR, "mountd died"); - exit(1); + + /* Expand svc_run() here so that we can call get_exportlist(). */ + for (;;) { + if (got_sighup) { + get_exportlist(); + got_sighup = 0; + } + readfds = svc_fdset; + switch (select(svc_maxfd + 1, &readfds, NULL, NULL, NULL)) { + case -1: + if (errno == EINTR) + continue; + syslog(LOG_ERR, "mountd died: select: %m"); + exit(1); + case 0: + continue; + default: + svc_getreqset(&readfds); + } + } } static void @@ -2455,6 +2475,12 @@ sacmp(struct sockaddr *sa1, struct sockaddr *sa2) return memcmp(p1, p2, len); } +void +huphandler(int sig) +{ + got_sighup = 1; +} + void terminate(sig) int sig; { |