]>
Commit | Line | Data |
---|---|---|
9a56f871 | 1 | /* Test that failing system calls do set errno to the correct value. |
b36a65e5 | 2 | Linux sycalls version. |
9a56f871 | 3 | |
04277e02 | 4 | Copyright (C) 2017-2019 Free Software Foundation, Inc. |
9a56f871 YN |
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 | |
5a82c748 | 19 | <https://www.gnu.org/licenses/>. */ |
9a56f871 | 20 | |
ef11081f | 21 | #include <array_length.h> |
9a56f871 YN |
22 | #include <errno.h> |
23 | #include <fcntl.h> | |
24 | #include <mqueue.h> | |
25 | #include <sched.h> | |
26 | #include <signal.h> | |
ef11081f | 27 | #include <stdbool.h> |
9a56f871 YN |
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 | ||
48 | /* This is not an exhaustive test: only system calls that can be | |
49 | persuaded to fail with a consistent error code and no side effects | |
50 | are included. Usually these are failures due to invalid arguments, | |
51 | with errno code EBADF or EINVAL. The order of argument checks is | |
52 | unspecified, so we must take care to provide arguments that only | |
53 | allow _one_ failure mode. | |
54 | ||
55 | Note that all system calls that can fail with EFAULT are permitted | |
56 | to deliver a SIGSEGV signal instead, so we avoid supplying invalid | |
57 | pointers in general, and we do not attempt to test system calls | |
58 | that can only fail with EFAULT (e.g. gettimeofday, gethostname). | |
59 | ||
60 | Also note that root-only system calls (e.g. acct, reboot) may, when | |
61 | the test is run as an unprivileged user, fail due to insufficient | |
62 | privileges before bothering to do argument checks, so those are not | |
63 | tested either. | |
64 | ||
65 | Also, system calls that take enum or a set of flags as argument is | |
66 | not tested if POSIX doesn't specify exact binary values for all | |
67 | flags, and so any value passed to flags may become valid. | |
68 | ||
69 | Some tests assume "/bin/sh" names a file that exists and is not a | |
70 | directory. */ | |
71 | ||
ef11081f FW |
72 | /* Evalutes to the arguments in a list initializer which can be used |
73 | as a single macro argument. */ | |
74 | #define LIST(...) { __VA_ARGS__ } | |
75 | ||
76 | /* This macro is necessary to forward the output of LIST as a macro | |
77 | argument. */ | |
78 | #define LIST_FORWARD(...) __VA_ARGS__ | |
79 | ||
80 | /* Return true if CODE is contained in the array [CODES, CODES + | |
81 | COUNT]. */ | |
82 | static bool | |
83 | check_error_in_list (int code, int *codes, size_t count) | |
84 | { | |
85 | for (size_t i = 0; i < count; ++i) | |
86 | if (codes[i] == code) | |
87 | return true; | |
88 | return false; | |
89 | } | |
90 | ||
91 | #define test_wrp_rv(rtype, prtype, experr_list, syscall, ...) \ | |
9a56f871 YN |
92 | (__extension__ ({ \ |
93 | errno = 0xdead; \ | |
ef11081f | 94 | int experr[] = experr_list; \ |
9a56f871 YN |
95 | rtype ret = syscall (__VA_ARGS__); \ |
96 | int err = errno; \ | |
97 | int fail; \ | |
ef11081f FW |
98 | if ((ret == (rtype) -1) \ |
99 | && check_error_in_list (err, experr, array_length (experr))) \ | |
9a56f871 YN |
100 | fail = 0; \ |
101 | else \ | |
102 | { \ | |
103 | fail = 1; \ | |
104 | if (ret != (rtype) -1) \ | |
105 | printf ("FAIL: " #syscall ": didn't fail as expected" \ | |
b36a65e5 | 106 | " (return "prtype")\n", ret); \ |
9a56f871 | 107 | else if (err == 0xdead) \ |
b36a65e5 | 108 | puts ("FAIL: " #syscall ": didn't update errno"); \ |
ef11081f | 109 | else \ |
9a56f871 | 110 | printf ("FAIL: " #syscall \ |
ef11081f FW |
111 | ": errno is: %d (%s) expected one of %s\n", \ |
112 | err, strerror (err), #experr_list); \ | |
9a56f871 YN |
113 | } \ |
114 | fail; \ | |
115 | })) | |
116 | ||
117 | #define test_wrp(experr, syscall, ...) \ | |
ef11081f | 118 | test_wrp_rv(int, "%d", LIST (experr), syscall, __VA_ARGS__) |
9a56f871 | 119 | |
ef11081f FW |
120 | #define test_wrp2(experr, syscall, ...) \ |
121 | test_wrp_rv(int, "%d", LIST_FORWARD (experr), syscall, __VA_ARGS__) | |
b36a65e5 | 122 | |
9a56f871 YN |
123 | static int |
124 | do_test (void) | |
125 | { | |
126 | fd_set rs, ws, es; | |
127 | int status; | |
128 | off_t off; | |
129 | stack_t ss; | |
130 | struct dqblk dqblk; | |
131 | struct epoll_event epoll_event; | |
132 | struct pollfd pollfd; | |
133 | struct sched_param sch_param; | |
134 | struct timespec ts; | |
135 | struct timeval tv; | |
136 | unsigned char vec[16]; | |
137 | ss.ss_flags = ~SS_DISABLE; | |
138 | ts.tv_sec = -1; | |
139 | ||
140 | int fails = 0; | |
141 | fails |= test_wrp (EINVAL, epoll_create, -1); | |
142 | fails |= test_wrp (EINVAL, epoll_create1, EPOLL_CLOEXEC + 1); | |
143 | fails |= test_wrp (EBADF, epoll_ctl, -1, EPOLL_CTL_ADD, 0, &epoll_event); | |
144 | fails |= test_wrp (EBADF, epoll_wait, -1, &epoll_event, 1, 1); | |
145 | fails |= test_wrp (EBADF, fdatasync, -1); | |
146 | fails |= test_wrp (EBADF, flock, -1, LOCK_SH); | |
147 | fails |= test_wrp (ESRCH, getpgid, -1); | |
2183741f AZ |
148 | /* Linux v3.8 (676a0675c) removed the test to check at least one valid |
149 | bit in flags (to return EINVAL). It was later added back in v3.9 | |
150 | (04df32fa1). */ | |
ef11081f | 151 | fails |= test_wrp2 (LIST (EINVAL, EBADF), inotify_add_watch, -1, "/", 0); |
9a56f871 | 152 | fails |= test_wrp (EINVAL, mincore, (void *) -1, 0, vec); |
b36a65e5 AZ |
153 | /* mlock fails if the result of the addition addr+len was less than addr |
154 | (which indicates final address overflow), however on 32 bits binaries | |
155 | running on 64 bits kernels, internal syscall address check won't result | |
156 | in an invalid address and thus syscalls fails later in vma | |
157 | allocation. */ | |
ef11081f | 158 | fails |= test_wrp2 (LIST (EINVAL, ENOMEM), mlock, (void *) -1, 1); |
9a56f871 YN |
159 | fails |= test_wrp (EINVAL, nanosleep, &ts, &ts); |
160 | fails |= test_wrp (EINVAL, poll, &pollfd, -1, 0); | |
ef11081f FW |
161 | /* quotactl returns ENOSYS for kernels not configured with |
162 | CONFIG_QUOTA, and may return EPERM if called within certain types | |
163 | of containers. */ | |
164 | fails |= test_wrp2 (LIST (ENODEV, ENOSYS, EPERM), | |
165 | quotactl, Q_GETINFO, NULL, -1, (caddr_t) &dqblk); | |
9a56f871 YN |
166 | fails |= test_wrp (EINVAL, sched_getparam, -1, &sch_param); |
167 | fails |= test_wrp (EINVAL, sched_getscheduler, -1); | |
168 | fails |= test_wrp (EINVAL, sched_get_priority_max, -1); | |
169 | fails |= test_wrp (EINVAL, sched_get_priority_min, -1); | |
170 | fails |= test_wrp (EINVAL, sched_rr_get_interval, -1, &ts); | |
171 | fails |= test_wrp (EINVAL, sched_setparam, -1, &sch_param); | |
172 | fails |= test_wrp (EINVAL, sched_setscheduler, -1, 0, &sch_param); | |
173 | fails |= test_wrp (EINVAL, select, -1, &rs, &ws, &es, &tv); | |
174 | fails |= test_wrp (EBADF, sendfile, -1, -1, &off, 0); | |
175 | fails |= test_wrp (EINVAL, sigaltstack, &ss, NULL); | |
176 | fails |= test_wrp (ECHILD, wait4, -1, &status, 0, NULL); | |
177 | ||
178 | return fails; | |
179 | } | |
180 | ||
181 | #include "support/test-driver.c" |