Home | History | Annotate | Download | only in sysctl
      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