(root)/
glibc-2.38/
posix/
test-errno.c
       1  /* Test that failing system calls do set errno to the correct value.
       2  
       3     Copyright (C) 2017-2023 Free Software Foundation, Inc.
       4     This file is part of the GNU C Library.
       5  
       6     The GNU C Library is free software; you can redistribute it and/or
       7     modify it under the terms of the GNU Lesser General Public
       8     License as published by the Free Software Foundation; either
       9     version 2.1 of the License, or (at your option) any later version.
      10  
      11     The GNU C Library is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14     Lesser General Public License for more details.
      15  
      16     You should have received a copy of the GNU Lesser General Public
      17     License along with the GNU C Library; if not, see
      18     <https://www.gnu.org/licenses/>.  */
      19  
      20  #include <sys/cdefs.h>
      21  #include <libc-diag.h>
      22  #if __GNUC_PREREQ (7, 0)
      23  /* Triggered by getgroup fortify wrapper.  */
      24  DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow");
      25  #endif
      26  
      27  #include <errno.h>
      28  #include <limits.h>
      29  #include <grp.h>
      30  #include <fcntl.h>
      31  #include <stdio.h>
      32  #include <string.h>
      33  #include <sys/ioctl.h>
      34  #include <sys/socket.h>
      35  #include <sys/stat.h>
      36  #include <sys/time.h>
      37  #include <sys/resource.h>
      38  #include <sys/types.h>
      39  #include <sys/statfs.h>
      40  #include <sys/mman.h>
      41  #include <sys/uio.h>
      42  #include <unistd.h>
      43  #include <netinet/in.h>
      44  
      45  /* This is not an exhaustive test: only system calls that can be
      46     persuaded to fail with a consistent error code and no side effects
      47     are included.  Usually these are failures due to invalid arguments,
      48     with errno code EBADF or EINVAL.  The order of argument checks is
      49     unspecified, so we must take care to provide arguments that only
      50     allow _one_ failure mode.
      51  
      52     Note that all system calls that can fail with EFAULT are permitted
      53     to deliver a SIGSEGV signal instead, so we avoid supplying invalid
      54     pointers in general, and we do not attempt to test system calls
      55     that can only fail with EFAULT (e.g. gettimeofday, gethostname).
      56  
      57     Also note that root-only system calls (e.g. acct, reboot) may, when
      58     the test is run as an unprivileged user, fail due to insufficient
      59     privileges before bothering to do argument checks, so those are not
      60     tested either.
      61  
      62     Also, system calls that take enum or a set of flags as argument is
      63     not tested if POSIX doesn't specify exact binary values for all
      64     flags, and so any value passed to flags may become valid.
      65  
      66     Some tests assume "/bin/sh" names a file that exists and is not a
      67     directory.  */
      68  
      69  #define test_wrp_rv(rtype, prtype, experr, syscall, ...)	\
      70    (__extension__ ({						\
      71      errno = 0xdead;						\
      72      rtype ret = syscall (__VA_ARGS__);				\
      73      int err = errno;						\
      74      int fail;							\
      75      if (ret == (rtype) -1 && err == experr)			\
      76        fail = 0;							\
      77      else							\
      78        {								\
      79          fail = 1;						\
      80          if (ret != (rtype) -1)					\
      81            printf ("FAIL: " #syscall ": didn't fail as expected"	\
      82                 " (return "prtype")\n", ret);			\
      83          else if (err == 0xdead)					\
      84            puts("FAIL: " #syscall ": didn't update errno\n");	\
      85          else if (err != experr)					\
      86            printf ("FAIL: " #syscall				\
      87                 ": errno is: %d (%s) expected: %d (%s)\n",	\
      88                 err, strerror (err), experr, strerror (experr));	\
      89        }								\
      90      fail;							\
      91    }))
      92  
      93  #define test_wrp(experr, syscall, ...)				\
      94    test_wrp_rv(int, "%d", experr, syscall, __VA_ARGS__)
      95  
      96  static int
      97  do_test (void)
      98  {
      99    size_t pagesize = sysconf (_SC_PAGESIZE);
     100    struct statfs sfs;
     101    struct sockaddr sa;
     102    socklen_t sl;
     103    char buf[1];
     104    struct iovec iov[1] = { { buf, 1 } };
     105    struct sockaddr_in sin;
     106    sin.sin_family = AF_INET;
     107    sin.sin_port = htons (1026);
     108    sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
     109    struct msghdr msg;
     110    memset(&msg, 0, sizeof msg);
     111    msg.msg_iov = iov;
     112    msg.msg_iovlen = 1;
     113  
     114    int fails = 0;
     115    fails |= test_wrp (EBADF, accept, -1, &sa, &sl);
     116    fails |= test_wrp (EINVAL, access, "/", -1);
     117    fails |= test_wrp (EBADF, bind, -1, (struct sockaddr *)&sin, sizeof sin);
     118    fails |= test_wrp (ENOTDIR, chdir, "/bin/sh");
     119    fails |= test_wrp (EBADF, close, -1);
     120    fails |= test_wrp (EBADF, connect, -1, (struct sockaddr *)&sin, sizeof sin);
     121    fails |= test_wrp (EBADF, dup, -1);
     122    fails |= test_wrp (EBADF, dup2, -1, -1);
     123    fails |= test_wrp (EBADF, fchdir, -1);
     124    fails |= test_wrp (EBADF, fchmod, -1, 0);
     125    fails |= test_wrp (EBADF, fcntl, -1, 0);
     126    fails |= test_wrp (EBADF, fstatfs, -1, &sfs);
     127    fails |= test_wrp (EBADF, fsync, -1);
     128    fails |= test_wrp (EBADF, ftruncate, -1, 0);
     129  
     130  #if __GNUC_PREREQ (7, 0)
     131    DIAG_PUSH_NEEDS_COMMENT;
     132    /* Avoid warnings about the second (size) argument being negative.  */
     133    DIAG_IGNORE_NEEDS_COMMENT (10.1, "-Wstringop-overflow");
     134  #endif
     135    fails |= test_wrp (EINVAL, getgroups, -1, 0);
     136  #if __GNUC_PREREQ (7, 0)
     137    DIAG_POP_NEEDS_COMMENT;
     138  #endif
     139    fails |= test_wrp (EBADF, getpeername, -1, &sa, &sl);
     140    fails |= test_wrp (EBADF, getsockname, -1, &sa, &sl);
     141    fails |= test_wrp (EBADF, getsockopt, -1, 0, 0, buf, &sl);
     142    fails |= test_wrp (EBADF, ioctl, -1, TIOCNOTTY);
     143    fails |= test_wrp (EBADF, listen, -1, 1);
     144    fails |= test_wrp (EBADF, lseek, -1, 0, 0);
     145    fails |= test_wrp (EINVAL, madvise, (void *) -1, -1, 0);
     146    fails |= test_wrp_rv (void *, "%p", EBADF,
     147                          mmap, 0, pagesize, PROT_READ, MAP_PRIVATE, -1, 0);
     148    fails |= test_wrp (EINVAL, mprotect, (void *) -1, pagesize, -1);
     149    fails |= test_wrp (EINVAL, msync, (void *) -1, pagesize, -1);
     150    fails |= test_wrp (EINVAL, munmap, (void *) -1, 0);
     151    fails |= test_wrp (EISDIR, open, "/bin", EISDIR, O_WRONLY);
     152    fails |= test_wrp (EBADF, read, -1, buf, 1);
     153    fails |= test_wrp (EINVAL, readlink, "/", buf, sizeof buf);
     154    fails |= test_wrp (EBADF, readv, -1, iov, 1);
     155    fails |= test_wrp (EBADF, recv, -1, buf, 1, 0);
     156    fails |= test_wrp (EBADF, recvfrom, -1, buf, 1, 0, &sa, &sl);
     157    fails |= test_wrp (EBADF, recvmsg, -1, &msg, 0);
     158    fails |= test_wrp (EINVAL, select, -1, 0, 0, 0, 0);
     159    fails |= test_wrp (EBADF, send, -1, buf, 1, 0);
     160    fails |= test_wrp (EBADF, sendmsg, -1, &msg, 0);
     161    fails |= test_wrp (EBADF, sendto, -1, buf, 1, 0, &sa, sl);
     162    fails |= test_wrp (EBADF, setsockopt, -1, 0, 0, buf, sizeof (*buf));
     163    fails |= test_wrp (EBADF, shutdown, -1, SHUT_RD);
     164    fails |= test_wrp (EBADF, write, -1, "Hello", sizeof ("Hello") );
     165    fails |= test_wrp (EBADF, writev, -1, iov, 1 );
     166  
     167    return fails;
     168  }
     169  
     170  #include "support/test-driver.c"