Blame sysdeps/unix/sysv/linux/test-errno-linux.c

Packit Service 82fcde
/* Test that failing system calls do set errno to the correct value.
Packit Service 82fcde
   Linux sycalls version.
Packit Service 82fcde
Packit Service 82fcde
   Copyright (C) 2017-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <array_length.h>
Packit Service 82fcde
#include <errno.h>
Packit Service 82fcde
#include <fcntl.h>
Packit Service 82fcde
#include <mqueue.h>
Packit Service 82fcde
#include <sched.h>
Packit Service 82fcde
#include <signal.h>
Packit Service 82fcde
#include <stdbool.h>
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <time.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <sys/epoll.h>
Packit Service 82fcde
#include <sys/eventfd.h>
Packit Service 82fcde
#include <sys/file.h>
Packit Service 82fcde
#include <sys/fsuid.h>
Packit Service 82fcde
#include <sys/inotify.h>
Packit Service 82fcde
#include <sys/mman.h>
Packit Service 82fcde
#include <sys/poll.h>
Packit Service 82fcde
#include <sys/quota.h>
Packit Service 82fcde
#include <sys/resource.h>
Packit Service 82fcde
#include <sys/select.h>
Packit Service 82fcde
#include <sys/sendfile.h>
Packit Service 82fcde
#include <sys/swap.h>
Packit Service 82fcde
#include <sys/time.h>
Packit Service 82fcde
#include <sys/types.h>
Packit Service 82fcde
#include <sys/wait.h>
Packit Service 82fcde
Packit Service 82fcde
/* This is not an exhaustive test: only system calls that can be
Packit Service 82fcde
   persuaded to fail with a consistent error code and no side effects
Packit Service 82fcde
   are included.  Usually these are failures due to invalid arguments,
Packit Service 82fcde
   with errno code EBADF or EINVAL.  The order of argument checks is
Packit Service 82fcde
   unspecified, so we must take care to provide arguments that only
Packit Service 82fcde
   allow _one_ failure mode.
Packit Service 82fcde
Packit Service 82fcde
   Note that all system calls that can fail with EFAULT are permitted
Packit Service 82fcde
   to deliver a SIGSEGV signal instead, so we avoid supplying invalid
Packit Service 82fcde
   pointers in general, and we do not attempt to test system calls
Packit Service 82fcde
   that can only fail with EFAULT (e.g. gettimeofday, gethostname).
Packit Service 82fcde
Packit Service 82fcde
   Also note that root-only system calls (e.g. acct, reboot) may, when
Packit Service 82fcde
   the test is run as an unprivileged user, fail due to insufficient
Packit Service 82fcde
   privileges before bothering to do argument checks, so those are not
Packit Service 82fcde
   tested either.
Packit Service 82fcde
Packit Service 82fcde
   Also, system calls that take enum or a set of flags as argument is
Packit Service 82fcde
   not tested if POSIX doesn't specify exact binary values for all
Packit Service 82fcde
   flags, and so any value passed to flags may become valid.
Packit Service 82fcde
Packit Service 82fcde
   Some tests assume "/bin/sh" names a file that exists and is not a
Packit Service 82fcde
   directory.  */
Packit Service 82fcde
Packit Service 82fcde
/* Evalutes to the arguments in a list initializer which can be used
Packit Service 82fcde
   as a single macro argument.  */
Packit Service 82fcde
#define LIST(...) { __VA_ARGS__ }
Packit Service 82fcde
Packit Service 82fcde
/* This macro is necessary to forward the output of LIST as a macro
Packit Service 82fcde
   argument.  */
Packit Service 82fcde
#define LIST_FORWARD(...) __VA_ARGS__
Packit Service 82fcde
Packit Service 82fcde
/* Return true if CODE is contained in the array [CODES, CODES +
Packit Service 82fcde
   COUNT].  */
