From owner-freebsd-bugs@FreeBSD.ORG Sat Aug 4 09:20:06 2012 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1915B106566C for ; Sat, 4 Aug 2012 09:20:06 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id E4A4A8FC0A for ; Sat, 4 Aug 2012 09:20:05 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.5/8.14.5) with ESMTP id q749K52Z077014 for ; Sat, 4 Aug 2012 09:20:05 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.5/8.14.5/Submit) id q749K5Xn077013; Sat, 4 Aug 2012 09:20:05 GMT (envelope-from gnats) Resent-Date: Sat, 4 Aug 2012 09:20:05 GMT Resent-Message-Id: <201208040920.q749K5Xn077013@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, "Jukka A. Ukkonen" Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 154FB106564A for ; Sat, 4 Aug 2012 09:14:52 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22]) by mx1.freebsd.org (Postfix) with ESMTP id E87D48FC08 for ; Sat, 4 Aug 2012 09:14:51 +0000 (UTC) Received: from red.freebsd.org (localhost [127.0.0.1]) by red.freebsd.org (8.14.4/8.14.4) with ESMTP id q749EolQ012332 for ; Sat, 4 Aug 2012 09:14:50 GMT (envelope-from nobody@red.freebsd.org) Received: (from nobody@localhost) by red.freebsd.org (8.14.4/8.14.4/Submit) id q749EoWs012326; Sat, 4 Aug 2012 09:14:50 GMT (envelope-from nobody) Message-Id: <201208040914.q749EoWs012326@red.freebsd.org> Date: Sat, 4 Aug 2012 09:14:50 GMT From: "Jukka A. Ukkonen" To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/170369: More O_CLOEXEC flags to plug files being leaked to child processes X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Aug 2012 09:20:06 -0000 >Number: 170369 >Category: kern >Synopsis: More O_CLOEXEC flags to plug files being leaked to child processes >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Sat Aug 04 09:20:05 UTC 2012 >Closed-Date: >Last-Modified: >Originator: Jukka A. Ukkonen >Release: FreeBSD 9.1-PRERELEASE >Organization: ----- >Environment: FreeBSD sleipnir 9.1-PRERELEASE FreeBSD 9.1-PRERELEASE #1: Tue Jul 31 15:39:12 EEST 2012 root@sleipnir:/usr/obj/usr/src/sys/Sleipnir amd64 >Description: This is a merged patch to plug many potential file descriptor leaks from parent to child processes when one thread calls a function which opens a file and another thread executes a child process before the thread with the new file descriptor gets time to set FD_CLOEXEC. All of the changes included simply add O_CLOEXEC to the options to open(). Some of the changes included in this merged patch rely on another patch which extends fopen() to set O_CLOEXEC when necessary http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/169320 Do not try this one without applying the dependency as well. >How-To-Repeat: See full description above. >Fix: See full description above. Patch attached with submission follows: --- lib/libc/gen/arc4random.c.orig 2012-08-04 10:16:08.000000000 +0300 +++ lib/libc/gen/arc4random.c 2012-08-04 10:16:20.000000000 +0300 @@ -114,7 +114,7 @@ u_int8_t rnd[KEYSIZE]; } rdat; - fd = _open(RANDOMDEV, O_RDONLY, 0); + fd = _open(RANDOMDEV, O_RDONLY | O_CLOEXEC, 0); done = 0; if (fd >= 0) { if (_read(fd, &rdat, KEYSIZE) == KEYSIZE) --- lib/libc/gen/fmtmsg.c.orig 2012-08-04 10:19:48.000000000 +0300 +++ lib/libc/gen/fmtmsg.c 2012-08-04 10:19:57.000000000 +0300 @@ -87,7 +87,7 @@ if (output == NULL) return (MM_NOCON); if (*output != '\0') { - if ((fp = fopen("/dev/console", "a")) == NULL) { + if ((fp = fopen("/dev/console", "ae")) == NULL) { free(output); return (MM_NOCON); } --- lib/libc/gen/fts-compat.c.orig 2012-08-04 10:26:58.000000000 +0300 +++ lib/libc/gen/fts-compat.c 2012-08-04 10:31:15.000000000 +0300 @@ -218,7 +218,8 @@ * and ".." are all fairly nasty problems. Note, if we can't get the * descriptor we run anyway, just more slowly. */ - if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = _open(".", O_RDONLY, 0)) < 0) + if (!ISSET(FTS_NOCHDIR) && + (sp->fts_rfd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) SET(FTS_NOCHDIR); return (sp); @@ -347,7 +348,8 @@ (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { p->fts_info = fts_stat(sp, p, 1); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { - if ((p->fts_symfd = _open(".", O_RDONLY, 0)) < 0) { + if ((p->fts_symfd = _open(".", + O_RDONLY | O_CLOEXEC, 0)) < 0) { p->fts_errno = errno; p->fts_info = FTS_ERR; } else @@ -438,7 +440,7 @@ p->fts_info = fts_stat(sp, p, 1); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { if ((p->fts_symfd = - _open(".", O_RDONLY, 0)) < 0) { + _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) { p->fts_errno = errno; p->fts_info = FTS_ERR; } else @@ -579,7 +581,7 @@ ISSET(FTS_NOCHDIR)) return (sp->fts_child = fts_build(sp, instr)); - if ((fd = _open(".", O_RDONLY, 0)) < 0) + if ((fd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) return (NULL); sp->fts_child = fts_build(sp, instr); if (fchdir(fd)) @@ -1178,7 +1180,7 @@ newfd = fd; if (ISSET(FTS_NOCHDIR)) return (0); - if (fd < 0 && (newfd = _open(path, O_RDONLY, 0)) < 0) + if (fd < 0 && (newfd = _open(path, O_RDONLY | O_CLOEXEC, 0)) < 0) return (-1); if (_fstat(newfd, &sb)) { ret = -1; --- lib/libc/gen/fts.c.orig 2012-08-04 10:33:20.000000000 +0300 +++ lib/libc/gen/fts.c 2012-08-04 10:34:38.000000000 +0300 @@ -213,7 +213,8 @@ * and ".." are all fairly nasty problems. Note, if we can't get the * descriptor we run anyway, just more slowly. */ - if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = _open(".", O_RDONLY, 0)) < 0) + if (!ISSET(FTS_NOCHDIR) && + (sp->fts_rfd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) SET(FTS_NOCHDIR); return (sp); @@ -342,7 +343,8 @@ (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { p->fts_info = fts_stat(sp, p, 1); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { - if ((p->fts_symfd = _open(".", O_RDONLY, 0)) < 0) { + if ((p->fts_symfd = _open(".", + O_RDONLY | O_CLOEXEC, 0)) < 0) { p->fts_errno = errno; p->fts_info = FTS_ERR; } else @@ -433,7 +435,7 @@ p->fts_info = fts_stat(sp, p, 1); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { if ((p->fts_symfd = - _open(".", O_RDONLY, 0)) < 0) { + _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) { p->fts_errno = errno; p->fts_info = FTS_ERR; } else @@ -574,7 +576,7 @@ ISSET(FTS_NOCHDIR)) return (sp->fts_child = fts_build(sp, instr)); - if ((fd = _open(".", O_RDONLY, 0)) < 0) + if ((fd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) return (NULL); sp->fts_child = fts_build(sp, instr); if (fchdir(fd)) { @@ -1145,7 +1147,7 @@ newfd = fd; if (ISSET(FTS_NOCHDIR)) return (0); - if (fd < 0 && (newfd = _open(path, O_RDONLY, 0)) < 0) + if (fd < 0 && (newfd = _open(path, O_RDONLY | O_CLOEXEC, 0)) < 0) return (-1); if (_fstat(newfd, &sb)) { ret = -1; --- lib/libc/gen/getcap.c.orig 2012-08-04 10:39:15.000000000 +0300 +++ lib/libc/gen/getcap.c 2012-08-04 10:41:20.000000000 +0300 @@ -241,7 +241,9 @@ myfd = 0; } else { (void)snprintf(pbuf, sizeof(pbuf), "%s.db", *db_p); - if ((capdbp = dbopen(pbuf, O_RDONLY, 0, DB_HASH, 0)) + if ((capdbp = dbopen(pbuf, + O_RDONLY | O_CLOEXEC, + 0, DB_HASH, 0)) != NULL) { free(record); retval = cdbget(capdbp, &record, name); @@ -264,7 +266,7 @@ *cap = cbuf; return (retval); } else { - fd = _open(*db_p, O_RDONLY, 0); + fd = _open(*db_p, O_RDONLY | O_CLOEXEC, 0); if (fd < 0) continue; myfd = 1; --- lib/libc/gen/getcwd.c.orig 2012-08-04 10:45:41.000000000 +0300 +++ lib/libc/gen/getcwd.c 2012-08-04 10:47:37.000000000 +0300 @@ -140,7 +140,7 @@ /* Open and stat parent directory. */ fd = _openat(dir != NULL ? dirfd(dir) : AT_FDCWD, - "..", O_RDONLY); + "..", O_RDONLY | O_CLOEXEC); if (fd == -1) goto err; if (dir) --- lib/libc/gen/getgrent.c.orig 2012-08-04 10:48:47.000000000 +0300 +++ lib/libc/gen/getgrent.c 2012-08-04 10:50:03.000000000 +0300 @@ -810,7 +810,7 @@ if (st->fp != NULL) rewind(st->fp); else if (stayopen) - st->fp = fopen(_PATH_GROUP, "r"); + st->fp = fopen(_PATH_GROUP, "re"); break; case ENDGRENT: if (st->fp != NULL) { @@ -861,7 +861,7 @@ if (*errnop != 0) return (NS_UNAVAIL); if (st->fp == NULL && - ((st->fp = fopen(_PATH_GROUP, "r")) == NULL)) { + ((st->fp = fopen(_PATH_GROUP, "re")) == NULL)) { *errnop = errno; return (NS_UNAVAIL); } @@ -1251,7 +1251,7 @@ if (st->fp != NULL) rewind(st->fp); else if (stayopen) - st->fp = fopen(_PATH_GROUP, "r"); + st->fp = fopen(_PATH_GROUP, "re"); set_setent(dtab, mdata); (void)_nsdispatch(NULL, dtab, NSDB_GROUP_COMPAT, "setgrent", compatsrc, 0); @@ -1335,7 +1335,7 @@ if (*errnop != 0) return (NS_UNAVAIL); if (st->fp == NULL && - ((st->fp = fopen(_PATH_GROUP, "r")) == NULL)) { + ((st->fp = fopen(_PATH_GROUP, "re")) == NULL)) { *errnop = errno; rv = NS_UNAVAIL; goto fin; --- lib/libc/gen/getnetgrent.c.orig 2012-08-04 10:51:39.000000000 +0300 +++ lib/libc/gen/getnetgrent.c 2012-08-04 10:51:53.000000000 +0300 @@ -173,7 +173,7 @@ if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) && errno == ENOENT) || _yp_statp.st_size == 0) _use_only_yp = _netgr_yp_enabled = 1; - if ((netf = fopen(_PATH_NETGROUP,"r")) != NULL ||_use_only_yp){ + if ((netf = fopen(_PATH_NETGROUP,"re")) != NULL ||_use_only_yp){ /* * Icky: grab the first character of the netgroup file * and turn on NIS if it's a '+'. rewind the stream @@ -197,7 +197,7 @@ return; } #else - if ((netf = fopen(_PATH_NETGROUP, "r"))) { + if ((netf = fopen(_PATH_NETGROUP, "re"))) { #endif if (parse_netgrp(group)) endnetgrent(); --- lib/libc/gen/nlist.c.orig 2012-08-04 10:57:58.000000000 +0300 +++ lib/libc/gen/nlist.c 2012-08-04 10:58:11.000000000 +0300 @@ -66,7 +66,7 @@ { int fd, n; - fd = _open(name, O_RDONLY, 0); + fd = _open(name, O_RDONLY | O_CLOEXEC, 0); if (fd < 0) return (-1); n = __fdnlist(fd, list); --- lib/libc/gen/pututxline.c.orig 2012-08-04 11:04:47.000000000 +0300 +++ lib/libc/gen/pututxline.c 2012-08-04 11:06:54.000000000 +0300 @@ -47,7 +47,7 @@ struct stat sb; int fd; - fd = _open(file, O_CREAT|O_RDWR|O_EXLOCK, 0644); + fd = _open(file, O_CREAT|O_RDWR|O_EXLOCK|O_CLOEXEC, 0644); if (fd < 0) return (NULL); @@ -219,7 +219,7 @@ struct stat sb; int fd; - fd = _open(_PATH_UTX_LASTLOGIN, O_RDWR, 0644); + fd = _open(_PATH_UTX_LASTLOGIN, O_RDWR | O_CLOEXEC, 0644); if (fd < 0) return; @@ -253,7 +253,7 @@ vec[1].iov_len = l; l = htobe16(l); - fd = _open(_PATH_UTX_LOG, O_CREAT|O_WRONLY|O_APPEND, 0644); + fd = _open(_PATH_UTX_LOG, O_CREAT|O_WRONLY|O_APPEND|O_CLOEXEC, 0644); if (fd < 0) return (-1); if (_writev(fd, vec, 2) == -1) --- lib/libc/gen/readpassphrase.c.orig 2012-08-04 11:09:43.000000000 +0300 +++ lib/libc/gen/readpassphrase.c 2012-08-04 11:11:13.000000000 +0300 @@ -68,7 +68,7 @@ * stdin and write to stderr unless a tty is required. */ if ((flags & RPP_STDIN) || - (input = output = _open(_PATH_TTY, O_RDWR)) == -1) { + (input = output = _open(_PATH_TTY, O_RDWR | O_CLOEXEC)) == -1) { if (flags & RPP_REQUIRE_TTY) { errno = ENOTTY; return(NULL); --- lib/libc/gen/sem_new.c.orig 2012-08-04 11:14:23.000000000 +0300 +++ lib/libc/gen/sem_new.c 2012-08-04 11:14:31.000000000 +0300 @@ -198,7 +198,7 @@ goto error; } - fd = _open(path, flags|O_RDWR, mode); + fd = _open(path, flags|O_RDWR|O_CLOEXEC, mode); if (fd == -1) goto error; if (flock(fd, LOCK_EX) == -1) --- lib/libc/gen/syslog.c.orig 2012-08-04 11:18:24.000000000 +0300 +++ lib/libc/gen/syslog.c 2012-08-04 11:18:44.000000000 +0300 @@ -300,7 +300,8 @@ * Make sure the error reported is the one from the syslogd failure. */ if (LogStat & LOG_CONS && - (fd = _open(_PATH_CONSOLE, O_WRONLY|O_NONBLOCK, 0)) >= 0) { + (fd = _open(_PATH_CONSOLE, + O_WRONLY|O_NONBLOCK|O_CLOEXEC, 0)) >= 0) { struct iovec iov[2]; struct iovec *v = iov; >Release-Note: >Audit-Trail: >Unformatted: