From owner-freebsd-bugs@FreeBSD.ORG Sun Oct 21 07:00:01 2012 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id A23C6E4C for ; Sun, 21 Oct 2012 07:00:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.FreeBSD.org [8.8.178.135]) by mx1.freebsd.org (Postfix) with ESMTP id 7A2078FC0C for ; Sun, 21 Oct 2012 07:00:01 +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 q9L701K4088073 for ; Sun, 21 Oct 2012 07:00:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.5/8.14.5/Submit) id q9L701rl088072; Sun, 21 Oct 2012 07:00:01 GMT (envelope-from gnats) Resent-Date: Sun, 21 Oct 2012 07:00:01 GMT Resent-Message-Id: <201210210700.q9L701rl088072@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 Ukkonen Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id AC197E20 for ; Sun, 21 Oct 2012 06:55:57 +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 91BE68FC0C for ; Sun, 21 Oct 2012 06:55:57 +0000 (UTC) Received: from red.freebsd.org (localhost [127.0.0.1]) by red.freebsd.org (8.14.5/8.14.5) with ESMTP id q9L6tuaW096388 for ; Sun, 21 Oct 2012 06:55:56 GMT (envelope-from nobody@red.freebsd.org) Received: (from nobody@localhost) by red.freebsd.org (8.14.5/8.14.5/Submit) id q9L6tuBL096387; Sun, 21 Oct 2012 06:55:56 GMT (envelope-from nobody) Message-Id: <201210210655.q9L6tuBL096387@red.freebsd.org> Date: Sun, 21 Oct 2012 06:55:56 GMT From: Jukka Ukkonen To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Subject: kern/172921: O_CLOEXEC support for libdb / dbopen X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 21 Oct 2012 07:00:01 -0000 >Number: 172921 >Category: kern >Synopsis: O_CLOEXEC support for libdb / dbopen >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: Sun Oct 21 07:00:01 UTC 2012 >Closed-Date: >Last-Modified: >Originator: Jukka Ukkonen >Release: 9.1-PRERELEASE >Organization: ----- >Environment: FreeBSD sleipnir 9.1-PRERELEASE FreeBSD 9.1-PRERELEASE #0: Sun Oct 21 08:20:37 EEST 2012 root@sleipnir:/usr/obj/usr/src/sys/Sleipnir amd64 >Description: Traditionally libdb has used fcntl() and FD_CLOEXEC to mark the files to be closed when exec() is called. If used in a threaded code this leaves a minimal time window during which another thread could call exec() while the FD_CLOEXEC flag has not yet been set. Using O_CLOEXEC with open() can be used to close the window on system which support O_CLOEXEC. The attached path amends libdb (the default version bundled with libc) to use O_CLOEXEC whenever possible. The patch also changes dbopen to allow setting O_DIRECT on those systems which support the flag. >How-To-Repeat: In fact the little time window is extremely hard to abuse intentionally. >Fix: Apply the attached patch. Patch attached with submission follows: --- lib/libc/db/btree/bt_open.c.orig 2012-10-21 09:03:10.000000000 +0300 +++ lib/libc/db/btree/bt_open.c 2012-10-21 09:05:16.000000000 +0300 @@ -196,6 +196,10 @@ goto einval; } +#if defined(O_CLOEXEC) + flags |= O_CLOEXEC; +#endif + if ((t->bt_fd = _open(fname, flags, mode)) < 0) goto err; @@ -207,7 +211,10 @@ F_SET(t, B_INMEM); } - if (_fcntl(t->bt_fd, F_SETFD, 1) == -1) + /* + * Needed for the tmp() case and for systems without O_CLOEXEC. + */ + if (_fcntl(t->bt_fd, F_SETFD, FD_CLOEXEC) == -1) goto err; if (_fstat(t->bt_fd, &sb)) --- lib/libc/db/hash/hash.c.orig 2012-10-21 09:08:49.000000000 +0300 +++ lib/libc/db/hash/hash.c 2012-10-21 09:10:30.000000000 +0300 @@ -108,6 +108,10 @@ return (NULL); } +#if defined(O_CLOEXEC) + flags |= O_CLOEXEC; +#endif + if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB)))) return (NULL); hashp->fp = -1; @@ -123,7 +127,9 @@ if (file) { if ((hashp->fp = _open(file, flags, mode)) == -1) RETURN_ERROR(errno, error0); - (void)_fcntl(hashp->fp, F_SETFD, 1); +#if !defined(O_CLOEXEC) + (void)_fcntl(hashp->fp, F_SETFD, FD_CLOEXEC); +#endif new_table = _fstat(hashp->fp, &statbuf) == 0 && statbuf.st_size == 0 && (flags & O_ACCMODE) != O_RDONLY; } else --- lib/libc/db/recno/rec_open.c.orig 2012-10-21 09:21:53.000000000 +0300 +++ lib/libc/db/recno/rec_open.c 2012-10-21 09:27:57.000000000 +0300 @@ -63,6 +63,10 @@ struct stat sb; int rfd, sverrno; +#if defined(O_CLOEXEC) + flags |= O_CLOEXEC; +#endif + /* Open the user's file -- if this fails, we're done. */ if (fname != NULL && (rfd = _open(fname, flags, mode)) < 0) return (NULL); --- lib/libc/db/db/db.c.orig 2012-10-21 06:49:59.000000000 +0300 +++ lib/libc/db/db/db.c 2012-10-21 07:21:38.000000000 +0300 @@ -42,6 +42,20 @@ #include +/* + * Just so that the exact same USE_OPEN_FLAGS + * will work also on systems which do not have + * support for some common open() flags. + */ + +#if !defined(O_CLOEXEC) +# define O_CLOEXEC 0 +#endif + +#if !defined(O_DIRECT) +# define O_DIRECT 0 +#endif + static int __dberr(void); DB * @@ -51,7 +65,8 @@ #define DB_FLAGS (DB_LOCK | DB_SHMEM | DB_TXN) #define USE_OPEN_FLAGS \ (O_CREAT | O_EXCL | O_EXLOCK | O_NOFOLLOW | O_NONBLOCK | \ - O_RDONLY | O_RDWR | O_SHLOCK | O_SYNC | O_TRUNC) + O_RDONLY | O_RDWR | O_SHLOCK | O_SYNC | O_TRUNC | O_CLOEXEC | \ + O_DIRECT ) if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0) switch (type) { >Release-Note: >Audit-Trail: >Unformatted: