summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/tst-ofdlocks.c
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2018-04-04 11:24:15 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2018-06-26 13:22:53 -0300
commit06ab719d30b01da401150068054d3b8ea93dd12f (patch)
tree3a5204a151219d410caf2cc43afcec5bce19d54b /sysdeps/unix/sysv/linux/tst-ofdlocks.c
parent124e025864bb39732c71fc60c1443d5680881a0a (diff)
downloadglibc-06ab719d30b01da401150068054d3b8ea93dd12f.tar.gz
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.
Diffstat (limited to 'sysdeps/unix/sysv/linux/tst-ofdlocks.c')
-rw-r--r--sysdeps/unix/sysv/linux/tst-ofdlocks.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/tst-ofdlocks.c b/sysdeps/unix/sysv/linux/tst-ofdlocks.c
new file mode 100644
index 0000000000..bd345e9b64
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-ofdlocks.c
@@ -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>