Home | History | Annotate | Download | only in adjtimex
      1 /*
      2  * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
      3  *
      4  * This program is free software; you can redistribute it and/or modify it
      5  * under the terms of version 2 of the GNU General Public License as
      6  * published by the Free Software Foundation.
      7  *
      8  * This program is distributed in the hope that it would be useful, but
      9  * WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     11  *
     12  * You should have received a copy of the GNU General Public License along
     13  * with this program; if not, write the Free Software Foundation, Inc.,
     14  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     15  *
     16  */
     17 /**********************************************************
     18  *
     19  *    TEST IDENTIFIER	: adjtimex02
     20  *
     21  *    EXECUTED BY	: root / superuser
     22  *
     23  *    TEST TITLE	: Tests for error conditions
     24  *
     25  *    TEST CASE TOTAL	: 6
     26  *
     27  *    AUTHOR		: Saji Kumar.V.R <saji.kumar (at) wipro.com>
     28  *
     29  *    SIGNALS
     30  * 	Uses SIGUSR1 to pause before test if option set.
     31  * 	(See the parse_opts(3) man page).
     32  *
     33  *    DESCRIPTION
     34  *	Verify that
     35  *	1) adjtimex(2) fails with errno set to EFAULT if buf does
     36  *	   not point to writable memory
     37  *	2) adjtimex(2) fails with errno set to EINVAL if an attempt
     38  *	   is  made  to set buf.tick to a value < 900000/HZ
     39  *	3) adjtimex(2) fails with errno set to EINVAL if an attempt
     40  *	   is  made  to set buf.tick to a value > 1100000/HZ
     41  *	4) adjtimex(2) fails with errno set to EINVAL if an attempt
     42  *	   is  made  to set buf.offset to a value > 512000L
     43  *	   (This test case will be executed only if the kernel version
     44  *	    is 2.6.25 or below)
     45  *	5) adjtimex(2) fails with errno set to EINVAL if an attempt
     46  *	   is  made  to set buf.offset to a value < 512000L
     47  *	   (This test case will be executed only if the kernel version
     48  *	    is 2.6.25 or below)
     49  *	6) adjtimex(2) fails with errno set to EPERM if buf.mode is
     50  *	   non-zero and the user is not super-user.
     51  *
     52  * 	Setup:
     53  * 	  Setup signal handling.
     54  *	  Pause for SIGUSR1 if option specified.
     55  *	  Save current parameters in tim_save
     56  *
     57  * 	Test:
     58  *	 Loop if the proper options are given.
     59  *	  Call test case specific setup if needed
     60  * 	  call adjtimex with saved timex structure
     61  *	  Check return value is between 0 & 5
     62  *		Test passed
     63  *	  Otherwise
     64  *		Test failed
     65  *	  Call test case specific cleanup if needed
     66  *
     67  * 	Cleanup:
     68  * 	  Print errno log and/or timing stats if options given
     69  *
     70  * USAGE:  <for command-line>
     71  * adjtimex02 [-c n] [-e] [-i n] [-I x] [-P x] [-t] [-h] [-f] [-p]
     72  *			where,  -c n : Run n copies concurrently.
     73  *				-e   : Turn on errno logging.
     74  *				-h   : Show help screen
     75  *				-f   : Turn off functional testing
     76  *				-i n : Execute test n times.
     77  *				-I x : Execute test for x seconds.
     78  *				-p   : Pause for SIGUSR1 before starting
     79  *				-P x : Pause for x seconds between iterations.
     80  *				-t   : Turn on syscall timing.
     81  *
     82  ****************************************************************/
     83 
     84 #if defined UCLINUX && !__THROW
     85 /* workaround for libc bug causing failure in sys/timex.h */
     86 #define __THROW
     87 #endif
     88 
     89 #include <errno.h>
     90 #include <sys/timex.h>
     91 #include <unistd.h>
     92 #include <pwd.h>
     93 #include "test.h"
     94 #include "safe_macros.h"
     95 
     96 #define SET_MODE ( ADJ_OFFSET | ADJ_FREQUENCY | ADJ_MAXERROR | ADJ_ESTERROR | \
     97 	ADJ_STATUS | ADJ_TIMECONST | ADJ_TICK )
     98 
     99 static void setup(void);
    100 static int setup2(void);
    101 static int setup3(void);
    102 static int setup4(void);
    103 static int setup5(void);
    104 static int setup6(void);
    105 static void cleanup(void);
    106 static void cleanup6(void);
    107 
    108 char *TCID = "adjtimex02";
    109 
    110 static int hz;			/* HZ from sysconf */
    111 
    112 static struct timex tim_save;
    113 static struct timex buff;
    114 
    115 static char nobody_uid[] = "nobody";
    116 struct passwd *ltpuser;
    117 
    118 struct test_cases_t {
    119 	struct timex *buffp;
    120 	int (*setup) ();
    121 	void (*cleanup) ();
    122 	int exp_errno;
    123 } test_cases[] = {
    124 #ifndef UCLINUX
    125 	/* Skip since uClinux does not implement memory protection */
    126 	{
    127 	(struct timex *)-1, NULL, NULL, EFAULT},
    128 #endif
    129 	{
    130 	&buff, setup2, NULL, EINVAL}, {
    131 	&buff, setup3, NULL, EINVAL}, {
    132 	&buff, setup4, NULL, EINVAL}, {
    133 	&buff, setup5, NULL, EINVAL}, {
    134 	&buff, setup6, cleanup6, EPERM}
    135 };
    136 
    137 int TST_TOTAL = sizeof(test_cases) / sizeof(test_cases[0]);
    138 
    139 int main(int ac, char **av)
    140 {
    141 
    142 	int lc, i;
    143 
    144 	tst_parse_opts(ac, av, NULL, NULL);
    145 
    146 	setup();
    147 
    148 	for (lc = 0; TEST_LOOPING(lc); lc++) {
    149 
    150 		tst_count = 0;
    151 
    152 		for (i = 0; i < TST_TOTAL; ++i) {
    153 			/*
    154 			 * since Linux 2.6.26, if buf.offset value is outside
    155 			 * the acceptable range, it is simply normalized instead
    156 			 * of letting the syscall fail. so just skip this test
    157 			 * case.
    158 			 */
    159 			if ((i == 3 || i == 4) && tst_kvercmp(2, 6, 25) > 0) {
    160 				tst_resm(TCONF, "this kernel normalizes buf."
    161 					 "offset value if it is outside"
    162 					 " the acceptable range.");
    163 				continue;
    164 			}
    165 
    166 			buff = tim_save;
    167 			buff.modes = SET_MODE;
    168 			if ((test_cases[i].setup) && (test_cases[i].setup())) {
    169 				tst_resm(TWARN, "setup() failed, skipping"
    170 					 " this test case");
    171 				continue;
    172 			}
    173 
    174 			/* Call adjtimex(2) */
    175 			TEST(adjtimex(test_cases[i].buffp));
    176 
    177 			if ((TEST_RETURN == -1) && (TEST_ERRNO ==
    178 						    test_cases[i].exp_errno)) {
    179 				tst_resm(TPASS | TTERRNO,
    180 					 "Test Passed, adjtimex() returned -1");
    181 			} else {
    182 				tst_resm(TFAIL | TTERRNO,
    183 					 "Test Failed, adjtimex() returned %ld",
    184 					 TEST_RETURN);
    185 			}
    186 			if (test_cases[i].cleanup) {
    187 				test_cases[i].cleanup();
    188 			}
    189 		}
    190 	}
    191 
    192 	/* cleanup and exit */
    193 	cleanup();
    194 
    195 	tst_exit();
    196 
    197 }
    198 
    199 /* setup() - performs all ONE TIME setup for this test */
    200 void setup(void)
    201 {
    202 	tst_require_root();
    203 
    204 	tim_save.modes = 0;
    205 
    206 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
    207 
    208 	/* set the HZ from sysconf */
    209 	hz = SAFE_SYSCONF(NULL, _SC_CLK_TCK);
    210 
    211 	TEST_PAUSE;
    212 
    213 	/* Save current parameters in tim_save */
    214 	if ((adjtimex(&tim_save)) == -1) {
    215 		tst_brkm(TBROK, NULL, "Failed to save current parameters");
    216 	}
    217 }
    218 
    219 /*
    220  *cleanup() -  performs all ONE TIME cleanup for this test at
    221  *		completion or premature exit.
    222  */
    223 void cleanup(void)
    224 {
    225 
    226 	tim_save.modes = SET_MODE;
    227 	/* Restore saved parameters */
    228 	if ((adjtimex(&tim_save)) == -1) {
    229 		tst_resm(TWARN, "Failed to restore saved parameters");
    230 	}
    231 }
    232 
    233 int setup2(void)
    234 {
    235 	buff.tick = 900000 / hz - 1;
    236 	return 0;
    237 }
    238 
    239 int setup3(void)
    240 {
    241 	buff.tick = 1100000 / hz + 1;
    242 	return 0;
    243 }
    244 
    245 int setup4(void)
    246 {
    247 	buff.offset = 512000L + 1;
    248 	return 0;
    249 }
    250 
    251 int setup5(void)
    252 {
    253 	buff.offset = (-1) * (512000L) - 1;
    254 	return 0;
    255 }
    256 
    257 int setup6(void)
    258 {
    259 	/* Switch to nobody user for correct error code collection */
    260 	if ((ltpuser = getpwnam(nobody_uid)) == NULL) {
    261 		tst_brkm(TBROK, NULL, "\"nobody\" user not present");
    262 	}
    263 	if (seteuid(ltpuser->pw_uid) == -1) {
    264 		tst_resm(TWARN | TERRNO, "seteuid(%d) failed", ltpuser->pw_uid);
    265 		return 1;
    266 	}
    267 	return 0;
    268 }
    269 
    270 void cleanup6(void)
    271 {
    272 	/* Set effective user id back to root */
    273 	SAFE_SETEUID(cleanup, 0);
    274 }
    275