The flags passed to open(2) and openat(2) are not a simple bitset.  
Instead, the bits in O_ACCMODE are effectively an enumeration, and the 
other bits are or'ed onto that.

For example, a function that wraps open(2), taking a flag argument that it 
passes through, that wants to verify that it was invoked with either 
O_WRONLY or O_RDWR *cannot* just say
        if ((flags & O_ACCMODE) & ~(O_WRONLY | O_RDWR))
                return (EINVAL);

as that will accept O_RDONLY as well!  The correct test is to mask off 
O_ACCMODE and compare the results to the acceptable values:
        if ((flags & O_ACCMODE) != O_WRONLY && (flags & O_ACCMODE) != O_RDWR)
                return (EINVAL);


So, in anticipation of future changes, let's make interfaces that wrap 
open() be more precise in the handling of flags for open(), testing 
O_ACCMODE bits separately from others.

While here, document that shm_open() accept O_CLOEXEC and O_NOFOLLOW as 
extensions to POSIX, and use O_CLOEXEC on the temporary fd in 
posix_openpt()

ok?

Philip

Index: libc/db/db/db.c
===================================================================
RCS file: /cvs/src/lib/libc/db/db/db.c,v
retrieving revision 1.10
diff -u -p -r1.10 db.c
--- libc/db/db/db.c     5 Aug 2005 13:03:00 -0000       1.10
+++ libc/db/db/db.c     4 May 2015 04:48:11 -0000
@@ -48,9 +48,10 @@ dbopen(const char *fname, int flags, int
 #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_SHLOCK | O_SYNC | O_TRUNC)
 
-       if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0)
+       if (((flags & O_ACCMODE) == O_RDONLY || (flags & O_ACCMODE) == O_RDWR)
+           && (flags & ~(O_ACCMODE | USE_OPEN_FLAGS | DB_FLAGS)) == 0)
                switch (type) {
                case DB_BTREE:
                        return (__bt_open(fname, flags & USE_OPEN_FLAGS,
Index: libc/gen/shm_open.3
===================================================================
RCS file: /cvs/src/lib/libc/gen/shm_open.3,v
retrieving revision 1.4
diff -u -p -r1.4 shm_open.3
--- libc/gen/shm_open.3 8 Jul 2014 00:40:56 -0000       1.4
+++ libc/gen/shm_open.3 4 May 2015 04:48:11 -0000
@@ -45,7 +45,7 @@ and must include at least
 or
 .Dv O_RDWR
 and may also include a combination of
-.Dv O_CREAT , O_EXCL ,
+.Dv O_CREAT , O_EXCL , O_CLOEXEC , O_NOFOLLOW ,
 or
 .Dv O_TRUNC .
 This implementation forces the
@@ -81,6 +81,13 @@ and
 .Fn shm_unlink
 appear in
 .St -p1003.1-2001 .
+Using
+.Dv O_CLOEXEC
+or
+.Dv O_NOFOLLOW
+with
+.Fn shm_open
+is an extension to that standard.
 This implementation deviates from the standard by permitting less sharing.
 .Pp
 .Fn shm_mkstemp
Index: libc/gen/shm_open.c
===================================================================
RCS file: /cvs/src/lib/libc/gen/shm_open.c,v
retrieving revision 1.4
diff -u -p -r1.4 shm_open.c
--- libc/gen/shm_open.c 12 Nov 2013 06:09:48 -0000      1.4
+++ libc/gen/shm_open.c 4 May 2015 04:48:11 -0000
@@ -31,6 +31,9 @@
 /* "/tmp/" + sha256 + ".shm" */
 #define SHM_PATH_SIZE (5 + SHA256_DIGEST_STRING_LENGTH + 4)
 
+/* O_CLOEXEC and O_NOFOLLOW are extensions to POSIX */
+#define OK_FLAGS       (O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC | O_NOFOLLOW)
+
 static void
 makeshmpath(const char *origpath, char *shmpath, size_t len)
 {
@@ -47,8 +50,8 @@ shm_open(const char *path, int flags, mo
        struct stat sb;
        int fd;
 
-       if (flags & ~(O_RDONLY | O_RDWR |
-           O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC | O_NOFOLLOW)) {
+       if (((flags & O_ACCMODE) != O_RDONLY && (flags & O_ACCMODE) != O_RDWR)
+           || (flags & ~(O_ACCMODE | OK_FLAGS))) {
                errno = EINVAL;
                return -1;
        }
Index: libc/stdlib/posix_pty.c
===================================================================
RCS file: /cvs/src/lib/libc/stdlib/posix_pty.c,v
retrieving revision 1.1
diff -u -p -r1.1 posix_pty.c
--- libc/stdlib/posix_pty.c     3 Dec 2012 20:08:33 -0000       1.1
+++ libc/stdlib/posix_pty.c     4 May 2015 04:48:11 -0000
@@ -35,13 +35,14 @@ posix_openpt(int oflag)
        int fd, mfd = -1;
 
        /* User must specify O_RDWR in oflag. */
-       if (!(oflag & O_RDWR)) {
+       if ((oflag & O_ACCMODE) != O_RDWR ||
+           (oflag & ~(O_ACCMODE | O_NOCTTY)) != 0) {
                errno = EINVAL;
                return -1;
        }
 
        /* Get pty master and slave (this API only uses the master). */
-       fd = open(PATH_PTMDEV, O_RDWR);
+       fd = open(PATH_PTMDEV, O_RDWR | O_CLOEXEC);
        if (fd != -1) {
                if (ioctl(fd, PTMGET, &ptm) != -1) {
                        close(ptm.sfd);
Index: libkvm/kvm.c
===================================================================
RCS file: /cvs/src/lib/libkvm/kvm.c,v
retrieving revision 1.54
diff -u -p -r1.54 kvm.c
--- libkvm/kvm.c        16 Jan 2015 16:48:51 -0000      1.54
+++ libkvm/kvm.c        4 May 2015 04:48:11 -0000
@@ -198,7 +198,8 @@ _kvm_open(kvm_t *kd, const char *uf, con
                _kvm_err(kd, kd->program, "exec file name too long");
                goto failed;
        }
-       if (flag & ~O_ACCMODE) {
+       if ((flag & ~O_ACCMODE) || (flag != O_RDONLY && flag != O_WRONLY &&
+           flag != O_RDWR)){
                _kvm_err(kd, kd->program, "bad flags arg");
                goto failed;
        }

Reply via email to