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