Blame sysdeps/unix/sysv/linux/tst-ofdlocks-compat.c

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