1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * NAME
22 * sysctl05.c
23 *
24 * DESCRIPTION
25 * Testcase to check that sysctl(2) sets errno to EFAULT
26 *
27 * ALGORITHM
28 * 1. Call sysctl(2) with the address of sc_oldname outside the address
29 * space of the process, and expect EFAULT.
30 * 2. Call sysctl(2) with the address of sc_oldval outside the address
31 * space of the process, and expect EFAULT.
32 *
33 * USAGE: <for command-line>
34 * sysctl05 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
35 * where, -c n : Run n copies concurrently.
36 * -e : Turn on errno logging.
37 * -i n : Execute test n times.
38 * -I x : Execute test for x seconds.
39 * -P x : Pause for x seconds between iterations.
40 * -t : Turn on syscall timing.
41 *
42 * HISTORY
43 * 07/2001 Ported by Wayne Boyer
44 *
45 * RESTRICTIONS
46 * None
47 */
48
49 #include "test.h"
50 #include <stdio.h>
51 #include <unistd.h>
52 #include <linux/unistd.h>
53 #include <linux/sysctl.h>
54 #include <linux/version.h>
55 #include <errno.h>
56
57 char *TCID = "sysctl05";
58
59 /* This is an older/deprecated syscall that newer arches are omitting */
60 #ifdef __NR_sysctl
61
62 int TST_TOTAL = 2;
63
sysctl(int * name,int nlen,void * oldval,size_t * oldlenp,void * newval,size_t newlen)64 int sysctl(int *name, int nlen, void *oldval, size_t * oldlenp,
65 void *newval, size_t newlen)
66 {
67 struct __sysctl_args args =
68 { name, nlen, oldval, oldlenp, newval, newlen };
69 return syscall(__NR__sysctl, &args);
70 }
71
72 char osname[BUFSIZ];
73 size_t osnamelth;
74
75 void setup(void);
76 void cleanup(void);
77
78 struct testcases {
79 char *desc;
80 int name[2];
81 int size;
82 void *oldval;
83 size_t *oldlen;
84 void *newval;
85 int newlen;
86 int (*cleanup) ();
87 int exp_retval;
88 int exp_errno;
89 } testcases[] = {
90 {
91 "Test for EFAULT: invalid oldlen", {
92 CTL_KERN, KERN_OSRELEASE},
93 2, osname, (void *)-1, NULL, 0, NULL, -1, EFAULT}, {
94 "Test for EFAULT: invalid oldval", {
95 CTL_KERN, KERN_VERSION},
96 2, (void *)-1, &osnamelth, NULL, 0, NULL, -1, EFAULT}
97 };
98
99 #if !defined(UCLINUX)
100
main(int ac,char ** av)101 int main(int ac, char **av)
102 {
103 int lc;
104 int i;
105 int ret = 0;
106
107 tst_parse_opts(ac, av, NULL, NULL);
108
109 setup();
110
111 for (lc = 0; TEST_LOOPING(lc); lc++) {
112
113 /* reset tst_count in case we are looping */
114 tst_count = 0;
115
116 for (i = 0; i < TST_TOTAL; ++i) {
117
118 osnamelth = sizeof(osname);
119
120 TEST(sysctl(testcases[i].name, testcases[i].size,
121 testcases[i].oldval, testcases[i].oldlen,
122 testcases[i].newval, testcases[i].newlen));
123
124 if (TEST_RETURN != testcases[i].exp_retval) {
125 tst_resm(TFAIL, "sysctl(2) returned unexpected "
126 "retval, expected: %d, got: %d",
127 testcases[i].exp_retval, ret);
128 continue;
129 }
130
131 if (TEST_ERRNO == ENOSYS) {
132 tst_resm(TCONF,
133 "You may need to make CONFIG_SYSCTL_SYSCALL=y"
134 " to your kernel config.");
135 } else if (TEST_ERRNO != testcases[i].exp_errno) {
136 tst_resm(TFAIL, "sysctl(2) returned unexpected "
137 "errno, expected: %d, got: %d",
138 testcases[i].exp_errno, errno);
139 } else {
140 tst_resm(TPASS, "sysctl(2) set errno correctly "
141 "to %d", testcases[i].exp_errno);
142 }
143
144 if (testcases[i].cleanup) {
145 (void)testcases[i].cleanup();
146 }
147 }
148 }
149 cleanup();
150
151 tst_exit();
152 }
153
154 #else
155
main(void)156 int main(void)
157 {
158 tst_resm(TINFO, "test is not available on uClinux");
159 tst_exit();
160 }
161
162 #endif /* if !defined(UCLINUX) */
163
164 /*
165 * setup() - performs all ONE TIME setup for this test.
166 */
setup(void)167 void setup(void)
168 {
169
170 tst_sig(NOFORK, DEF_HANDLER, cleanup);
171
172 TEST_PAUSE;
173 }
174
175 /*
176 * cleanup() - performs all ONE TIME cleanup for this test at
177 * completion or premature exit.
178 */
cleanup(void)179 void cleanup(void)
180 {
181
182 }
183
184 #else
185 int TST_TOTAL = 0;
186
main(void)187 int main(void)
188 {
189
190 tst_brkm(TCONF, NULL,
191 "This test needs a kernel that has sysctl syscall.");
192 }
193 #endif
194