(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
test-errno-linux.c
       1  /* Test that failing system calls do set errno to the correct value.
       2     Linux sycalls version.
       3  
       4     Copyright (C) 2017-2023 Free Software Foundation, Inc.
       5     This file is part of the GNU C Library.
       6  
       7     The GNU C Library is free software; you can redistribute it and/or
       8     modify it under the terms of the GNU Lesser General Public
       9     License as published by the Free Software Foundation; either
      10     version 2.1 of the License, or (at your option) any later version.
      11  
      12     The GNU C Library is distributed in the hope that it will be useful,
      13     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15     Lesser General Public License for more details.
      16  
      17     You should have received a copy of the GNU Lesser General Public
      18     License along with the GNU C Library; if not, see
      19     <https://www.gnu.org/licenses/>.  */
      20  
      21  #include <array_length.h>
      22  #include <errno.h>
      23  #include <fcntl.h>
      24  #include <mqueue.h>
      25  #include <sched.h>
      26  #include <signal.h>
      27  #include <stdbool.h>
      28  #include <stdio.h>
      29  #include <string.h>
      30  #include <time.h>
      31  #include <unistd.h>
      32  #include <sys/epoll.h>
      33  #include <sys/eventfd.h>
      34  #include <sys/file.h>
      35  #include <sys/fsuid.h>
      36  #include <sys/inotify.h>
      37  #include <sys/mman.h>
      38  #include <sys/poll.h>
      39  #include <sys/quota.h>
      40  #include <sys/resource.h>
      41  #include <sys/select.h>
      42  #include <sys/sendfile.h>
      43  #include <sys/swap.h>
      44  #include <sys/time.h>
      45  #include <sys/types.h>
      46  #include <sys/wait.h>
      47  #include <libc-diag.h>
      48  
      49  /* This is not an exhaustive test: only system calls that can be
      50     persuaded to fail with a consistent error code and no side effects
      51     are included.  Usually these are failures due to invalid arguments,
      52     with errno code EBADF or EINVAL.  The order of argument checks is
      53     unspecified, so we must take care to provide arguments that only
      54     allow _one_ failure mode.
      55  
      56     Note that all system calls that can fail with EFAULT are permitted
      57     to deliver a SIGSEGV signal instead, so we avoid supplying invalid
      58     pointers in general, and we do not attempt to test system calls
      59     that can only fail with EFAULT (e.g. gettimeofday, gethostname).
      60  
      61     Also note that root-only system calls (e.g. acct, reboot) may, when
      62     the test is run as an unprivileged user, fail due to insufficient
      63     privileges before bothering to do argument checks, so those are not
      64     tested either.
      65  
      66     Also, system calls that take enum or a set of flags as argument is
      67     not tested if POSIX doesn't specify exact binary values for all
      68     flags, and so any value passed to flags may become valid.
      69  
      70     Some tests assume "/bin/sh" names a file that exists and is not a
      71     directory.  */
      72  
      73  /* Evaluates to the arguments in a list initializer which can be used
      74     as a single macro argument.  */
      75  #define LIST(...) { __VA_ARGS__ }
      76  
      77  /* This macro is necessary to forward the output of LIST as a macro
      78     argument.  */
      79  #define LIST_FORWARD(...) __VA_ARGS__
      80  
      81  /* Return true if CODE is contained in the array [CODES, CODES +
      82     COUNT].  */
      83  static bool
      84  check_error_in_list (int code, int *codes, size_t count)
      85  {
      86    for (size_t i = 0; i < count; ++i)
      87      if (codes[i] == code)
      88        return true;
      89    return false;
      90  }
      91  
      92  #define test_wrp_rv(rtype, prtype, experr_list, syscall, ...)	\
      93    (__extension__ ({						\
      94      errno = 0xdead;						\
      95      int experr[] = experr_list;					\
      96      rtype ret = syscall (__VA_ARGS__);				\
      97      int err = errno;						\
      98      int fail;							\
      99      if ((ret == (rtype) -1)					\
     100  	&& check_error_in_list (err, experr, array_length (experr))) \
     101        fail = 0;							\
     102      else							\
     103        {								\
     104          fail = 1;						\
     105          if (ret != (rtype) -1)					\
     106            printf ("FAIL: " #syscall ": didn't fail as expected"	\
     107  		  " (return "prtype")\n", ret);			\
     108          else if (err == 0xdead)					\
     109            puts ("FAIL: " #syscall ": didn't update errno");	\
     110  	else							\
     111            printf ("FAIL: " #syscall				\
     112  		  ": errno is: %d (%s) expected one of %s\n",	\
     113  		  err, strerror (err), #experr_list);		\
     114        }								\
     115      fail;							\
     116    }))
     117  
     118  #define test_wrp(experr, syscall, ...)				\
     119    test_wrp_rv(int, "%d", LIST (experr), syscall, __VA_ARGS__)
     120  
     121  #define test_wrp2(experr, syscall, ...)		\
     122    test_wrp_rv(int, "%d", LIST_FORWARD (experr), syscall, __VA_ARGS__)
     123  
     124  static int
     125  invalid_sigprocmask_how (void)
     126  {
     127    int n = 0;
     128    const int how[] = { SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK };
     129    for (int i = 0; i < array_length (how); i++)
     130      if (how[i] == n)
     131        n++;
     132    return n;
     133  }
     134  
     135  static int
     136  do_test (void)
     137  {
     138    fd_set rs, ws, es;
     139    int status;
     140    off_t off;
     141    stack_t ss;
     142    struct dqblk dqblk;
     143    struct epoll_event epoll_event;
     144    struct pollfd pollfd;
     145    struct sched_param sch_param;
     146    struct timespec ts;
     147    struct timeval tv;
     148    sigset_t sigs;
     149    unsigned char vec[16];
     150    ss.ss_flags = ~SS_DISABLE;
     151    ts.tv_sec = -1;
     152  
     153    sigemptyset (&sigs);
     154  
     155    int fails = 0;
     156    fails |= test_wrp (EINVAL, epoll_create, -1);
     157    fails |= test_wrp (EINVAL, epoll_create1, EPOLL_CLOEXEC + 1);
     158    fails |= test_wrp (EBADF, epoll_ctl, -1, EPOLL_CTL_ADD, 0, &epoll_event);
     159    fails |= test_wrp (EBADF, epoll_wait, -1, &epoll_event, 1, 1);
     160    fails |= test_wrp (EBADF, fdatasync, -1);
     161    fails |= test_wrp (EBADF, flock, -1, LOCK_SH);
     162    fails |= test_wrp (ESRCH, getpgid, -1);
     163    /* Linux v3.8 (676a0675c) removed the test to check at least one valid
     164       bit in flags (to return EINVAL).  It was later added back in v3.9
     165       (04df32fa1).  */
     166    fails |= test_wrp2 (LIST (EINVAL, EBADF), inotify_add_watch, -1, "/", 0);
     167    fails |= test_wrp (EINVAL, mincore, (void *) -1, 0, vec);
     168    /* mlock fails if the result of the addition addr+len was less than addr
     169       (which indicates final address overflow), however on 32 bits binaries
     170       running on 64 bits kernels, internal syscall address check won't result
     171       in an invalid address and thus syscalls fails later in vma
     172       allocation.  */
     173    fails |= test_wrp2 (LIST (EINVAL, ENOMEM), mlock, (void *) -1, 1);
     174    fails |= test_wrp (EINVAL, nanosleep, &ts, &ts);
     175  
     176    DIAG_PUSH_NEEDS_COMMENT;
     177  
     178  #if __GNUC_PREREQ (9, 0)
     179    /* Suppress valid GCC warning:
     180       'poll' specified size 18446744073709551608 exceeds maximum object size
     181    */
     182    DIAG_IGNORE_NEEDS_COMMENT (9, "-Wstringop-overflow=");
     183  #endif
     184    fails |= test_wrp (EINVAL, poll, &pollfd, -1, 0);
     185    DIAG_POP_NEEDS_COMMENT;
     186  
     187    /* quotactl returns ENOSYS for kernels not configured with
     188       CONFIG_QUOTA, and may return EPERM if called within certain types
     189       of containers.  Linux 5.4 added additional argument validation
     190       and can return EINVAL.  */
     191    fails |= test_wrp2 (LIST (ENODEV, ENOSYS, EPERM, EINVAL),
     192  		      quotactl, Q_GETINFO, NULL, -1, (caddr_t) &dqblk);
     193    fails |= test_wrp (EINVAL, sched_getparam, -1, &sch_param);
     194    fails |= test_wrp (EINVAL, sched_getscheduler, -1);
     195    fails |= test_wrp (EINVAL, sched_get_priority_max, -1);
     196    fails |= test_wrp (EINVAL, sched_get_priority_min, -1);
     197    fails |= test_wrp (EINVAL, sched_rr_get_interval, -1, &ts);
     198    fails |= test_wrp (EINVAL, sched_setparam, -1, &sch_param);
     199    fails |= test_wrp (EINVAL, sched_setscheduler, -1, 0, &sch_param);
     200    fails |= test_wrp (EINVAL, select, -1, &rs, &ws, &es, &tv);
     201    fails |= test_wrp (EBADF, sendfile, -1, -1, &off, 0);
     202    fails |= test_wrp (EINVAL, sigaltstack, &ss, NULL);
     203    fails |= test_wrp (ECHILD, wait4, -1, &status, 0, NULL);
     204    /* Austin Group issue #1132 states EINVAL should be returned for invalid
     205       how argument iff the new set mask is non-null.  And Linux follows the
     206       standard on this regard.  */
     207    fails |= test_wrp (EINVAL, sigprocmask, invalid_sigprocmask_how (), &sigs,
     208  		     NULL);
     209  
     210    return fails;
     211  }
     212  
     213  #include "support/test-driver.c"