diff options
author | dwmalone <dwmalone@FreeBSD.org> | 2003-02-23 16:54:19 +0000 |
---|---|---|
committer | dwmalone <dwmalone@FreeBSD.org> | 2003-02-23 16:54:19 +0000 |
commit | dff9ad9d4466cd10a9d3eb787a6638565fd087c0 (patch) | |
tree | 15d6317cfceb92f4e45245d34817c0eb3807530f /usr.sbin/inetd | |
parent | 1825d6d17dc5133b018a2bacfbf1949153cc05be (diff) | |
download | FreeBSD-src-dff9ad9d4466cd10a9d3eb787a6638565fd087c0.zip FreeBSD-src-dff9ad9d4466cd10a9d3eb787a6638565fd087c0.tar.gz |
Under some unusual conditions, inetd can leak a open file discriptor
into a child process. Rather than closing the discriptors manually,
mark all discriptors as close-on-exec.
PR: 47694
Submitted by: Max Okumoto <okumoto@ucsd.edu>
Obtained from: NetBSD
MFC after: 2 weeks
Diffstat (limited to 'usr.sbin/inetd')
-rw-r--r-- | usr.sbin/inetd/inetd.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c index 238e727..213683c 100644 --- a/usr.sbin/inetd/inetd.c +++ b/usr.sbin/inetd/inetd.c @@ -544,6 +544,11 @@ main(int argc, char **argv) syslog(LOG_ERR, "pipe: %m"); exit(EX_OSERR); } + if (fcntl(signalpipe[0], F_SETFD, FD_CLOEXEC) < 0 || + fcntl(signalpipe[1], F_SETFD, FD_CLOEXEC) < 0) { + syslog(LOG_ERR, "signalpipe: fcntl (F_SETFD, FD_CLOEXEC): %m"); + exit(EX_OSERR); + } FD_SET(signalpipe[0], &allsock); #ifdef SANITY_CHECK nsock++; @@ -724,11 +729,6 @@ main(int argc, char **argv) sigsetmask(0L); if (pid == 0) { if (dofork) { - if (debug) - warnx("+ closing from %d", maxsock); - for (tmpint = maxsock; tmpint > 2; tmpint--) - if (tmpint != ctrl) - (void) close(tmpint); sigaction(SIGALRM, &saalrm, (struct sigaction *)0); sigaction(SIGCHLD, &sachld, (struct sigaction *)0); sigaction(SIGHUP, &sahup, (struct sigaction *)0); @@ -779,8 +779,17 @@ main(int argc, char **argv) if (debug) warnx("%d execl %s", getpid(), sep->se_server); - dup2(ctrl, 0); - close(ctrl); + /* Clear close-on-exec. */ + if (fcntl(ctrl, F_SETFD, 0) < 0) { + syslog(LOG_ERR, + "%s/%s: fcntl (F_SETFD, 0): %m", + sep->se_service, sep->se_proto); + _exit(EX_OSERR); + } + if (ctrl != 0) { + dup2(ctrl, 0); + close(ctrl); + } dup2(0, 1); dup2(0, 2); if ((pwd = getpwnam(sep->se_user)) == NULL) { @@ -1259,6 +1268,13 @@ setup(struct servtab *sep) sep->se_service, sep->se_proto); return; } + /* Set all listening sockets to close-on-exec. */ + if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) { + syslog(LOG_ERR, "%s/%s: fcntl (F_SETFD, FD_CLOEXEC): %m", + sep->se_service, sep->se_proto); + close(sep->se_fd); + return; + } #define turnon(fd, opt) \ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && |