]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
linux: open and openat ignore 'mode' with O_TMPFILE in flags
authorEric Rannaud <e@nanocritical.com>
Tue, 24 Feb 2015 07:42:26 +0000 (13:12 +0530)
committerSiddhesh Poyarekar <siddhesh@redhat.com>
Tue, 24 Feb 2015 07:49:22 +0000 (13:19 +0530)
Both open and openat load their last argument 'mode' lazily, using
va_arg() only if O_CREAT is found in oflag. This is wrong, mode is also
necessary if O_TMPFILE is in oflag.

By chance on x86_64, the problem wasn't evident when using O_TMPFILE
with open, as the 3rd argument of open, even when not loaded with
va_arg, is left untouched in RDX, where the syscall expects it.

However, openat was not so lucky, and O_TMPFILE couldn't be used: mode
is the 4th argument, in RCX, but the syscall expects its 4th argument in
a different register than the glibc wrapper, in R10.

Introduce a macro __OPEN_NEEDS_MODE (oflag) to test if either O_CREAT or
O_TMPFILE is set in oflag.

Tested on Linux x86_64.

[BZ #17523]
* io/fcntl.h (__OPEN_NEEDS_MODE): New macro.
* io/bits/fcntl2.h (open): Use it.
(openat): Likewise.
* io/open.c (__libc_open): Likewise.
* io/open64.c (__libc_open64): Likewise.
* io/open64_2.c (__open64_2): Likewise.
* io/open_2.c (__open_2): Likewise.
* io/openat.c (__openat): Likewise.
* io/openat64.c (__openat64): Likewise.
* io/openat64_2.c (__openat64_2): Likewise.
* io/openat_2.c (__openat_2): Likewise.
* sysdeps/mach/hurd/open.c (__libc_open): Likewise.
* sysdeps/mach/hurd/openat.c (__openat): Likewise.
* sysdeps/posix/open64.c (__libc_open64): Likewise.
* sysdeps/unix/sysv/linux/dl-openat64.c (openat64): Likewise.
* sysdeps/unix/sysv/linux/generic/open.c (__libc_open): Likewise.
(__open_nocancel): Likewise.
* sysdeps/unix/sysv/linux/generic/open64.c (__libc_open64): Likewise.
* sysdeps/unix/sysv/linux/open64.c (__libc_open64): Likewise.
* sysdeps/unix/sysv/linux/openat.c (__OPENAT): Likewise.

20 files changed:
ChangeLog
NEWS
io/bits/fcntl2.h
io/fcntl.h
io/open.c
io/open64.c
io/open64_2.c
io/open_2.c
io/openat.c
io/openat64.c
io/openat64_2.c
io/openat_2.c
sysdeps/mach/hurd/open.c
sysdeps/mach/hurd/openat.c
sysdeps/posix/open64.c
sysdeps/unix/sysv/linux/dl-openat64.c
sysdeps/unix/sysv/linux/generic/open.c
sysdeps/unix/sysv/linux/generic/open64.c
sysdeps/unix/sysv/linux/open64.c
sysdeps/unix/sysv/linux/openat.c

index 2501fa5cc9576b9572617c5c7398f290d1e346c1..59a1571d013fc7fef3a7b71eea61603f1ffa9938 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2015-02-24  Eric Rannaud  <e@nanocritical.com>
+
+       [BZ #17523]
+       * io/fcntl.h (__OPEN_NEEDS_MODE): New macro.
+       * io/bits/fcntl2.h (open): Use it.
+       (openat): Likewise.
+       * io/open.c (__libc_open): Likewise.
+       * io/open64.c (__libc_open64): Likewise.
+       * io/open64_2.c (__open64_2): Likewise.
+       * io/open_2.c (__open_2): Likewise.
+       * io/openat.c (__openat): Likewise.
+       * io/openat64.c (__openat64): Likewise.
+       * io/openat64_2.c (__openat64_2): Likewise.
+       * io/openat_2.c (__openat_2): Likewise.
+       * sysdeps/mach/hurd/open.c (__libc_open): Likewise.
+       * sysdeps/mach/hurd/openat.c (__openat): Likewise.
+       * sysdeps/posix/open64.c (__libc_open64): Likewise.
+       * sysdeps/unix/sysv/linux/dl-openat64.c (openat64): Likewise.
+       * sysdeps/unix/sysv/linux/generic/open.c (__libc_open): Likewise.
+       (__open_nocancel): Likewise.
+       * sysdeps/unix/sysv/linux/generic/open64.c (__libc_open64): Likewise.
+       * sysdeps/unix/sysv/linux/open64.c (__libc_open64): Likewise.
+       * sysdeps/unix/sysv/linux/openat.c (__OPENAT): Likewise.
+
 2015-02-24  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
        [BZ #14841]
diff --git a/NEWS b/NEWS
index 3925acd93f1ef8a06f0b784e4d72e8412aa01d19..bd95e74cb6f118fbc065df4cab7bd90c8730ca57 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,9 +9,9 @@ Version 2.22
 
 * The following bugs are resolved with this release:
 
-  4719, 14841, 13064, 14094, 15319, 15467, 15790, 16560, 17269, 17569,
-  17588, 17792, 17836, 17912, 17932, 17944, 17949, 17964, 17965, 17967,
-  17969, 17978, 17987, 17991, 17996, 17998, 17999.
+  4719, 14841, 13064, 14094, 15319, 15467, 15790, 16560, 17269, 17523,
+  17569, 17588, 17792, 17836, 17912, 17932, 17944, 17949, 17964, 17965,
+  17967, 17969, 17978, 17987, 17991, 17996, 17998, 17999.
 
 * Character encoding and ctype tables were updated to Unicode 7.0.0, using
   new generator scripts contributed by Pravin Satpute and Mike FABIAN (Red
index 745bb0b9c17327241f526020da4f28708db4eb53..2ac54b200a31ead2b160c2f22904dc9fb056ef15 100644 (file)
@@ -20,7 +20,7 @@
 # error "Never include <bits/fcntl2.h> directly; use <fcntl.h> instead."
 #endif
 
-/* Check that calls to open and openat with O_CREAT set have an
+/* Check that calls to open and openat with O_CREAT or O_TMPFILE set have an
    appropriate third/fourth parameter.  */
 #ifndef __USE_FILE_OFFSET64
 extern int __open_2 (const char *__path, int __oflag) __nonnull ((1));
@@ -35,7 +35,7 @@ extern int __REDIRECT (__open_alias, (const char *__path, int __oflag, ...),
 __errordecl (__open_too_many_args,
             "open can be called either with 2 or 3 arguments, not more");
 __errordecl (__open_missing_mode,
-            "open with O_CREAT in second argument needs 3 arguments");
+            "open with O_CREAT or O_TMPFILE in second argument needs 3 arguments");
 
 __fortify_function int
 open (const char *__path, int __oflag, ...)
@@ -45,7 +45,7 @@ open (const char *__path, int __oflag, ...)
 
   if (__builtin_constant_p (__oflag))
     {
-      if ((__oflag & O_CREAT) != 0 && __va_arg_pack_len () < 1)
+      if (__OPEN_NEEDS_MODE (__oflag) && __va_arg_pack_len () < 1)
        {
          __open_missing_mode ();
          return __open_2 (__path, __oflag);
@@ -67,7 +67,7 @@ extern int __REDIRECT (__open64_alias, (const char *__path, int __oflag,
 __errordecl (__open64_too_many_args,
             "open64 can be called either with 2 or 3 arguments, not more");
 __errordecl (__open64_missing_mode,
-            "open64 with O_CREAT in second argument needs 3 arguments");
+            "open64 with O_CREAT or O_TMPFILE in second argument needs 3 arguments");
 
 __fortify_function int
 open64 (const char *__path, int __oflag, ...)
@@ -77,7 +77,7 @@ open64 (const char *__path, int __oflag, ...)
 
   if (__builtin_constant_p (__oflag))
     {
-      if ((__oflag & O_CREAT) != 0 && __va_arg_pack_len () < 1)
+      if (__OPEN_NEEDS_MODE (__oflag) && __va_arg_pack_len () < 1)
        {
          __open64_missing_mode ();
          return __open64_2 (__path, __oflag);
@@ -111,7 +111,7 @@ extern int __REDIRECT (__openat_alias, (int __fd, const char *__path,
 __errordecl (__openat_too_many_args,
             "openat can be called either with 3 or 4 arguments, not more");
 __errordecl (__openat_missing_mode,
-            "openat with O_CREAT in third argument needs 4 arguments");
+            "openat with O_CREAT or O_TMPFILE in third argument needs 4 arguments");
 
 __fortify_function int
 openat (int __fd, const char *__path, int __oflag, ...)
@@ -121,7 +121,7 @@ openat (int __fd, const char *__path, int __oflag, ...)
 
   if (__builtin_constant_p (__oflag))
     {
-      if ((__oflag & O_CREAT) != 0 && __va_arg_pack_len () < 1)
+      if (__OPEN_NEEDS_MODE (__oflag) && __va_arg_pack_len () < 1)
        {
          __openat_missing_mode ();
          return __openat_2 (__fd, __path, __oflag);
@@ -145,7 +145,7 @@ extern int __REDIRECT (__openat64_alias, (int __fd, const char *__path,
 __errordecl (__openat64_too_many_args,
             "openat64 can be called either with 3 or 4 arguments, not more");
 __errordecl (__openat64_missing_mode,
-            "openat64 with O_CREAT in third argument needs 4 arguments");
+            "openat64 with O_CREAT or O_TMPFILE in third argument needs 4 arguments");
 
 __fortify_function int
 openat64 (int __fd, const char *__path, int __oflag, ...)
@@ -155,7 +155,7 @@ openat64 (int __fd, const char *__path, int __oflag, ...)
 
   if (__builtin_constant_p (__oflag))
     {
-      if ((__oflag & O_CREAT) != 0 && __va_arg_pack_len () < 1)
+      if (__OPEN_NEEDS_MODE (__oflag) && __va_arg_pack_len () < 1)
        {
          __openat64_missing_mode ();
          return __openat64_2 (__fd, __path, __oflag);
index 71f5e52e883ed354abee1ffb2af9a4b95c6d5190..c6812c467b8f41c2e0bdf8d3c57e70ca9cb89c97 100644 (file)
@@ -34,6 +34,15 @@ __BEGIN_DECLS
    numbers and flag bits for `open', `fcntl', et al.  */
 #include <bits/fcntl.h>
 
+/* Detect if open needs mode as a third argument (or for openat as a fourth
+   argument).  */
+#ifdef __O_TMPFILE
+# define __OPEN_NEEDS_MODE(oflag) \
+  (((oflag) & O_CREAT) != 0 || ((oflag) & __O_TMPFILE) == __O_TMPFILE)
+#else
+# define __OPEN_NEEDS_MODE(oflag) (((oflag) & O_CREAT) != 0)
+#endif
+
 /* POSIX.1-2001 specifies that these types are defined by <fcntl.h>.
    Earlier POSIX standards permitted any type ending in `_t' to be defined
    by any POSIX header, so we don't conditionalize the definitions here.  */
@@ -160,8 +169,9 @@ typedef __pid_t pid_t;
 extern int fcntl (int __fd, int __cmd, ...);
 
 /* Open FILE and return a new file descriptor for it, or -1 on error.
-   OFLAG determines the type of access used.  If O_CREAT is on OFLAG,
-   the third argument is taken as a `mode_t', the mode of the created file.
+   OFLAG determines the type of access used.  If O_CREAT or O_TMPFILE is set
+   in OFLAG, the third argument is taken as a `mode_t', the mode of the
+   created file.
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
index cf1245bf7d19d2df5252fdb7bd68deb9a15f5e4c..c0000bacd6e87baa439c233e017e82f1767eba7c 100644 (file)
--- a/io/open.c
+++ b/io/open.c
@@ -23,7 +23,7 @@
 #include <stdio.h>
 
 
-/* Open FILE with access OFLAG.  If OFLAG includes O_CREAT,
+/* Open FILE with access OFLAG.  If O_CREAT or O_TMPFILE is in OFLAG,
    a third argument is the file protection.  */
 int
 __libc_open (file, oflag)
@@ -38,7 +38,7 @@ __libc_open (file, oflag)
       return -1;
     }
 
-  if (oflag & O_CREAT)
+  if (__OPEN_NEEDS_MODE (oflag))
     {
       va_list arg;
       va_start(arg, oflag);
index edd5fd3432874a2d245279a62515a1c5985a97b0..f87ee570995355a31d5dc082aae9a6fd1fba19a0 100644 (file)
@@ -21,7 +21,7 @@
 #include <stddef.h>
 #include <stdio.h>
 
-/* Open FILE with access OFLAG.  If OFLAG includes O_CREAT,
+/* Open FILE with access OFLAG.  If O_CREAT or O_TMPFILE is in OFLAG,
    a third argument is the file protection.  */
 int
 __libc_open64 (file, oflag)
@@ -36,7 +36,7 @@ __libc_open64 (file, oflag)
       return -1;
     }
 
-  if (oflag & O_CREAT)
+  if (__OPEN_NEEDS_MODE (oflag))
     {
       va_list arg;
       va_start (arg, oflag);
index d56dc65f83d39029f64135f9d9536e963e6d398a..0fd562dc0ffbedb7d1328d559571f334d7222a28 100644 (file)
@@ -22,8 +22,8 @@
 int
 __open64_2 (const char *file, int oflag)
 {
-  if (oflag & O_CREAT)
-    __fortify_fail ("invalid open64 call: O_CREAT without mode");
+  if (__OPEN_NEEDS_MODE (oflag))
+    __fortify_fail ("invalid open64 call: O_CREAT or O_TMPFILE without mode");
 
   return __open64 (file, oflag);
 }
index c07ecdd3bdc92c50f6837e1365d6533f8df3af9d..f11ebe00bbe46db12eefcbae6c7e645fd3739304 100644 (file)
@@ -22,8 +22,8 @@
 int
 __open_2 (const char *file, int oflag)
 {
-  if (oflag & O_CREAT)
-    __fortify_fail ("invalid open call: O_CREAT without mode");
+  if (__OPEN_NEEDS_MODE (oflag))
+    __fortify_fail ("invalid open call: O_CREAT or O_TMPFILE without mode");
 
   return __open (file, oflag);
 }
index e54eb9bcad5410feff75866a57d92a55dd60eb22..08d61843fa2da0493c9703185856ae0ba531e1db 100644 (file)
@@ -31,7 +31,7 @@ int __have_atfcts;
 #endif
 
 /* Open FILE with access OFLAG.  Interpret relative paths relative to
-   the directory associated with FD.  If OFLAG includes O_CREAT, a
+   the directory associated with FD.  If O_CREAT or O_TMPFILE is in OFLAG, a
    third argument is the file protection.  */
 int
 __openat (int fd, const char *file, int oflag, ...)
@@ -58,7 +58,7 @@ __openat (int fd, const char *file, int oflag, ...)
        }
     }
 
-  if (oflag & O_CREAT)
+  if (__OPEN_NEEDS_MODE (oflag))
     {
       va_list arg;
       va_start (arg, oflag);
index 7801a92e767cb7431c088f138c30ad19b6de5acf..060fdf90459cccf5c4a5c01d3a01b5b030dafeeb 100644 (file)
@@ -24,7 +24,7 @@
 #include <libc-internal.h>
 
 /* Open FILE with access OFLAG.  Interpret relative paths relative to
-   the directory associated with FD.  If OFLAG includes O_CREAT, a
+   the directory associated with FD.  If O_CREAT or O_TMPFILE is in OFLAG, a
    third argument is the file protection.  */
 int
 __openat64 (int fd, const char *file, int oflag, ...)
@@ -51,7 +51,7 @@ __openat64 (int fd, const char *file, int oflag, ...)
        }
     }
 
-  if (oflag & O_CREAT)
+  if (__OPEN_NEEDS_MODE (oflag))
     {
       va_list arg;
       va_start (arg, oflag);
index 96f04d285bec2276956fba0aa279a0e7f62f8f42..8548c3d5576e3313a652974726fb8d3d7b8f30e1 100644 (file)
@@ -22,8 +22,8 @@
 int
 __openat64_2 (int fd, const char *file, int oflag)
 {
-  if (oflag & O_CREAT)
-    __fortify_fail ("invalid openat64 call: O_CREAT without mode");
+  if (__OPEN_NEEDS_MODE (oflag))
+    __fortify_fail ("invalid openat64 call: O_CREAT or O_TMPFILE without mode");
 
   return __openat64 (fd, file, oflag);
 }
index 2345cc27813d76f4afc0a3766cbc08ed8958d53e..54a98bece8a11e1a5d7de32994f4e4e0f5fd908d 100644 (file)
@@ -22,8 +22,8 @@
 int
 __openat_2 (int fd, const char *file, int oflag)
 {
-  if (oflag & O_CREAT)
-    __fortify_fail ("invalid openat call: O_CREAT without mode");
+  if (__OPEN_NEEDS_MODE (oflag))
+    __fortify_fail ("invalid openat call: O_CREAT or O_TMPFILE without mode");
 
   return __openat (fd, file, oflag);
 }
index 2d1415af6e66218d751492416e495e1230dc8aff..c497a7cb44790ca01e1564d0a93e22ce919fc751 100644 (file)
@@ -22,7 +22,7 @@
 #include <hurd.h>
 #include <hurd/fd.h>
 
-/* Open FILE with access OFLAG.  If OFLAG includes O_CREAT,
+/* Open FILE with access OFLAG.  If O_CREAT or O_TMPFILE is in OFLAG,
    a third argument is the file protection.  */
 int
 __libc_open (const char *file, int oflag, ...)
@@ -30,7 +30,7 @@ __libc_open (const char *file, int oflag, ...)
   mode_t mode;
   io_t port;
 
-  if (oflag & O_CREAT)
+  if (__OPEN_NEEDS_MODE (oflag))
     {
       va_list arg;
       va_start (arg, oflag);
index 0928dff6247d94a45e9aa7af825a28ba6f139dfc..0d3e138890636710daa3474deba9325bee9e1c11 100644 (file)
@@ -26,7 +26,7 @@
 #include <hurd/fd.h>
 
 /* Open FILE with access OFLAG.  Interpret relative paths relative to
-   the directory associated with FD.  If OFLAG includes O_CREAT, a
+   the directory associated with FD.  If O_CREAT or O_TMPFILE is in OFLAG, a
    third argument is the file protection.  */
 int
 __openat (fd, file, oflag)
@@ -37,7 +37,7 @@ __openat (fd, file, oflag)
   mode_t mode;
   io_t port;
 
-  if (oflag & O_CREAT)
+  if (__OPEN_NEEDS_MODE (oflag))
     {
       va_list arg;
       va_start (arg, oflag);
index 8f8dc60e243913f6e8fab5582160f4910c5e715c..74f669f4088d29ff303ee8305bf25556e7a9244c 100644 (file)
 #include <stdarg.h>
 #include <sysdep-cancel.h>
 
-/* Open FILE with access OFLAG.  If OFLAG includes O_CREAT,
+/* Open FILE with access OFLAG.  If O_CREAT or O_TMPFILE is in OFLAG,
    a third argument is the file protection.  */
 int
 __libc_open64 (const char *file, int oflag, ...)
 {
   int mode = 0;
 
-  if (oflag & O_CREAT)
+  if (__OPEN_NEEDS_MODE (oflag))
     {
       va_list arg;
       va_start (arg, oflag);
index 4dd5ed5c3b03b83996aeb0c1c13ace916aa7ba8b..732097dd92cdbcf447dc55f6a030c52b60333619 100644 (file)
@@ -28,7 +28,7 @@ openat64 (dfd, file, oflag)
      const char *file;
      int oflag;
 {
-  assert ((oflag & O_CREAT) == 0);
+  assert (!__OPEN_NEEDS_MODE (oflag));
 
 #ifdef __NR_openat
   return INLINE_SYSCALL (openat, 3, dfd, file, oflag | O_LARGEFILE);
index f15144cc2aa5addca79f4ecadc890916a262a6d0..289f57aadafb76f5b04009fb01c03e037c83bd51 100644 (file)
 #include <stdio.h>
 #include <sysdep-cancel.h>
 
-/* Open FILE with access OFLAG.  If OFLAG includes O_CREAT,
+/* Open FILE with access OFLAG.  If O_CREAT or O_TMPFILE is in OFLAG,
    a third argument is the file protection.  */
 int
 __libc_open (const char *file, int oflag, ...)
 {
   int mode = 0;
 
-  if (oflag & O_CREAT)
+  if (__OPEN_NEEDS_MODE (oflag))
     {
       va_list arg;
       va_start (arg, oflag);
@@ -59,7 +59,7 @@ __open_nocancel (const char *file, int oflag, ...)
 {
   int mode = 0;
 
-  if (oflag & O_CREAT)
+  if (__OPEN_NEEDS_MODE (oflag))
     {
       va_list arg;
       va_start (arg, oflag);
index 4feedbaff525733d2224e93f94ddcedb30224232..374e41cf3a02f848237e3c0f719a2d7382ec5ff9 100644 (file)
 #include <stdio.h>
 #include <sysdep-cancel.h>
 
-/* Open FILE with access OFLAG.  If OFLAG includes O_CREAT,
+/* Open FILE with access OFLAG.  If O_CREAT or O_TMPFILE is in OFLAG,
    a third argument is the file protection.  */
 int
 __libc_open64 (const char *file, int oflag, ...)
 {
   int mode = 0;
 
-  if (oflag & O_CREAT)
+  if (__OPEN_NEEDS_MODE (oflag))
     {
       va_list arg;
       va_start (arg, oflag);
index 006760128364c85a1e6337398da02cefa314d5b5..d3ab813ab6b556323ebe9c5267ccd3339a9fdd3b 100644 (file)
 #include <stdio.h>
 #include <sysdep-cancel.h>
 
-/* Open FILE with access OFLAG.  If OFLAG includes O_CREAT,
+/* Open FILE with access OFLAG.  If O_CREAT or O_TMPFILE is in OFLAG,
    a third argument is the file protection.  */
 int
 __libc_open64 (const char *file, int oflag, ...)
 {
   int mode = 0;
 
-  if (oflag & O_CREAT)
+  if (__OPEN_NEEDS_MODE (oflag))
     {
       va_list arg;
       va_start (arg, oflag);
index 5145823b8e58bba2b7ff5740b3f0809fdf6c80e9..30d8e6e1ac96f70fbd6446325593118e507d047e 100644 (file)
@@ -54,13 +54,13 @@ OPENAT_NOT_CANCEL (int fd, const char *file, int oflag, mode_t mode)
 
 
 /* Open FILE with access OFLAG.  Interpret relative paths relative to
-   the directory associated with FD.  If OFLAG includes O_CREAT, a
-   third argument is the file protection.  */
+   the directory associated with FD.  If OFLAG includes O_CREAT or
+   O_TMPFILE, a fourth argument is the file protection.  */
 int
 __OPENAT (int fd, const char *file, int oflag, ...)
 {
   mode_t mode = 0;
-  if (oflag & O_CREAT)
+  if (__OPEN_NEEDS_MODE (oflag))
     {
       va_list arg;
       va_start (arg, oflag);