On Sun, 03 May 2015 22:07:33 -0700, Philip Guenther wrote:

> 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()

A few comments inline:

> 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;
>       }

I don't see the need to use O_ACCMODE here at all.  Why not just:

        if (!(oflag & O_RDWR) || (oflag & ~(O_RDWR | O_NOCTTY)) != 0)

or even:

        if (oflag != O_RDWR && oflag != (O_RDWR | O_NOCTTY))

>       /* 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)){

The check against O_ACCMODE seems superfluous here since you added
the explicit flag value checks.

>               _kvm_err(kd, kd->program, "bad flags arg");
>               goto failed;
>       }
> 

Reply via email to