Date: Sun, 21 Oct 2012 06:55:56 GMT From: Jukka Ukkonen <jau@iki.fi> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/172921: O_CLOEXEC support for libdb / dbopen Message-ID: <201210210655.q9L6tuBL096387@red.freebsd.org> Resent-Message-ID: <201210210700.q9L701rl088072@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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 <db.h> +/* + * 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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201210210655.q9L6tuBL096387>