Fix Linux fcntl OFD locks for non-LFS architectures (BZ#20251)

This patch fixes the OFD ("file private") locks for architectures that
support non-LFS flock definition (__USE_FILE_OFFSET64 not defined). The
issue in this case is both F_OFD_{GETLK,SETLK,SETLKW} and
F_{SET,GET}L{W}K64 expects a flock64 argument and when using old
F_OFD_* flags with a non LFS flock argument the kernel might interpret
the underlying data wrongly.  Kernel idea originally was to avoid using
such flags in non-LFS syscall, but since GLIBC uses fcntl with LFS
semantic as default it is possible to provide the functionality and
avoid the bogus struct kernel passing by adjusting the struct manually
for the required flags.

The idea follows other LFS interfaces that provide two symbols:

  1. A new LFS fcntl64 is added on default ABI with the usual macros to
     select it for FILE_OFFSET_BITS=64.

  2. The Linux non-LFS fcntl use a stack allocated struct flock64 for
     F_OFD_{GETLK,SETLK,SETLKW} copy the results on the user provided
     struct.

  3. Keep a compat symbol with old broken semantic for architectures
     that do not define __OFF_T_MATCHES_OFF64_T.

So for architectures which defines __USE_FILE_OFFSET64, fcntl64 will
aliased to fcntl and no adjustment would be required.  So to actually
use F_OFD_* with LFS support the source must be built with LFS support
(_FILE_OFFSET_BITS=64).

Also F_OFD_SETLKW command is handled a cancellation point, as for
F_SETLKW{64}.

Checked on x86_64-linux-gnu and i686-linux-gnu.

	[BZ #20251]
	* NEWS: Mention fcntl64 addition.
	* csu/check_fds.c: Replace __fcntl_nocancel by __fcntl64_nocancel.
	* login/utmp_file.c: Likewise.
	* sysdeps/posix/fdopendir.c: Likewise.
	* sysdeps/posix/opendir.c: Likewise.
	* sysdeps/unix/pt-fcntl.c: Likewise.
	* include/fcntl.h (__libc_fcntl64, __fcntl64,
	__fcntl64_nocancel_adjusted): New prototype.
	(__fcntl_nocancel_adjusted): Remove prototype.
	* io/Makefile (routines): Add fcntl64.
	(CFLAGS-fcntl64.c): New rule.
	* io/Versions [GLIBC_2.28] (fcntl64): New symbol.
	[GLIBC_PRIVATE] (__libc_fcntl): Rename to __libc_fcntl64.
	* io/fcntl.h (fcntl64): Add prototype and redirect if
	__USE_FILE_OFFSET64 is defined.
	* io/fcntl64.c: New file.
	* manual/llio.text: Add a note for which commands fcntl acts a
	cancellation point.
	* nptl/Makefile (CFLAGS-fcntl64.c): New rule.
	* sysdeps/mach/hurd/fcntl.c: Alias fcntl to fcntl64 symbols.
	* sysdeps/mach/hurd/i386/libc.abilist [GLIBC_2.28] (fcntl, fcntl64):
	New symbols.
	* sysdeps/unix/sysv/linux/fcntl.c (__libc_fcntl): Fix F_GETLK64,
	F_OFD_GETLK, F_SETLK64, F_SETLKW64, F_OFD_SETLK, and F_OFD_SETLKW for
	non-LFS case.
	* sysdeps/unix/sysv/linux/fcntl64.c: New file.
	* sysdeps/unix/sysv/linux/fcntl_nocancel.c (__fcntl_nocancel): Rename
	to __fcntl64_nocancel.
	(__fcntl_nocancel_adjusted): Rename to __fcntl64_nocancel_adjusted.
	* sysdeps/unix/sysv/linux/not-cancel.h (__fcntl_nocancel): Rename
	to __fcntl64_nocancel.
	* sysdeps/unix/sysv/linux/tst-ofdlocks.c: New file.
	* sysdeps/unix/sysv/linux/tst-ofdlocks-compat.c: Likewise.
	* sysdeps/unix/sysv/linux/Makefile (tests): Add tst-ofdlocks.
	(tests-internal): Add tst-ofdlocks-compat.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist [GLIBC_2.28]
	(fcntl64): New symbol.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
	* sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist [GLIBC_2.28] (fcntl,
	fcntl64): Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilis: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
This commit is contained in:
Adhemerval Zanella 2018-04-04 11:24:15 -03:00
parent 124e025864
commit 06ab719d30
51 changed files with 519 additions and 35 deletions

View File

@ -1,3 +1,71 @@
2018-06-26 Adhemerval Zanella <adhemerval.zanella@linaro.org>
[BZ #20251]
* NEWS: Mention fcntl64 addition.
* csu/check_fds.c: Replace __fcntl_nocancel by __fcntl64_nocancel.
* login/utmp_file.c: Likewise.
* sysdeps/posix/fdopendir.c: Likewise.
* sysdeps/posix/opendir.c: Likewise.
* sysdeps/unix/pt-fcntl.c: Likewise.
* include/fcntl.h (__libc_fcntl64, __fcntl64,
__fcntl64_nocancel_adjusted): New prototype.
(__fcntl_nocancel_adjusted): Remove prototype.
* io/Makefile (routines): Add fcntl64.
(CFLAGS-fcntl64.c): New rule.
* io/Versions [GLIBC_2.28] (fcntl64): New symbol.
[GLIBC_PRIVATE] (__libc_fcntl): Rename to __libc_fcntl64.
* io/fcntl.h (fcntl64): Add prototype and redirect if
__USE_FILE_OFFSET64 is defined.
* io/fcntl64.c: New file.
* manual/llio.text: Add a note for which commands fcntl acts a
cancellation point.
* nptl/Makefile (CFLAGS-fcntl64.c): New rule.
* sysdeps/mach/hurd/fcntl.c: Alias fcntl to fcntl64 symbols.
* sysdeps/mach/hurd/i386/libc.abilist [GLIBC_2.28] (fcntl, fcntl64):
New symbols.
* sysdeps/unix/sysv/linux/fcntl.c (__libc_fcntl): Fix F_GETLK64,
F_OFD_GETLK, F_SETLK64, F_SETLKW64, F_OFD_SETLK, and F_OFD_SETLKW for
non-LFS case.
* sysdeps/unix/sysv/linux/fcntl64.c: New file.
* sysdeps/unix/sysv/linux/fcntl_nocancel.c (__fcntl_nocancel): Rename
to __fcntl64_nocancel.
(__fcntl_nocancel_adjusted): Rename to __fcntl64_nocancel_adjusted.
* sysdeps/unix/sysv/linux/not-cancel.h (__fcntl_nocancel): Rename
to __fcntl64_nocancel.
* sysdeps/generic/not-cancel.h: Likewise.
* sysdeps/unix/sysv/linux/tst-ofdlocks.c: New file.
* sysdeps/unix/sysv/linux/Makefile (tests): Add tst-ofdlocks.
* sysdeps/unix/sysv/linux/aarch64/libc.abilist [GLIBC_2.28]
(fcntl64): New symbol.
* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
* sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/arm/libc.abilist [GLIBC_2.28] (fcntl,
fcntl64): Likewise.
* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/i386/libc.abilis: Likewise.
* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
Likewise.
* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
Likewise.
* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
2018-06-26 Florian Weimer <fweimer@redhat.com>
Run thread shutdown functions in an explicit order.

6
NEWS
View File

@ -110,6 +110,12 @@ Deprecated and removed features, and other changes affecting compatibility:
restriction (rejecting '_' in host names, among other things) has been
removed, for increased compatibility with non-IDN name resolution.
* The fcntl function now have a Long File Support variant named fcntl64. It
is added to fix some Linux Open File Description (OFD) locks usage on non
LFS mode. As for others *64 functions, fcntl64 semantics are analogous with
fcntl and LFS support is handled transparently. Also for Linux, the OFD
locks act as a cancellation entrypoint.
Changes to build and runtime requirements:
[Add changes to build and runtime requirements here]

View File

@ -39,7 +39,7 @@
static void
check_one_fd (int fd, int mode)
{
if (__builtin_expect (__fcntl_nocancel (fd, F_GETFD), 0) == -1
if (__builtin_expect (__fcntl64_nocancel (fd, F_GETFD), 0) == -1
&& errno == EBADF)
{
const char *name;

View File

@ -10,11 +10,16 @@ extern int __libc_open (const char *file, int oflag, ...);
libc_hidden_proto (__libc_open)
extern int __libc_fcntl (int fd, int cmd, ...);
libc_hidden_proto (__libc_fcntl)
extern int __fcntl_nocancel_adjusted (int fd, int cmd, void *arg) attribute_hidden;
extern int __fcntl64_nocancel_adjusted (int fd, int cmd, void *arg)
attribute_hidden;
extern int __libc_fcntl64 (int fd, int cmd, ...);
libc_hidden_proto (__libc_fcntl64)
extern int __open (const char *__file, int __oflag, ...);
libc_hidden_proto (__open)
extern int __fcntl (int __fd, int __cmd, ...);
libc_hidden_proto (__fcntl)
extern int __fcntl64 (int __fd, int __cmd, ...) attribute_hidden;
libc_hidden_proto (__fcntl64)
extern int __openat (int __fd, const char *__file, int __oflag, ...)
__nonnull ((2));
libc_hidden_proto (__openat)

View File

@ -40,7 +40,7 @@ routines := \
mkdir mkdirat \
open open_2 open64 open64_2 openat openat_2 openat64 openat64_2 \
read write lseek lseek64 access euidaccess faccessat \
fcntl flock lockf lockf64 \
fcntl fcntl64 flock lockf lockf64 \
close dup dup2 dup3 pipe pipe2 \
creat creat64 \
chdir fchdir \
@ -89,6 +89,7 @@ CFLAGS-open64.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-creat.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-creat64.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-fcntl.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-fcntl64.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-poll.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-ppoll.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-lockf.c += -fexceptions

View File

@ -128,8 +128,11 @@ libc {
GLIBC_2.27 {
copy_file_range;
}
GLIBC_2.28 {
fcntl64;
}
GLIBC_PRIVATE {
__libc_fcntl;
__libc_fcntl64;
__fcntl_nocancel;
__open64_nocancel;
__write_nocancel;

View File

@ -167,7 +167,18 @@ typedef __pid_t pid_t;
This function is a cancellation point and therefore not marked with
__THROW. */
#ifndef __USE_FILE_OFFSET64
extern int fcntl (int __fd, int __cmd, ...);
#else
# ifdef __REDIRECT
extern int __REDIRECT (fcntl, (int __fd, int __cmd, ...), fcntl64);
# else
# define fcntl fcntl64
# endif
#endif
#ifdef __USE_LARGEFILE64
extern int fcntl64 (int __fd, int __cmd, ...);
#endif
/* Open FILE and return a new file descriptor for it, or -1 on error.
OFLAG determines the type of access used. If O_CREAT or O_TMPFILE is set

38
io/fcntl64.c Normal file
View File

@ -0,0 +1,38 @@
/* Manipulate file descriptor. Stub LFS version.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <fcntl.h>
/* Perform file control operations on FD. */
int
__fcntl64 (int fd, int cmd, ...)
{
if (fd < 0)
{
__set_errno (EBADF);
return -1;
}
__set_errno (ENOSYS);
return -1;
}
libc_hidden_def (__fcntl64)
stub_warning (fcntl64)
weak_alias (__fcntl64, fcntl64)

View File

@ -82,7 +82,7 @@ static void timeout_handler (int signum) {};
memset (&fl, '\0', sizeof (struct flock)); \
fl.l_type = (type); \
fl.l_whence = SEEK_SET; \
if (__fcntl_nocancel ((fd), F_SETLKW, &fl) < 0)
if (__fcntl64_nocancel ((fd), F_SETLKW, &fl) < 0)
#define LOCKING_FAILED() \
goto unalarm_return
@ -90,7 +90,7 @@ static void timeout_handler (int signum) {};
#define UNLOCK_FILE(fd) \
/* Unlock the file. */ \
fl.l_type = F_UNLCK; \
__fcntl_nocancel ((fd), F_SETLKW, &fl); \
__fcntl64_nocancel ((fd), F_SETLKW, &fl); \
\
unalarm_return: \
/* Reset the signal handler and alarm. We must reset the alarm \

View File

@ -3281,12 +3281,13 @@ Set process or process group ID to receive @code{SIGIO} signals.
@xref{Interrupt Input}.
@end vtable
This function is a cancellation point in multi-threaded programs. This
is a problem if the thread allocates some resources (like memory, file
descriptors, semaphores or whatever) at the time @code{fcntl} is
called. If the thread gets canceled these resources stay allocated
until the program ends. To avoid this calls to @code{fcntl} should be
protected using cancellation handlers.
This function is a cancellation point in multi-threaded programs for the
commands @code{F_SETLKW} (and the LFS analogous @code{F_SETLKW64}) and
@code {F_OFD_SETLKW}. This is a problem if the thread allocates some
resources (like memory, file descriptors, semaphores or whatever) at the time
@code{fcntl} is called. If the thread gets canceled these resources stay
allocated until the program ends. To avoid this calls to @code{fcntl} should
be protected using cancellation handlers.
@c ref pthread_cleanup_push / pthread_cleanup_pop
@end deftypefun

View File

@ -191,6 +191,7 @@ CFLAGS-sem_timedwait.c += -fexceptions -fasynchronous-unwind-tables
# These are the function wrappers we have to duplicate here.
CFLAGS-fcntl.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-fcntl64.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-lockf.c += -fexceptions
CFLAGS-pread.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-pread64.c += -fexceptions -fasynchronous-unwind-tables

View File

@ -51,7 +51,7 @@
__pause ()
#define __nanosleep_nocancel(requested_time, remaining) \
__nanosleep (requested_time, remaining)
#define __fcntl_nocancel(fd, cmd, ...) \
__fcntl (fd, cmd, __VA_ARGS__)
#define __fcntl64_nocancel(fd, cmd, ...) \
__fcntl64 (fd, cmd, __VA_ARGS__)
#endif /* NOT_CANCEL_H */

View File

@ -1,9 +1,18 @@
/* This file generated by errnos.awk from
errno.texi
stdc-predef.h
libc-symbols.h
mach/message.h
mach/kern_return.h
mach/i386/kern_return.h
mach/port.h
mach/boolean.h
mach/i386/boolean.h
mach/i386/vm_types.h
mach/mig_errors.h
device/device_types.h
mach/std_types.h
/home/azanella/Projects/glibc/build/i686-gnu/errnos.d
Do not edit this file; edit errnos.awk and regenerate it. */
#ifndef _BITS_ERRNO_H

View File

@ -210,3 +210,8 @@ libc_hidden_def (__libc_fcntl)
weak_alias (__libc_fcntl, __fcntl)
libc_hidden_weak (__fcntl)
weak_alias (__libc_fcntl, fcntl)
strong_alias (__libc_fcntl, __libc_fcntl64)
libc_hidden_def (__libc_fcntl64)
weak_alias (__libc_fcntl64, __fcntl64)
libc_hidden_weak (__fcntl64)

View File

@ -2033,6 +2033,8 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -38,7 +38,7 @@ __fdopendir (int fd)
}
/* Make sure the descriptor allows for reading. */
int flags = __fcntl_nocancel (fd, F_GETFL);
int flags = __fcntl64_nocancel (fd, F_GETFL);
if (__glibc_unlikely (flags == -1))
return NULL;
if (__glibc_unlikely ((flags & O_ACCMODE) == O_WRONLY))

View File

@ -99,7 +99,7 @@ __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
/* We have to set the close-on-exit flag if the user provided the
file descriptor. */
if (!close_fd
&& __glibc_unlikely (__fcntl_nocancel (fd, F_SETFD, FD_CLOEXEC) < 0))
&& __glibc_unlikely (__fcntl64_nocancel (fd, F_SETFD, FD_CLOEXEC) < 0))
goto lose;
const size_t default_allocation = (4 * BUFSIZ < sizeof (struct dirent64)

View File

@ -37,7 +37,7 @@ fcntl_compat (int fd, int cmd, ...)
va_start (ap, cmd);
arg = va_arg (ap, void *);
va_end (ap);
return __libc_fcntl (fd, cmd, arg);
return __libc_fcntl64 (fd, cmd, arg);
}
weak_alias (fcntl_compat, fcntl_alias)

View File

@ -45,7 +45,9 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \
test-errno-linux tst-memfd_create tst-mlock2 tst-pkey \
tst-rlimit-infinity
tst-rlimit-infinity tst-ofdlocks
tests-internal += tst-ofdlocks-compat
# Generate the list of SYS_* macros for the system calls (__NR_*
# macros). The file syscall-names.list contains all possible system

View File

@ -2131,3 +2131,4 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F

View File

@ -2026,6 +2026,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -115,6 +115,8 @@ GLIBC_2.27 wcstof32x F
GLIBC_2.27 wcstof32x_l F
GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.4 _Exit F
GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
GLIBC_2.4 _IO_2_1_stdin_ D 0xa0

View File

@ -20,15 +20,12 @@
#include <stdarg.h>
#include <errno.h>
#include <sysdep-cancel.h>
#include <not-cancel.h>
#ifndef __NR_fcntl64
# define __NR_fcntl64 __NR_fcntl
#endif
#ifndef __OFF_T_MATCHES_OFF64_T
#ifndef FCNTL_ADJUST_CMD
# define FCNTL_ADJUST_CMD(__cmd) __cmd
#endif
# ifndef FCNTL_ADJUST_CMD
# define FCNTL_ADJUST_CMD(__cmd) __cmd
# endif
int
__libc_fcntl (int fd, int cmd, ...)
@ -42,13 +39,84 @@ __libc_fcntl (int fd, int cmd, ...)
cmd = FCNTL_ADJUST_CMD (cmd);
if (cmd == F_SETLKW || cmd == F_SETLKW64)
return SYSCALL_CANCEL (fcntl64, fd, cmd, (void *) arg);
return __fcntl_nocancel_adjusted (fd, cmd, arg);
switch (cmd)
{
case F_SETLKW:
case F_SETLKW64:
return SYSCALL_CANCEL (fcntl64, fd, cmd, arg);
case F_OFD_SETLKW:
{
struct flock *flk = (struct flock *) arg;
struct flock64 flk64 =
{
.l_type = flk->l_type,
.l_whence = flk->l_whence,
.l_start = flk->l_start,
.l_len = flk->l_len,
.l_pid = flk->l_pid
};
return SYSCALL_CANCEL (fcntl64, fd, cmd, &flk64);
}
case F_OFD_GETLK:
case F_OFD_SETLK:
{
struct flock *flk = (struct flock *) arg;
struct flock64 flk64 =
{
.l_type = flk->l_type,
.l_whence = flk->l_whence,
.l_start = flk->l_start,
.l_len = flk->l_len,
.l_pid = flk->l_pid
};
int ret = INLINE_SYSCALL_CALL (fcntl64, fd, cmd, &flk64);
if (ret == -1)
return -1;
if ((off_t) flk64.l_start != flk64.l_start
|| (off_t) flk64.l_len != flk64.l_len)
{
__set_errno (EOVERFLOW);
return -1;
}
flk->l_type = flk64.l_type;
flk->l_whence = flk64.l_whence;
flk->l_start = flk64.l_start;
flk->l_len = flk64.l_len;
flk->l_pid = flk64.l_pid;
return ret;
}
/* Since only F_SETLKW{64}/F_OLD_SETLK are cancellation entrypoints and
only OFD locks require LFS handling, all others flags are handled
unmodified by calling __NR_fcntl64. */
default:
return __fcntl64_nocancel_adjusted (fd, cmd, arg);
}
}
libc_hidden_def (__libc_fcntl)
weak_alias (__libc_fcntl, __fcntl)
libc_hidden_weak (__fcntl)
# include <shlib-compat.h>
# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_28)
int
__old_libc_fcntl64 (int fd, int cmd, ...)
{
va_list ap;
void *arg;
va_start (ap, cmd);
arg = va_arg (ap, void *);
va_end (ap);
/* Previous versions called __NR_fcntl64 for fcntl (which did not handle
OFD locks in LFS mode). */
return __libc_fcntl64 (fd, cmd, arg);
}
compat_symbol (libc, __old_libc_fcntl64, fcntl, GLIBC_2_0);
versioned_symbol (libc, __libc_fcntl, fcntl, GLIBC_2_28);
# else
weak_alias (__libc_fcntl, fcntl)
# endif
#endif /* __OFF_T_MATCHES_OFF64_T */

View File

@ -0,0 +1,63 @@
/* Manipulate file descriptor. Linux LFS version.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define fcntl __no_decl_fcntl
#define __fcntl __no_decl___fcntl
#include <fcntl.h>
#undef fcntl
#undef __fcntl
#include <stdarg.h>
#include <errno.h>
#include <sysdep-cancel.h>
#ifndef __NR_fcntl64
# define __NR_fcntl64 __NR_fcntl
#endif
#ifndef FCNTL_ADJUST_CMD
# define FCNTL_ADJUST_CMD(__cmd) __cmd
#endif
int
__libc_fcntl64 (int fd, int cmd, ...)
{
va_list ap;
void *arg;
va_start (ap, cmd);
arg = va_arg (ap, void *);
va_end (ap);
cmd = FCNTL_ADJUST_CMD (cmd);
if (cmd == F_SETLKW || cmd == F_SETLKW64 || cmd == F_OFD_SETLKW)
return SYSCALL_CANCEL (fcntl64, fd, cmd, arg);
return __fcntl64_nocancel_adjusted (fd, cmd, arg);
}
libc_hidden_def (__libc_fcntl64)
weak_alias (__libc_fcntl64, __fcntl64)
libc_hidden_weak (__fcntl64)
weak_alias (__libc_fcntl64, fcntl64)
#ifdef __OFF_T_MATCHES_OFF64_T
weak_alias (__libc_fcntl64, __libc_fcntl)
weak_alias (__libc_fcntl64, __fcntl)
weak_alias (__libc_fcntl64, __GI___fcntl)
weak_alias (__libc_fcntl64, fcntl)
#endif

View File

@ -31,7 +31,7 @@
#endif
int
__fcntl_nocancel (int fd, int cmd, ...)
__fcntl64_nocancel (int fd, int cmd, ...)
{
va_list ap;
void *arg;
@ -42,12 +42,12 @@ __fcntl_nocancel (int fd, int cmd, ...)
cmd = FCNTL_ADJUST_CMD (cmd);
return __fcntl_nocancel_adjusted (fd, cmd, arg);
return __fcntl64_nocancel_adjusted (fd, cmd, arg);
}
hidden_def (__fcntl_nocancel)
hidden_def (__fcntl64_nocancel)
int
__fcntl_nocancel_adjusted (int fd, int cmd, void *arg)
__fcntl64_nocancel_adjusted (int fd, int cmd, void *arg)
{
if (cmd == F_GETOWN)
{

View File

@ -1872,6 +1872,8 @@ GLIBC_2.27 wcstof32x F
GLIBC_2.27 wcstof32x_l F
GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -2037,6 +2037,8 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -1907,6 +1907,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -116,6 +116,8 @@ GLIBC_2.27 wcstof32x F
GLIBC_2.27 wcstof32x_l F
GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.4 _Exit F
GLIBC_2.4 _IO_2_1_stderr_ D 0x98
GLIBC_2.4 _IO_2_1_stdin_ D 0x98

View File

@ -1981,6 +1981,8 @@ GLIBC_2.27 wcstof32x F
GLIBC_2.27 wcstof32x_l F
GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -2122,3 +2122,5 @@ GLIBC_2.27 wcstof32x F
GLIBC_2.27 wcstof32x_l F
GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F

View File

@ -1959,6 +1959,8 @@ GLIBC_2.27 wcstof32x F
GLIBC_2.27 wcstof32x_l F
GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -1957,6 +1957,8 @@ GLIBC_2.27 wcstof32x F
GLIBC_2.27 wcstof32x_l F
GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -1965,6 +1965,8 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -1961,6 +1961,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -2163,3 +2163,5 @@ GLIBC_2.27 wcstof32x F
GLIBC_2.27 wcstof32x_l F
GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F

View File

@ -76,7 +76,7 @@ __typeof (pause) __pause_nocancel;
__typeof (__nanosleep) __nanosleep_nocancel;
/* Uncancelable fcntl. */
__typeof (__fcntl) __fcntl_nocancel;
__typeof (__fcntl) __fcntl64_nocancel;
#if IS_IN (libc) || IS_IN (rtld)
hidden_proto (__open_nocancel)
@ -89,7 +89,7 @@ hidden_proto (__close_nocancel)
hidden_proto (__waitpid_nocancel)
hidden_proto (__pause_nocancel)
hidden_proto (__nanosleep_nocancel)
hidden_proto (__fcntl_nocancel)
hidden_proto (__fcntl64_nocancel)
#endif
#endif /* NOT_CANCEL_H */

View File

@ -1985,6 +1985,8 @@ GLIBC_2.27 wcstof32x F
GLIBC_2.27 wcstof32x_l F
GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -1989,6 +1989,8 @@ GLIBC_2.27 wcstof32x F
GLIBC_2.27 wcstof32x_l F
GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -2221,3 +2221,4 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F

View File

@ -116,6 +116,7 @@ GLIBC_2.27 wcstof32x F
GLIBC_2.27 wcstof32x_l F
GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 _Exit F
GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
GLIBC_2.3 _IO_2_1_stdin_ D 0xe0

View File

@ -2093,3 +2093,4 @@ GLIBC_2.27 xdrstdio_create F
GLIBC_2.27 xencrypt F
GLIBC_2.27 xprt_register F
GLIBC_2.27 xprt_unregister F
GLIBC_2.28 fcntl64 F

View File

@ -1994,6 +1994,8 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -1900,6 +1900,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -1876,6 +1876,8 @@ GLIBC_2.27 wcstof32x F
GLIBC_2.27 wcstof32x_l F
GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -1988,6 +1988,8 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -1930,6 +1930,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -0,0 +1,84 @@
/* Check non representable OFD locks regions in non-LFS mode for compat
mode (BZ #20251)
Copyright (C) 2018 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
#include <errno.h>
#include <support/temp_file.h>
#include <support/check.h>
#include <shlib-compat.h>
#if TEST_COMPAT (libc, GLIBC_2_0, GLIBC_2_28)
compat_symbol_reference (libc, fcntl, fcntl, GLIBC_2_0);
static char *temp_filename;
static int temp_fd;
static void
do_prepare (int argc, char **argv)
{
temp_fd = create_temp_file ("tst-ofdlocks-compat.", &temp_filename);
TEST_VERIFY_EXIT (temp_fd != -1);
}
#define PREPARE do_prepare
static int
do_test (void)
{
/* The compat fcntl version for architectures which support non-LFS
operations does not wrap the flock OFD argument, so the struct is passed
unmodified to kernel. It means no EOVERFLOW is returned, so operations
with LFS should not incur in failure. */
struct flock64 lck64 = {
.l_type = F_WRLCK,
.l_whence = SEEK_SET,
.l_start = (off64_t)INT32_MAX + 1024,
.l_len = 1024,
};
TEST_VERIFY_EXIT (fcntl (temp_fd, F_OFD_SETLKW, &lck64) == 0);
/* Open file description locks placed through the same open file description
(either by same file descriptor or a duplicated one created by fork,
dup, fcntl F_DUPFD, etc.) overwrites then old lock. To force a
conflicting lock combination, it creates a new file descriptor. */
int fd = open64 (temp_filename, O_RDWR, 0666);
TEST_VERIFY_EXIT (fd != -1);
struct flock64 lck = {
.l_type = F_WRLCK,
.l_whence = SEEK_SET,
.l_start = INT32_MAX - 1024,
.l_len = 4 * 1024,
};
TEST_VERIFY (fcntl (fd, F_OFD_GETLK, &lck) == 0);
return 0;
}
#else
static int
do_test (void)
{
return 77;
}
#endif
#include <support/test-driver.c>

View File

@ -0,0 +1,76 @@
/* Check non representable OFD locks regions in non-LFS mode (BZ #20251)
Copyright (C) 2018 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
#include <errno.h>
#include <support/temp_file.h>
#include <support/check.h>
static char *temp_filename;
static int temp_fd;
static void
do_prepare (int argc, char **argv)
{
temp_fd = create_temp_file ("tst-ofdlocks.", &temp_filename);
TEST_VERIFY_EXIT (temp_fd != -1);
}
#define PREPARE do_prepare
static int
do_test (void)
{
/* It first allocates a open file description lock range which can not
be represented in a 32 bit struct flock. */
struct flock64 lck64 = {
.l_type = F_WRLCK,
.l_whence = SEEK_SET,
.l_start = (off64_t)INT32_MAX + 1024,
.l_len = 1024,
};
TEST_VERIFY_EXIT (fcntl64 (temp_fd, F_OFD_SETLKW, &lck64) == 0);
/* Open file description locks placed through the same open file description
(either by same file descriptor or a duplicated one created by fork,
dup, fcntl F_DUPFD, etc.) overwrites then old lock. To force a
conflicting lock combination, it creates a new file descriptor. */
int fd = open64 (temp_filename, O_RDWR, 0666);
TEST_VERIFY_EXIT (fd != -1);
/* It tries then to allocate another open file descriptior with a valid
non-LFS bits struct flock but which will result in a conflicted region
which can not be represented in a non-LFS struct flock. */
struct flock lck = {
.l_type = F_WRLCK,
.l_whence = SEEK_SET,
.l_start = INT32_MAX - 1024,
.l_len = 4 * 1024,
};
int r = fcntl (fd, F_OFD_GETLK, &lck);
if (sizeof (off_t) != sizeof (off64_t))
TEST_VERIFY (r == -1 && errno == EOVERFLOW);
else
TEST_VERIFY (r == 0);
return 0;
}
#include <support/test-driver.c>

View File

@ -1888,6 +1888,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F

View File

@ -2139,3 +2139,4 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F