From patchwork Fri Oct 31 00:21:10 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Rannaud X-Patchwork-Id: 3508 Received: (qmail 3225 invoked by alias); 31 Oct 2014 00:21:37 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 3207 invoked by uid 89); 31 Oct 2014 00:21:36 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 X-HELO: mail-pa0-f50.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=1S0E/99xc1dTaY4ZD2HBVCx2TTOyQpcPA3pR+ZV06EI=; b=GAn6trSHGIDqzOhGcVNUmGtRGBTmThJCYGikMBU6SHUJrtQHzsUht8clhX3o0Mb2Q6 rcFtgS/vUBLR9K8DJKW7/h+W/uLgM7gk2pKoXE+J9ddgGNz+20fu3xrr7YK3ZXqb3fUG MuqqS+i+Jjy5fncok5JsLG+wDSAFSKz2iLCzEJ5HpPoBM2nXbS2GeYadi/GbT7tklWhB gDghVUJDb0V0SK5zjYn62bQbGnKHdZ49cQ94PDcF1615/dtYoGlRUuqh2R6GJc20X3dt ebrYEvlTmfUrgGU/7Xk8HLiL4Tc5P41R9j/mjafPS2ChnrtzRi0USi/Qbx1rzwRSWCJN UEAA== X-Gm-Message-State: ALoCoQnS6s1j+8/Oww4dcIxUmAuZswseVD6RyobM4KLyRmW8Co80hZh540pl1eeOgqs4DMPekHSA X-Received: by 10.68.101.34 with SMTP id fd2mr79698pbb.164.1414714892605; Thu, 30 Oct 2014 17:21:32 -0700 (PDT) From: "Eric Rannaud" To: Roland McGrath Cc: libc-alpha@sourceware.org, joseph@codesourcery.com, Eric Rannaud Subject: [PATCH v2] linux: open and openat ignore 'mode' with O_TMPFILE in flags Date: Thu, 30 Oct 2014 17:21:10 -0700 Message-Id: <9e272d5ae70d7db36329c99785aefa9d32f0964d.1414714637.git.e@nanocritical.com> In-Reply-To: References: 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: Define __OPEN_NEEDS_MODE. * io/bits/fcntl2.h: Use __OPEN_NEEDS_MODE. * io/open.c: Likewise. * io/open64.c: Likewise. * io/open64_2.c: Likewise. * io/open_2.c: Likewise. * io/openat.c: Likewise. * io/openat64.c: Likewise. * io/openat64_2.c: Likewise. * io/openat_2.c: Likewise. * sysdeps/mach/hurd/open.c: Likewise. * sysdeps/mach/hurd/openat.c: Likewise. * sysdeps/posix/open64.c: Likewise. * sysdeps/unix/sysv/linux/dl-openat64.c: Likewise. * sysdeps/unix/sysv/linux/generic/open.c: Likewise. * sysdeps/unix/sysv/linux/generic/open64.c: Likewise. * sysdeps/unix/sysv/linux/open64.c: Likewise. * sysdeps/unix/sysv/linux/openat.c: Likewise. --- ChangeLog | 22 ++++++++++++++++++++++ io/bits/fcntl2.h | 18 +++++++++--------- io/fcntl.h | 14 ++++++++++++-- io/open.c | 4 ++-- io/open64.c | 4 ++-- io/open64_2.c | 4 ++-- io/open_2.c | 4 ++-- io/openat.c | 4 ++-- io/openat64.c | 4 ++-- io/openat64_2.c | 4 ++-- io/openat_2.c | 4 ++-- sysdeps/mach/hurd/open.c | 4 ++-- sysdeps/mach/hurd/openat.c | 4 ++-- sysdeps/posix/open64.c | 4 ++-- sysdeps/unix/sysv/linux/dl-openat64.c | 2 +- sysdeps/unix/sysv/linux/generic/open.c | 6 +++--- sysdeps/unix/sysv/linux/generic/open64.c | 4 ++-- sysdeps/unix/sysv/linux/open64.c | 4 ++-- sysdeps/unix/sysv/linux/openat.c | 6 +++--- 19 files changed, 76 insertions(+), 44 deletions(-) diff --git a/ChangeLog b/ChangeLog index a28bb3b3452f..b1787fbdceab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2014-10-30 Eric Rannaud + + [BZ #17523] + * io/fcntl.h: Define __OPEN_NEEDS_MODE. + * io/bits/fcntl2.h: Use __OPEN_NEEDS_MODE. + * io/open.c: Likewise. + * io/open64.c: Likewise. + * io/open64_2.c: Likewise. + * io/open_2.c: Likewise. + * io/openat.c: Likewise. + * io/openat64.c: Likewise. + * io/openat64_2.c: Likewise. + * io/openat_2.c: Likewise. + * sysdeps/mach/hurd/open.c: Likewise. + * sysdeps/mach/hurd/openat.c: Likewise. + * sysdeps/posix/open64.c: Likewise. + * sysdeps/unix/sysv/linux/dl-openat64.c: Likewise. + * sysdeps/unix/sysv/linux/generic/open.c: Likewise. + * sysdeps/unix/sysv/linux/generic/open64.c: Likewise. + * sysdeps/unix/sysv/linux/open64.c: Likewise. + * sysdeps/unix/sysv/linux/openat.c: Likewise. + 2014-10-29 Carlos O'Donell * manual/llio.texi: Add comments discussing why write() may be diff --git a/io/bits/fcntl2.h b/io/bits/fcntl2.h index 4f13b1070673..bb8d233b01da 100644 --- a/io/bits/fcntl2.h +++ b/io/bits/fcntl2.h @@ -20,7 +20,7 @@ # error "Never include directly; use 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); diff --git a/io/fcntl.h b/io/fcntl.h index cf512dd27f8c..43e2a63343f1 100644 --- a/io/fcntl.h +++ b/io/fcntl.h @@ -34,6 +34,15 @@ __BEGIN_DECLS numbers and flag bits for `open', `fcntl', et al. */ #include +/* 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 . 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 on + 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. */ diff --git a/io/open.c b/io/open.c index 24aa38033984..d1df5c38d3fb 100644 --- a/io/open.c +++ b/io/open.c @@ -23,7 +23,7 @@ #include -/* 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); diff --git a/io/open64.c b/io/open64.c index 3f3d2e8bbd4b..def4e0b1b27d 100644 --- a/io/open64.c +++ b/io/open64.c @@ -21,7 +21,7 @@ #include #include -/* 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); diff --git a/io/open64_2.c b/io/open64_2.c index 7cafbba4fcc4..dced8abbe7af 100644 --- a/io/open64_2.c +++ b/io/open64_2.c @@ -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); } diff --git a/io/open_2.c b/io/open_2.c index 65d2c1c845bc..d5b3afe53013 100644 --- a/io/open_2.c +++ b/io/open_2.c @@ -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); } diff --git a/io/openat.c b/io/openat.c index 2d822702af43..f3ac8a7532fd 100644 --- a/io/openat.c +++ b/io/openat.c @@ -30,7 +30,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 (fd, file, oflag) @@ -60,7 +60,7 @@ __openat (fd, file, oflag) } } - if (oflag & O_CREAT) + if (__OPEN_NEEDS_MODE (oflag)) { va_list arg; va_start (arg, oflag); diff --git a/io/openat64.c b/io/openat64.c index c0c4e19589bc..d104bc123bb3 100644 --- a/io/openat64.c +++ b/io/openat64.c @@ -23,7 +23,7 @@ #include /* 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 (fd, file, oflag) @@ -53,7 +53,7 @@ __openat64 (fd, file, oflag) } } - if (oflag & O_CREAT) + if (__OPEN_NEEDS_MODE (oflag)) { va_list arg; va_start (arg, oflag); diff --git a/io/openat64_2.c b/io/openat64_2.c index 6cfea6a9aace..9c22a28cadc6 100644 --- a/io/openat64_2.c +++ b/io/openat64_2.c @@ -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); } diff --git a/io/openat_2.c b/io/openat_2.c index 9e38c142671c..d15d1e922d76 100644 --- a/io/openat_2.c +++ b/io/openat_2.c @@ -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); } diff --git a/sysdeps/mach/hurd/open.c b/sysdeps/mach/hurd/open.c index 7d9b2de70c38..f003d032e46e 100644 --- a/sysdeps/mach/hurd/open.c +++ b/sysdeps/mach/hurd/open.c @@ -22,7 +22,7 @@ #include #include -/* 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); diff --git a/sysdeps/mach/hurd/openat.c b/sysdeps/mach/hurd/openat.c index 318cb229ef64..83ffe13e5adb 100644 --- a/sysdeps/mach/hurd/openat.c +++ b/sysdeps/mach/hurd/openat.c @@ -26,7 +26,7 @@ #include /* 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); diff --git a/sysdeps/posix/open64.c b/sysdeps/posix/open64.c index 64d192af9793..4b7ec362be80 100644 --- a/sysdeps/posix/open64.c +++ b/sysdeps/posix/open64.c @@ -19,14 +19,14 @@ #include #include -/* 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); diff --git a/sysdeps/unix/sysv/linux/dl-openat64.c b/sysdeps/unix/sysv/linux/dl-openat64.c index 9d00b459a60d..5ac16a221315 100644 --- a/sysdeps/unix/sysv/linux/dl-openat64.c +++ b/sysdeps/unix/sysv/linux/dl-openat64.c @@ -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); diff --git a/sysdeps/unix/sysv/linux/generic/open.c b/sysdeps/unix/sysv/linux/generic/open.c index 4f73fa019cd8..b4c68344c2eb 100644 --- a/sysdeps/unix/sysv/linux/generic/open.c +++ b/sysdeps/unix/sysv/linux/generic/open.c @@ -22,14 +22,14 @@ #include #include -/* 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); diff --git a/sysdeps/unix/sysv/linux/generic/open64.c b/sysdeps/unix/sysv/linux/generic/open64.c index 93d79e381fab..faea4df9511b 100644 --- a/sysdeps/unix/sysv/linux/generic/open64.c +++ b/sysdeps/unix/sysv/linux/generic/open64.c @@ -22,14 +22,14 @@ #include #include -/* 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); diff --git a/sysdeps/unix/sysv/linux/open64.c b/sysdeps/unix/sysv/linux/open64.c index 0d63806d04ae..6d91b21c3c4f 100644 --- a/sysdeps/unix/sysv/linux/open64.c +++ b/sysdeps/unix/sysv/linux/open64.c @@ -21,14 +21,14 @@ #include #include -/* 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); diff --git a/sysdeps/unix/sysv/linux/openat.c b/sysdeps/unix/sysv/linux/openat.c index 36555b958fdd..99462dcef0d8 100644 --- a/sysdeps/unix/sysv/linux/openat.c +++ b/sysdeps/unix/sysv/linux/openat.c @@ -58,8 +58,8 @@ OPENAT_NOT_CANCEL (fd, file, oflag, 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 (fd, file, oflag) int fd; @@ -67,7 +67,7 @@ __OPENAT (fd, file, oflag) int oflag; { mode_t mode = 0; - if (oflag & O_CREAT) + if (__OPEN_NEEDS_MODE (oflag)) { va_list arg; va_start (arg, oflag);