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 (at) 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 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 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 194 void setup(void) 195 { 196 tst_require_root(); 197 198 tst_sig(FORK, DEF_HANDLER, cleanup); 199 200 TEST_PAUSE; 201 } 202 203 void cleanup(void) 204 { 205 } 206 207 #else 208 int TST_TOTAL = 0; 209 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