aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/inetd
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2020-01-01 04:22:04 +0000
committerKyle Evans <kevans@FreeBSD.org>2020-01-01 04:22:04 +0000
commitc53b0f40f3b3000d37d533f7f32cf4132d057bd3 (patch)
treeb7d3573de80c2e319cbbe2a68a43d18e854a11a3 /usr.sbin/inetd
parentd6272fce7c1a45863c1fc64d348e07668429ef4d (diff)
downloadsrc-c53b0f40f3b3000d37d533f7f32cf4132d057bd3.tar.gz
src-c53b0f40f3b3000d37d533f7f32cf4132d057bd3.zip
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
Notes
Notes: svn path=/head/; revision=356247
Diffstat (limited to 'usr.sbin/inetd')
-rw-r--r--usr.sbin/inetd/inetd.c62
-rw-r--r--usr.sbin/inetd/inetd.h7
2 files changed, 40 insertions, 29 deletions
diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c
index cb3fad815d23..fb52ed9faed5 100644
--- a/usr.sbin/inetd/inetd.c
+++ b/usr.sbin/inetd/inetd.c
@@ -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 @@ more:
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 @@ more:
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]);
diff --git a/usr.sbin/inetd/inetd.h b/usr.sbin/inetd/inetd.h
index 412dbdcd132e..a7dc89ad7015 100644
--- a/usr.sbin/inetd/inetd.h
+++ b/usr.sbin/inetd/inetd.h
@@ -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