1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-28 00:21:52 +03:00

linux: open and openat ignore 'mode' with O_TMPFILE in flags

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.
This commit is contained in:
Eric Rannaud
2015-02-24 13:12:26 +05:30
committed by Siddhesh Poyarekar
parent 3e3002ffea
commit 65f6f938cd
20 changed files with 81 additions and 47 deletions

View File

@ -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> 2015-02-24 Siddhesh Poyarekar <siddhesh@redhat.com>
[BZ #14841] [BZ #14841]

6
NEWS
View File

@ -9,9 +9,9 @@ Version 2.22
* The following bugs are resolved with this release: * The following bugs are resolved with this release:
4719, 14841, 13064, 14094, 15319, 15467, 15790, 16560, 17269, 17569, 4719, 14841, 13064, 14094, 15319, 15467, 15790, 16560, 17269, 17523,
17588, 17792, 17836, 17912, 17932, 17944, 17949, 17964, 17965, 17967, 17569, 17588, 17792, 17836, 17912, 17932, 17944, 17949, 17964, 17965,
17969, 17978, 17987, 17991, 17996, 17998, 17999. 17967, 17969, 17978, 17987, 17991, 17996, 17998, 17999.
* Character encoding and ctype tables were updated to Unicode 7.0.0, using * Character encoding and ctype tables were updated to Unicode 7.0.0, using
new generator scripts contributed by Pravin Satpute and Mike FABIAN (Red new generator scripts contributed by Pravin Satpute and Mike FABIAN (Red

View File

@ -20,7 +20,7 @@
# error "Never include <bits/fcntl2.h> directly; use <fcntl.h> instead." # error "Never include <bits/fcntl2.h> directly; use <fcntl.h> instead."
#endif #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. */ appropriate third/fourth parameter. */
#ifndef __USE_FILE_OFFSET64 #ifndef __USE_FILE_OFFSET64
extern int __open_2 (const char *__path, int __oflag) __nonnull ((1)); 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, __errordecl (__open_too_many_args,
"open can be called either with 2 or 3 arguments, not more"); "open can be called either with 2 or 3 arguments, not more");
__errordecl (__open_missing_mode, __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 __fortify_function int
open (const char *__path, int __oflag, ...) open (const char *__path, int __oflag, ...)
@ -45,7 +45,7 @@ open (const char *__path, int __oflag, ...)
if (__builtin_constant_p (__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 (); __open_missing_mode ();
return __open_2 (__path, __oflag); return __open_2 (__path, __oflag);
@ -67,7 +67,7 @@ extern int __REDIRECT (__open64_alias, (const char *__path, int __oflag,
__errordecl (__open64_too_many_args, __errordecl (__open64_too_many_args,
"open64 can be called either with 2 or 3 arguments, not more"); "open64 can be called either with 2 or 3 arguments, not more");
__errordecl (__open64_missing_mode, __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 __fortify_function int
open64 (const char *__path, int __oflag, ...) open64 (const char *__path, int __oflag, ...)
@ -77,7 +77,7 @@ open64 (const char *__path, int __oflag, ...)
if (__builtin_constant_p (__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 (); __open64_missing_mode ();
return __open64_2 (__path, __oflag); return __open64_2 (__path, __oflag);
@ -111,7 +111,7 @@ extern int __REDIRECT (__openat_alias, (int __fd, const char *__path,
__errordecl (__openat_too_many_args, __errordecl (__openat_too_many_args,
"openat can be called either with 3 or 4 arguments, not more"); "openat can be called either with 3 or 4 arguments, not more");
__errordecl (__openat_missing_mode, __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 __fortify_function int
openat (int __fd, const char *__path, int __oflag, ...) 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 (__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 (); __openat_missing_mode ();
return __openat_2 (__fd, __path, __oflag); 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, __errordecl (__openat64_too_many_args,
"openat64 can be called either with 3 or 4 arguments, not more"); "openat64 can be called either with 3 or 4 arguments, not more");
__errordecl (__openat64_missing_mode, __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 __fortify_function int
openat64 (int __fd, const char *__path, int __oflag, ...) 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 (__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 (); __openat64_missing_mode ();
return __openat64_2 (__fd, __path, __oflag); return __openat64_2 (__fd, __path, __oflag);

View File

@ -34,6 +34,15 @@ __BEGIN_DECLS
numbers and flag bits for `open', `fcntl', et al. */ numbers and flag bits for `open', `fcntl', et al. */
#include <bits/fcntl.h> #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>. /* POSIX.1-2001 specifies that these types are defined by <fcntl.h>.
Earlier POSIX standards permitted any type ending in `_t' to be defined Earlier POSIX standards permitted any type ending in `_t' to be defined
by any POSIX header, so we don't conditionalize the definitions here. */ 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, ...); extern int fcntl (int __fd, int __cmd, ...);
/* Open FILE and return a new file descriptor for it, or -1 on error. /* 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, OFLAG determines the type of access used. If O_CREAT or O_TMPFILE is set
the third argument is taken as a `mode_t', the mode of the created file. 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 This function is a cancellation point and therefore not marked with
__THROW. */ __THROW. */

View File

@ -23,7 +23,7 @@
#include <stdio.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. */ a third argument is the file protection. */
int int
__libc_open (file, oflag) __libc_open (file, oflag)
@ -38,7 +38,7 @@ __libc_open (file, oflag)
return -1; return -1;
} }
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
{ {
va_list arg; va_list arg;
va_start(arg, oflag); va_start(arg, oflag);

View File

@ -21,7 +21,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdio.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. */ a third argument is the file protection. */
int int
__libc_open64 (file, oflag) __libc_open64 (file, oflag)
@ -36,7 +36,7 @@ __libc_open64 (file, oflag)
return -1; return -1;
} }
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
{ {
va_list arg; va_list arg;
va_start (arg, oflag); va_start (arg, oflag);

View File

@ -22,8 +22,8 @@
int int
__open64_2 (const char *file, int oflag) __open64_2 (const char *file, int oflag)
{ {
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
__fortify_fail ("invalid open64 call: O_CREAT without mode"); __fortify_fail ("invalid open64 call: O_CREAT or O_TMPFILE without mode");
return __open64 (file, oflag); return __open64 (file, oflag);
} }

View File

@ -22,8 +22,8 @@
int int
__open_2 (const char *file, int oflag) __open_2 (const char *file, int oflag)
{ {
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
__fortify_fail ("invalid open call: O_CREAT without mode"); __fortify_fail ("invalid open call: O_CREAT or O_TMPFILE without mode");
return __open (file, oflag); return __open (file, oflag);
} }

View File

@ -31,7 +31,7 @@ int __have_atfcts;
#endif #endif
/* Open FILE with access OFLAG. Interpret relative paths relative to /* 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. */ third argument is the file protection. */
int int
__openat (int fd, const char *file, int oflag, ...) __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_list arg;
va_start (arg, oflag); va_start (arg, oflag);

View File

@ -24,7 +24,7 @@
#include <libc-internal.h> #include <libc-internal.h>
/* Open FILE with access OFLAG. Interpret relative paths relative to /* 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. */ third argument is the file protection. */
int int
__openat64 (int fd, const char *file, int oflag, ...) __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_list arg;
va_start (arg, oflag); va_start (arg, oflag);

View File

@ -22,8 +22,8 @@
int int
__openat64_2 (int fd, const char *file, int oflag) __openat64_2 (int fd, const char *file, int oflag)
{ {
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
__fortify_fail ("invalid openat64 call: O_CREAT without mode"); __fortify_fail ("invalid openat64 call: O_CREAT or O_TMPFILE without mode");
return __openat64 (fd, file, oflag); return __openat64 (fd, file, oflag);
} }

View File

@ -22,8 +22,8 @@
int int
__openat_2 (int fd, const char *file, int oflag) __openat_2 (int fd, const char *file, int oflag)
{ {
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
__fortify_fail ("invalid openat call: O_CREAT without mode"); __fortify_fail ("invalid openat call: O_CREAT or O_TMPFILE without mode");
return __openat (fd, file, oflag); return __openat (fd, file, oflag);
} }

View File

@ -22,7 +22,7 @@
#include <hurd.h> #include <hurd.h>
#include <hurd/fd.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. */ a third argument is the file protection. */
int int
__libc_open (const char *file, int oflag, ...) __libc_open (const char *file, int oflag, ...)
@ -30,7 +30,7 @@ __libc_open (const char *file, int oflag, ...)
mode_t mode; mode_t mode;
io_t port; io_t port;
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
{ {
va_list arg; va_list arg;
va_start (arg, oflag); va_start (arg, oflag);

View File

@ -26,7 +26,7 @@
#include <hurd/fd.h> #include <hurd/fd.h>
/* Open FILE with access OFLAG. Interpret relative paths relative to /* 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. */ third argument is the file protection. */
int int
__openat (fd, file, oflag) __openat (fd, file, oflag)
@ -37,7 +37,7 @@ __openat (fd, file, oflag)
mode_t mode; mode_t mode;
io_t port; io_t port;
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
{ {
va_list arg; va_list arg;
va_start (arg, oflag); va_start (arg, oflag);

View File

@ -19,14 +19,14 @@
#include <stdarg.h> #include <stdarg.h>
#include <sysdep-cancel.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. */ a third argument is the file protection. */
int int
__libc_open64 (const char *file, int oflag, ...) __libc_open64 (const char *file, int oflag, ...)
{ {
int mode = 0; int mode = 0;
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
{ {
va_list arg; va_list arg;
va_start (arg, oflag); va_start (arg, oflag);

View File

@ -28,7 +28,7 @@ openat64 (dfd, file, oflag)
const char *file; const char *file;
int oflag; int oflag;
{ {
assert ((oflag & O_CREAT) == 0); assert (!__OPEN_NEEDS_MODE (oflag));
#ifdef __NR_openat #ifdef __NR_openat
return INLINE_SYSCALL (openat, 3, dfd, file, oflag | O_LARGEFILE); return INLINE_SYSCALL (openat, 3, dfd, file, oflag | O_LARGEFILE);

View File

@ -22,14 +22,14 @@
#include <stdio.h> #include <stdio.h>
#include <sysdep-cancel.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. */ a third argument is the file protection. */
int int
__libc_open (const char *file, int oflag, ...) __libc_open (const char *file, int oflag, ...)
{ {
int mode = 0; int mode = 0;
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
{ {
va_list arg; va_list arg;
va_start (arg, oflag); va_start (arg, oflag);
@ -59,7 +59,7 @@ __open_nocancel (const char *file, int oflag, ...)
{ {
int mode = 0; int mode = 0;
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
{ {
va_list arg; va_list arg;
va_start (arg, oflag); va_start (arg, oflag);

View File

@ -22,14 +22,14 @@
#include <stdio.h> #include <stdio.h>
#include <sysdep-cancel.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. */ a third argument is the file protection. */
int int
__libc_open64 (const char *file, int oflag, ...) __libc_open64 (const char *file, int oflag, ...)
{ {
int mode = 0; int mode = 0;
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
{ {
va_list arg; va_list arg;
va_start (arg, oflag); va_start (arg, oflag);

View File

@ -21,14 +21,14 @@
#include <stdio.h> #include <stdio.h>
#include <sysdep-cancel.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. */ a third argument is the file protection. */
int int
__libc_open64 (const char *file, int oflag, ...) __libc_open64 (const char *file, int oflag, ...)
{ {
int mode = 0; int mode = 0;
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
{ {
va_list arg; va_list arg;
va_start (arg, oflag); va_start (arg, oflag);

View 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 /* 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 OFLAG includes O_CREAT or
third argument is the file protection. */ O_TMPFILE, a fourth argument is the file protection. */
int int
__OPENAT (int fd, const char *file, int oflag, ...) __OPENAT (int fd, const char *file, int oflag, ...)
{ {
mode_t mode = 0; mode_t mode = 0;
if (oflag & O_CREAT) if (__OPEN_NEEDS_MODE (oflag))
{ {
va_list arg; va_list arg;
va_start (arg, oflag); va_start (arg, oflag);