Packit Service 82fcde
static bool
Packit Service 82fcde
check_error_in_list (int code, int *codes, size_t count)
Packit Service 82fcde
{
Packit Service 82fcde
  for (size_t i = 0; i < count; ++i)
Packit Service 82fcde
    if (codes[i] == code)
Packit Service 82fcde
      return true;
Packit Service 82fcde
  return false;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#define test_wrp_rv(rtype, prtype, experr_list, syscall, ...)	\
Packit Service 82fcde
  (__extension__ ({						\
Packit Service 82fcde
    errno = 0xdead;						\
Packit Service 82fcde
    int experr[] = experr_list;					\
Packit Service 82fcde
    rtype ret = syscall (__VA_ARGS__);				\
Packit Service 82fcde
    int err = errno;						\
Packit Service 82fcde
    int fail;							\
Packit Service 82fcde
    if ((ret == (rtype) -1)					\
Packit Service 82fcde
	&& check_error_in_list (err, experr, array_length (experr))) \
Packit Service 82fcde
      fail = 0;							\
Packit Service 82fcde
    else							\
Packit Service 82fcde
      {								\
Packit Service 82fcde
        fail = 1;						\
Packit Service 82fcde
        if (ret != (rtype) -1)					\
Packit Service 82fcde
          printf ("FAIL: " #syscall ": didn't fail as expected"	\
Packit Service 82fcde
		  " (return "prtype")\n", ret);			\
Packit Service 82fcde
        else if (err == 0xdead)					\
Packit Service 82fcde
          puts ("FAIL: " #syscall ": didn't update errno");	\
Packit Service 82fcde
	else							\
Packit Service 82fcde
          printf ("FAIL: " #syscall				\
Packit Service 82fcde
		  ": errno is: %d (%s) expected one of %s\n",	\
Packit Service 82fcde
		  err, strerror (err), #experr_list);		\
Packit Service 82fcde
      }								\
Packit Service 82fcde
    fail;							\
Packit Service 82fcde
  }))
Packit Service 82fcde
Packit Service 82fcde
#define test_wrp(experr, syscall, ...)				\
Packit Service 82fcde
  test_wrp_rv(int, "%d", LIST (experr), syscall, __VA_ARGS__)
Packit Service 82fcde
Packit Service 82fcde
#define test_wrp2(experr, syscall, ...)		\
Packit Service 82fcde
  test_wrp_rv(int, "%d", LIST_FORWARD (experr), syscall, __VA_ARGS__)
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
do_test (void)
Packit Service 82fcde
{
Packit Service 82fcde
  fd_set rs, ws, es;
Packit Service 82fcde
  int status;
Packit Service 82fcde
  off_t off;
Packit Service 82fcde
  stack_t ss;
Packit Service 82fcde
  struct dqblk dqblk;
Packit Service 82fcde
  struct epoll_event epoll_event;
Packit Service 82fcde
  struct pollfd pollfd;
Packit Service 82fcde
  struct sched_param sch_param;
Packit Service 82fcde
  struct timespec ts;
Packit Service 82fcde
  struct timeval tv;
Packit Service 82fcde
  unsigned char vec[16];
Packit Service 82fcde
  ss.ss_flags = ~SS_DISABLE;
Packit Service 82fcde
  ts.tv_sec = -1;
Packit Service 82fcde
Packit Service 82fcde
  int fails = 0;
Packit Service 82fcde
  fails |= test_wrp (EINVAL, epoll_create, -1);
Packit Service 82fcde
  fails |= test_wrp (EINVAL, epoll_create1, EPOLL_CLOEXEC + 1);
Packit Service 82fcde
  fails |= test_wrp (EBADF, epoll_ctl, -1, EPOLL_CTL_ADD, 0, &epoll_event);
Packit Service 82fcde
  fails |= test_wrp (EBADF, epoll_wait, -1, &epoll_event, 1, 1);
Packit Service 82fcde
  fails |= test_wrp (EBADF, fdatasync, -1);
Packit Service 82fcde
  fails |= test_wrp (EBADF, flock, -1, LOCK_SH);
Packit Service 82fcde
  fails |= test_wrp (ESRCH, getpgid, -1);
Packit Service 82fcde
  /* Linux v3.8 (676a0675c) removed the test to check at least one valid
Packit Service 82fcde
     bit in flags (to return EINVAL).  It was later added back in v3.9
Packit Service 82fcde
     (04df32fa1).  */
Packit Service 82fcde
  fails |= test_wrp2 (LIST (EINVAL, EBADF), inotify_add_watch, -1, "/", 0);
Packit Service 82fcde
  fails |= test_wrp (EINVAL, mincore, (void *) -1, 0, vec);
Packit Service 82fcde
  /* mlock fails if the result of the addition addr+len was less than addr
Packit Service 82fcde
     (which indicates final address overflow), however on 32 bits binaries
Packit Service 82fcde
     running on 64 bits kernels, internal syscall address check won't result
Packit Service 82fcde
     in an invalid address and thus syscalls fails later in vma
Packit Service 82fcde
     allocation.  */
Packit Service 82fcde
  fails |= test_wrp2 (LIST (EINVAL, ENOMEM), mlock, (void *) -1, 1);
Packit Service 82fcde
  fails |= test_wrp (EINVAL, nanosleep, &ts, &ts);
Packit Service 82fcde
  fails |= test_wrp (EINVAL, poll, &pollfd, -1, 0);
Packit Service 82fcde
  /* quotactl returns ENOSYS for kernels not configured with
Packit Service 82fcde
     CONFIG_QUOTA, and may return EPERM if called within certain types
Packit Service 82fcde
     of containers.  */
Packit Service 82fcde
  fails |= test_wrp2 (LIST (ENODEV, ENOSYS, EPERM),
Packit Service 82fcde
		      quotactl, Q_GETINFO, NULL, -1, (caddr_t) &dqblk);
Packit Service 82fcde
  fails |= test_wrp (EINVAL, sched_getparam, -1, &sch_param);
Packit Service 82fcde
  fails |= test_wrp (EINVAL, sched_getscheduler, -1);
Packit Service 82fcde
  fails |= test_wrp (EINVAL, sched_get_priority_max, -1);
Packit Service 82fcde
  fails |= test_wrp (EINVAL, sched_get_priority_min, -1);
Packit Service 82fcde
  fails |= test_wrp (EINVAL, sched_rr_get_interval, -1, &ts);
Packit Service 82fcde
  fails |= test_wrp (EINVAL, sched_setparam, -1, &sch_param);
Packit Service 82fcde
  fails |= test_wrp (EINVAL, sched_setscheduler, -1, 0, &sch_param);
Packit Service 82fcde
  fails |= test_wrp (EINVAL, select, -1, &rs, &ws, &es, &tv;;
Packit Service 82fcde
  fails |= test_wrp (EBADF, sendfile, -1, -1, &off, 0);
Packit Service 82fcde
  fails |= test_wrp (EINVAL, sigaltstack, &ss, NULL);
Packit Service 82fcde
  fails |= test_wrp (ECHILD, wait4, -1, &status, 0, NULL);
Packit Service 82fcde
Packit Service 82fcde
  return fails;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#include "support/test-driver.c"