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 * sysctl03.c
23 *
24 * DESCRIPTION
25 * Testcase to check that sysctl(2) sets errno to EPERM correctly.
26 *
27 * ALGORITHM
28 * a. Call sysctl(2) as a root user, and attempt to write data
29 * to the kernel_table[]. Since the table does not have write
30 * permissions even for the root, it should fail EPERM.
31 * b. Call sysctl(2) as a non-root user, and attempt to write data
32 * to the kernel_table[]. Since the table does not have write
33 * permission for the regular user, it should fail with EPERM.
34 *
35 * NOTE: There is a documentation bug in 2.6.33-rc1 where unfortunately the
36 * behavior of sysctl(2) isn't properly documented, as discussed in detail in
37 * the following thread:
38 * http://sourceforge.net/mailarchive/message.php?msg_name=4B7BA24F.2010705%40linux.vnet.ibm.com.
39 *
40 * The documentation bug is filed as:
41 * https://bugzilla.kernel.org/show_bug.cgi?id=15446 . If you want the message
42 * removed, please ask your fellow kernel maintainer to fix his/her
43 * documentation.
44 *
45 * Thanks!
46 * -Garrett
47 *
48 * USAGE: <for command-line>
49 * sysctl03 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
50 * where, -c n : Run n copies concurrently.
51 * -e : Turn on errno logging.
52 * -i n : Execute test n times.
53 * -I x : Execute test for x seconds.
54 * -P x : Pause for x seconds between iterations.
55 * -t : Turn on syscall timing.
56 *
57 * HISTORY
58 * 07/2001 Ported by Wayne Boyer
59 * 02/2010 Updated by shiwh@cn.fujitsu.com
60 *
61 * RESTRICTIONS
62 * Test must be run as root.
63 */
64 #include "test.h"
65 #include <sys/types.h>
66 #include <sys/wait.h>
67 #include <stdio.h>
68 #include <errno.h>
69 #include <unistd.h>
70 #include <linux/unistd.h>
71 #include <linux/sysctl.h>
72 #include <pwd.h>
73
74 char *TCID = "sysctl03";
75
76 /* This is an older/deprecated syscall that newer arches are omitting */
77 #ifdef __NR_sysctl
78
79 int TST_TOTAL = 2;
80
sysctl(int * name,int nlen,void * oldval,size_t * oldlenp,void * newval,size_t newlen)81 int sysctl(int *name, int nlen, void *oldval, size_t * oldlenp,
82 void *newval, size_t newlen)
83 {
84 struct __sysctl_args args =
85 { name, nlen, oldval, oldlenp, newval, newlen };
86 return syscall(__NR__sysctl, &args);
87 }
88
89 #define OSNAMESZ 100
90
91 void setup(void);
92 void cleanup(void);
93
main(int ac,char ** av)94 int main(int ac, char **av)
95 {
96 int exp_eno;
97 int lc;
98
99 char osname[OSNAMESZ];
100 int osnamelth, status;
101 int name[] = { CTL_KERN, KERN_OSTYPE };
102 pid_t pid;
103 struct passwd *ltpuser;
104
105 tst_parse_opts(ac, av, NULL, NULL);
106
107 setup();
108
109 if ((tst_kvercmp(2, 6, 32)) <= 0) {
110 exp_eno = EPERM;
111 } else {
112 /* ^^ Look above this warning. ^^ */
113 tst_resm(TINFO,
114 "this test's results are based on potentially undocumented behavior in the kernel. read the NOTE in the source file for more details");
115 exp_eno = EACCES;
116 exp_enos[0] = EACCES;
117 }
118
119 for (lc = 0; TEST_LOOPING(lc); lc++) {
120
121 /* reset tst_count in case we are looping */
122 tst_count = 0;
123
124 strcpy(osname, "Linux");
125 osnamelth = sizeof(osname);
126
127 TEST(sysctl(name, ARRAY_SIZE(name), 0, 0, osname, osnamelth));
128
129 if (TEST_RETURN != -1) {
130 tst_resm(TFAIL, "sysctl(2) succeeded unexpectedly");
131 } else {
132 if (TEST_ERRNO == exp_eno) {
133 tst_resm(TPASS | TTERRNO, "Got expected error");
134 } else if (errno == ENOSYS) {
135 tst_resm(TCONF,
136 "You may need to make CONFIG_SYSCTL_SYSCALL=y"
137 " to your kernel config.");
138 } else {
139 tst_resm(TFAIL | TTERRNO,
140 "Got unexpected error");
141 }
142 }
143
144 osnamelth = sizeof(osname);
145 if ((ltpuser = getpwnam("nobody")) == NULL) {
146 tst_brkm(TBROK, cleanup, "getpwnam() failed");
147 }
148
149 /* set process ID to "ltpuser1" */
150 if (seteuid(ltpuser->pw_uid) == -1) {
151 tst_brkm(TBROK, cleanup,
152 "seteuid() failed, errno %d", errno);
153 }
154
155 if ((pid = FORK_OR_VFORK()) == -1) {
156 tst_brkm(TBROK, cleanup, "fork() failed");
157 }
158
159 if (pid == 0) {
160 TEST(sysctl(name, ARRAY_SIZE(name), 0, 0, osname, osnamelth));
161
162 if (TEST_RETURN != -1) {
163 tst_resm(TFAIL, "call succeeded unexpectedly");
164 } else {
165 if (TEST_ERRNO == exp_eno) {
166 tst_resm(TPASS | TTERRNO,
167 "Got expected error");
168 } else if (TEST_ERRNO == ENOSYS) {
169 tst_resm(TCONF,
170 "You may need to make CONFIG_SYSCTL_SYSCALL=y"
171 " to your kernel config.");
172 } else {
173 tst_resm(TFAIL | TTERRNO,
174 "Got unexpected error");
175 }
176 }
177
178 cleanup();
179
180 } else {
181 /* wait for the child to finish */
182 wait(&status);
183 }
184
185 /* set process ID back to root */
186 if (seteuid(0) == -1) {
187 tst_brkm(TBROK, cleanup, "seteuid() failed");
188 }
189 }
190 cleanup();
191 tst_exit();
192 }
193
setup(void)194 void setup(void)
195 {
196 tst_require_root();
197
198 tst_sig(FORK, DEF_HANDLER, cleanup);
199
200 TEST_PAUSE;
201 }
202
cleanup(void)203 void cleanup(void)
204 {
205 }
206
207 #else
208 int TST_TOTAL = 0;
209
main(void)210 int main(void)
211 {
212
213 tst_brkm(TCONF, NULL,
214 "This test needs a kernel that has sysctl syscall.");
215 }
216 #endif
217