Correct two bugs:

- If a child receives a SIGTERM, it will call the terminate() function
  and end up doing the shutdown procedurs that should really only be
  done by the parent. Set the SIGTERM behavior back to SIG_DLT in the
  child after fork()ing.

- If the parent fails to read data back from the child because the
  child has exited, it will call rpc_received() with bogus tdata that
  can cause the parent to SEGV. Make handle_children() detect this
  condition correctly and handle it sanely.

*sigh* Another 2.2 candidate.
This commit is contained in:
Bill Paul 1997-01-11 17:16:18 +00:00
parent 4387f78ffa
commit 341460c3b5

View File

@ -28,7 +28,7 @@
*/
#ifndef LINT
static char rcsid[] = "$Id: ypbind.c,v 1.18 1995/12/15 03:39:25 wpaul Exp $";
static char rcsid[] = "$Id: ypbind.c,v 1.19 1996/12/30 15:31:26 peter Exp $";
#endif
#include <sys/param.h>
@ -132,7 +132,7 @@ struct in_addr restricted_addrs[RESTRICTED_SERVERS];
#endif
/* RPC timeout value */
#ifndef FAIL_THRESHOLD
#define FAIL_THRESHOLD 10
#define FAIL_THRESHOLD 20
#endif
/* Number of times to fish for a response froma particular set of hosts */
@ -193,7 +193,7 @@ CLIENT *clnt;
}
ypdb = (struct _dom_binding *)malloc(sizeof *ypdb);
if (ypdb == NULL) {
syslog(LOG_WARNING, "malloc: %s", strerror(errno));
syslog(LOG_WARNING, "malloc: %m");
res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC;
return &res;
}
@ -483,7 +483,7 @@ char **argv;
break;
case -1:
if (errno != EINTR)
syslog(LOG_WARNING, "select: %s", strerror(errno));
syslog(LOG_WARNING, "select: %m");
break;
default:
for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) {
@ -525,17 +525,52 @@ struct _dom_binding *ypdb;
{
char buf[YPMAXDOMAIN + 1];
struct sockaddr_in addr;
int d = 0, a = 0;
struct _dom_binding *y, *prev = NULL;
char path[MAXPATHLEN];
if (read(READFD, &buf, sizeof(buf)) < 0)
syslog(LOG_WARNING, "could not read from child: %s", strerror(errno));
if (read(READFD, &addr, sizeof(struct sockaddr_in)) < 0)
syslog(LOG_WARNING, "could not read from child: %s", strerror(errno));
if ((d = read(READFD, &buf, sizeof(buf))) <= 0)
syslog(LOG_WARNING, "could not read from child: %m");
if ((a = read(READFD, &addr, sizeof(struct sockaddr_in))) < 0)
syslog(LOG_WARNING, "could not read from child: %m");
close(READFD);
FD_CLR(READFD, &fdsr);
FD_CLR(READFD, &svc_fdset);
READFD = WRITEFD = -1;
rpc_received((char *)&buf, &addr, 0);
if (d > 0 && a > 0)
rpc_received((char *)&buf, &addr, 0);
else {
for(y=ypbindlist; y; y=y->dom_pnext) {
if (y == ypdb)
break;
prev = y;
}
switch(ypdb->dom_default) {
case 0:
if (prev == NULL)
ypbindlist = y->dom_pnext;
else
prev->dom_pnext = y->dom_pnext;
sprintf(path, "%s/%s.%ld", BINDINGDIR,
ypdb->dom_domain, YPVERS);
close(ypdb->dom_lockfd);
unlink(path);
free(ypdb);
domains--;
return;
case 1:
ypdb->dom_broadcast_pid = 0;
ypdb->dom_alive = 0;
broadcast(ypdb);
return;
default:
break;
}
}
return;
}
/*
@ -620,7 +655,7 @@ struct _dom_binding *ypdb;
return;
if (pipe(ypdb->dom_pipe_fds) < 0) {
syslog(LOG_WARNING, "pipe: %s",strerror(errno));
syslog(LOG_WARNING, "pipe: %m");
return;
}
@ -634,9 +669,11 @@ struct _dom_binding *ypdb;
switch((ypdb->dom_broadcast_pid = fork())) {
case 0:
close(READFD);
signal(SIGCHLD, SIG_DFL);
signal(SIGTERM, SIG_DFL);
break;
case -1:
syslog(LOG_WARNING, "fork: %s", strerror(errno));
syslog(LOG_WARNING, "fork: %m");
close(READFD);
close(WRITEFD);
return;
@ -810,7 +847,7 @@ int force;
return;
ypdb = (struct _dom_binding *)malloc(sizeof *ypdb);
if (ypdb == NULL) {
syslog(LOG_WARNING, "malloc: %s", strerror(errno));
syslog(LOG_WARNING, "malloc: %m");
return;
}
bzero((char *)ypdb, sizeof *ypdb);
@ -870,7 +907,7 @@ int force;
*(u_short *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port = raddrp->sin_port;
if( writev(ypdb->dom_lockfd, iov, 2) != iov[0].iov_len + iov[1].iov_len) {
syslog(LOG_WARNING, "write: %s", strerror(errno));
syslog(LOG_WARNING, "write: %m");
close(ypdb->dom_lockfd);
ypdb->dom_lockfd = -1;
return;