]>
Commit | Line | Data |
---|---|---|
9a56f871 | 1 | /* Test that failing system calls do set errno to the correct value. |
b36a65e5 | 2 | Linux sycalls version. |
9a56f871 YN |
3 | |
4 | Copyright (C) 2017 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 | <http://www.gnu.org/licenses/>. */ | |
20 | ||
21 | #include <errno.h> | |
22 | #include <fcntl.h> | |
23 | #include <mqueue.h> | |
24 | #include <sched.h> | |
25 | #include <signal.h> | |
26 | #include <stdio.h> | |
27 | #include <string.h> | |
28 | #include <time.h> | |
29 | #include <unistd.h> | |
30 | #include <sys/epoll.h> | |
31 | #include <sys/eventfd.h> | |
32 | #include <sys/file.h> | |
33 | #include <sys/fsuid.h> | |
34 | #include <sys/inotify.h> | |
35 | #include <sys/mman.h> | |
36 | #include <sys/poll.h> | |
37 | #include <sys/quota.h> | |
38 | #include <sys/resource.h> | |
39 | #include <sys/select.h> | |
40 | #include <sys/sendfile.h> | |
41 | #include <sys/swap.h> | |
42 | #include <sys/time.h> | |
43 | #include <sys/types.h> | |
44 | #include <sys/wait.h> | |
45 | ||
46 | /* This is not an exhaustive test: only system calls that can be | |
47 | persuaded to fail with a consistent error code and no side effects | |
48 | are included. Usually these are failures due to invalid arguments, | |
49 | with errno code EBADF or EINVAL. The order of argument checks is | |
50 | unspecified, so we must take care to provide arguments that only | |
51 | allow _one_ failure mode. | |
52 | ||
53 | Note that all system calls that can fail with EFAULT are permitted | |
54 | to deliver a SIGSEGV signal instead, so we avoid supplying invalid | |
55 | pointers in general, and we do not attempt to test system calls | |
56 | that can only fail with EFAULT (e.g. gettimeofday, gethostname). | |
57 | ||
58 | Also note that root-only system calls (e.g. acct, reboot) may, when | |
59 | the test is run as an unprivileged user, fail due to insufficient | |
60 | privileges before bothering to do argument checks, so those are not | |
61 | tested either. | |
62 | ||
63 | Also, system calls that take enum or a set of flags as argument is | |
64 | not tested if POSIX doesn't specify exact binary values for all | |
65 | flags, and so any value passed to flags may become valid. | |
66 | ||
67 | Some tests assume "/bin/sh" names a file that exists and is not a | |
68 | directory. */ | |
69 | ||
70 | #define test_wrp_rv(rtype, prtype, experr, syscall, ...) \ | |
71 | (__extension__ ({ \ | |
72 | errno = 0xdead; \ | |
73 | rtype ret = syscall (__VA_ARGS__); \ | |
74 | int err = errno; \ | |
75 | int fail; \ | |
b36a65e5 | 76 | if ((ret == (rtype) -1) && (err == experr)) \ |
9a56f871 YN |
77 | fail = 0; \ |
78 | else \ | |
79 | { \ | |
80 | fail = 1; \ | |
81 | if (ret != (rtype) -1) \ | |
82 | printf ("FAIL: " #syscall ": didn't fail as expected" \ | |
b36a65e5 | 83 | " (return "prtype")\n", ret); \ |
9a56f871 | 84 | else if (err == 0xdead) \ |
b36a65e5 | 85 | puts ("FAIL: " #syscall ": didn't update errno"); \ |
9a56f871 YN |
86 | else if (err != experr) \ |
87 | printf ("FAIL: " #syscall \ | |
b36a65e5 AZ |
88 | ": errno is: %d (%s) expected: %d (%s)\n", \ |
89 | err, strerror (err), experr, strerror (experr));\ | |
9a56f871 YN |
90 | } \ |
91 | fail; \ | |
92 | })) | |
93 | ||
b36a65e5 AZ |
94 | #define test_wrp_rv2(rtype, prtype, experr1, experr2, syscall, ...) \ |
95 | (__extension__ ({ \ | |
96 | errno = 0xdead; \ | |
97 | rtype ret = syscall (__VA_ARGS__); \ | |
98 | int err = errno; \ | |
99 | int fail; \ | |
100 | if ((ret == (rtype) -1) && ((err == experr1) || (err == experr2))) \ | |
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 if (err != experr1 && err != experr2) \ | |
111 | printf ("FAIL: " #syscall \ | |
112 | ": errno is: %d (%s) expected: %d (%s) or %d (%s)\n", \ | |
113 | err, strerror (err), experr1, strerror (experr1), \ | |
114 | experr2, strerror (experr2)); \ | |
115 | } \ | |
116 | fail; \ | |
117 | })) | |
118 | ||
9a56f871 YN |
119 | #define test_wrp(experr, syscall, ...) \ |
120 | test_wrp_rv(int, "%d", experr, syscall, __VA_ARGS__) | |
121 | ||
b36a65e5 AZ |
122 | #define test_wrp2(experr1, experr2, syscall, ...) \ |
123 | test_wrp_rv2(int, "%d", experr1, experr2, syscall, __VA_ARGS__) | |
124 | ||
9a56f871 YN |
125 | static int |
126 | do_test (void) | |
127 | { | |
128 | fd_set rs, ws, es; | |
129 | int status; | |
130 | off_t off; | |
131 | stack_t ss; | |
132 | struct dqblk dqblk; | |
133 | struct epoll_event epoll_event; | |
134 | struct pollfd pollfd; | |
135 | struct sched_param sch_param; | |
136 | struct timespec ts; | |
137 | struct timeval tv; | |
138 | unsigned char vec[16]; | |
139 | ss.ss_flags = ~SS_DISABLE; | |
140 | ts.tv_sec = -1; | |
141 | ||
142 | int fails = 0; | |
143 | fails |= test_wrp (EINVAL, epoll_create, -1); | |
144 | fails |= test_wrp (EINVAL, epoll_create1, EPOLL_CLOEXEC + 1); | |
145 | fails |= test_wrp (EBADF, epoll_ctl, -1, EPOLL_CTL_ADD, 0, &epoll_event); | |
146 | fails |= test_wrp (EBADF, epoll_wait, -1, &epoll_event, 1, 1); | |
147 | fails |= test_wrp (EBADF, fdatasync, -1); | |
148 | fails |= test_wrp (EBADF, flock, -1, LOCK_SH); | |
149 | fails |= test_wrp (ESRCH, getpgid, -1); | |
2183741f AZ |
150 | /* Linux v3.8 (676a0675c) removed the test to check at least one valid |
151 | bit in flags (to return EINVAL). It was later added back in v3.9 | |
152 | (04df32fa1). */ | |
153 | fails |= test_wrp2 (EINVAL, EBADF, inotify_add_watch, -1, "/", 0); | |
9a56f871 | 154 | fails |= test_wrp (EINVAL, mincore, (void *) -1, 0, vec); |
b36a65e5 AZ |
155 | /* mlock fails if the result of the addition addr+len was less than addr |
156 | (which indicates final address overflow), however on 32 bits binaries | |
157 | running on 64 bits kernels, internal syscall address check won't result | |
158 | in an invalid address and thus syscalls fails later in vma | |
159 | allocation. */ | |
160 | fails |= test_wrp2 (EINVAL, ENOMEM, mlock, (void *) -1, 1); | |
9a56f871 YN |
161 | fails |= test_wrp (EINVAL, nanosleep, &ts, &ts); |
162 | fails |= test_wrp (EINVAL, poll, &pollfd, -1, 0); | |
2183741f AZ |
163 | /* quotactl returns ENOSYS for kernels not configured with CONFIG_QUOTA. */ |
164 | fails |= test_wrp2 (ENODEV, ENOSYS, quotactl, Q_GETINFO, NULL, -1, | |
165 | (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" |