inetd: track all child pids, regardless of maxchild spec

Currently, child pids are only tracked if maxchildren is specified. As a
consequence, without a maxchild limit we do not get a notice in syslog on
children aborting abnormally. This turns out to be a great debugging aide at
times.

Children are now tracked in a LIST; the management interface is decidedly
less painful when there's no upper bound on the number of entries we may
have at the cost of one small allocation per connection.

PR:		70335
This commit is contained in:
Kyle Evans 2020-01-01 04:22:04 +00:00
parent d6272fce7c
commit c53b0f40f3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=356247
2 changed files with 40 additions and 29 deletions

View File

@ -922,8 +922,8 @@ flag_signal(int signo)
static void
addchild(struct servtab *sep, pid_t pid)
{
if (sep->se_maxchild <= 0)
return;
struct stabchild *sc;
#ifdef SANITY_CHECK
if (SERVTAB_EXCEEDS_LIMIT(sep)) {
syslog(LOG_ERR, "%s: %d >= %d",
@ -931,7 +931,15 @@ addchild(struct servtab *sep, pid_t pid)
exit(EX_SOFTWARE);
}
#endif
sep->se_pids[sep->se_numchild++] = pid;
sc = malloc(sizeof(*sc));
if (sc == NULL) {
syslog(LOG_ERR, "malloc: %m");
exit(EX_OSERR);
}
memset(sc, 0, sizeof(*sc));
sc->sc_pid = pid;
LIST_INSERT_HEAD(&sep->se_children, sc, sc_link);
++sep->se_numchild;
if (SERVTAB_AT_LIMIT(sep))
disable(sep);
}
@ -939,8 +947,9 @@ addchild(struct servtab *sep, pid_t pid)
static void
reapchild(void)
{
int k, status;
int status;
pid_t pid;
struct stabchild *sc;
struct servtab *sep;
for (;;) {
@ -953,14 +962,17 @@ reapchild(void)
WIFEXITED(status) ? WEXITSTATUS(status)
: WTERMSIG(status));
for (sep = servtab; sep; sep = sep->se_next) {
for (k = 0; k < sep->se_numchild; k++)
if (sep->se_pids[k] == pid)
LIST_FOREACH(sc, &sep->se_children, sc_link) {
if (sc->sc_pid == pid)
break;
if (k == sep->se_numchild)
}
if (sc == NULL)
continue;
if (SERVTAB_AT_LIMIT(sep))
enable(sep);
sep->se_pids[k] = sep->se_pids[--sep->se_numchild];
LIST_REMOVE(sc, sc_link);
free(sc);
--sep->se_numchild;
if (WIFSIGNALED(status) || WEXITSTATUS(status))
syslog(LOG_WARNING,
"%s[%d]: exited, %s %u",
@ -1032,18 +1044,14 @@ config(void)
sep->se_nomapped = new->se_nomapped;
sep->se_reset = 1;
}
/* copy over outstanding child pids */
if (sep->se_maxchild > 0 && new->se_maxchild > 0) {
new->se_numchild = sep->se_numchild;
if (new->se_numchild > new->se_maxchild)
new->se_numchild = new->se_maxchild;
memcpy(new->se_pids, sep->se_pids,
new->se_numchild * sizeof(*new->se_pids));
}
SWAP(pid_t *, sep->se_pids, new->se_pids);
sep->se_maxchild = new->se_maxchild;
sep->se_numchild = new->se_numchild;
/*
* The children tracked remain; we want numchild to
* still reflect how many jobs are running so we don't
* throw off our accounting.
*/
sep->se_maxcpm = new->se_maxcpm;
sep->se_maxchild = new->se_maxchild;
resize_conn(sep, new->se_maxperip);
sep->se_maxperip = new->se_maxperip;
sep->se_bi = new->se_bi;
@ -1949,13 +1957,7 @@ getconfigent(void)
else
sep->se_maxchild = 1;
}
if (sep->se_maxchild > 0) {
sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids));
if (sep->se_pids == NULL) {
syslog(LOG_ERR, "malloc: %m");
exit(EX_OSERR);
}
}
LIST_INIT(&sep->se_children);
argc = 0;
for (arg = skip(&cp); cp; arg = skip(&cp))
if (argc < MAXARGV) {
@ -1980,6 +1982,7 @@ getconfigent(void)
static void
freeconfig(struct servtab *cp)
{
struct stabchild *sc;
int i;
if (cp->se_service)
@ -1996,8 +1999,11 @@ freeconfig(struct servtab *cp)
#endif
if (cp->se_server)
free(cp->se_server);
if (cp->se_pids)
free(cp->se_pids);
while (!LIST_EMPTY(&cp->se_children)) {
sc = LIST_FIRST(&cp->se_children);
LIST_REMOVE(sc, sc_link);
free(sc);
}
for (i = 0; i < MAXARGV; i++)
if (cp->se_argv[i])
free(cp->se_argv[i]);

View File

@ -66,6 +66,11 @@ struct conninfo {
#define PERIPSIZE 256
struct stabchild {
LIST_ENTRY(stabchild) sc_link;
pid_t sc_pid;
};
struct servtab {
char *se_service; /* name of service */
int se_socktype; /* type of socket to use */
@ -74,7 +79,6 @@ struct servtab {
int se_maxchild; /* max number of children */
int se_maxcpm; /* max connects per IP per minute */
int se_numchild; /* current number of children */
pid_t *se_pids; /* array of child pids */
char *se_user; /* user name to run as */
char *se_group; /* group name to run as */
#ifdef LOGIN_CAP
@ -119,6 +123,7 @@ struct servtab {
} se_flags;
int se_maxperip; /* max number of children per src */
LIST_HEAD(, conninfo) se_conn[PERIPSIZE];
LIST_HEAD(, stabchild) se_children;
};
#define se_nomapped se_flags.se_nomapped