1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2004 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 * hugeshmctl03.c 23 * 24 * DESCRIPTION 25 * hugeshmctl03 - check for EACCES, and EPERM errors 26 * 27 * ALGORITHM 28 * create a large shared memory segment with root only read & write 29 * permissions fork a child process 30 * if child 31 * set the ID of the child process to that of "ltpuser1" 32 * call do_child() 33 * loop if that option was specified 34 * call shmctl() using three different invalid cases 35 * check the errno value 36 * issue a PASS message if we get EACCES or EPERM 37 * otherwise, the tests fails 38 * issue a FAIL message 39 * call cleanup 40 * if parent 41 * wait for child to exit 42 * remove the large shared memory segment 43 * 44 * USAGE: <for command-line> 45 * hugeshmctl03 [-c n] [-e] [-i n] [-I x] [-P x] [-t] 46 * where, -c n : Run n copies concurrently. 47 * -e : Turn on errno logging. 48 * -i n : Execute test n times. 49 * -I x : Execute test for x seconds. 50 * -P x : Pause for x seconds between iterations. 51 * -t : Turn on syscall timing. 52 * 53 * HISTORY 54 * 03/2001 - Written by Wayne Boyer 55 * 04/2004 - Updated by Robbie Williamson 56 * 57 * RESTRICTIONS 58 * test must be run as root 59 */ 60 61 #include <sys/types.h> 62 #include <sys/wait.h> 63 #include "test.h" 64 #include "safe_macros.h" 65 #include "mem.h" 66 #include "hugetlb.h" 67 68 char *TCID = "hugeshmctl03"; 69 int TST_TOTAL = 3; 70 71 static size_t shm_size; 72 static int shm_id_1 = -1; 73 static struct shmid_ds buf; 74 static uid_t ltp_uid; 75 static char *ltp_user = "nobody"; 76 77 static long hugepages = 128; 78 static option_t options[] = { 79 {"s:", &sflag, &nr_opt}, 80 {NULL, NULL, NULL} 81 }; 82 83 struct test_case_t { 84 int *shmid; 85 int cmd; 86 struct shmid_ds *sbuf; 87 int error; 88 } TC[] = { 89 /* EACCES - child has no read permission for segment */ 90 { 91 &shm_id_1, IPC_STAT, &buf, EACCES}, 92 /* EPERM - IPC_SET - child doesn't have permission to change segment */ 93 { 94 &shm_id_1, IPC_SET, &buf, EPERM}, 95 /* EPERM - IPC_RMID - child can not remove the segment */ 96 { 97 &shm_id_1, IPC_RMID, &buf, EPERM},}; 98 99 static void do_child(void); 100 101 int main(int ac, char **av) 102 { 103 pid_t pid; 104 int status; 105 106 tst_parse_opts(ac, av, options, NULL); 107 108 if (sflag) 109 hugepages = SAFE_STRTOL(NULL, nr_opt, 0, LONG_MAX); 110 111 setup(); 112 113 switch (pid = fork()) { 114 case -1: 115 tst_brkm(TBROK | TERRNO, cleanup, "fork"); 116 case 0: 117 /* set the user ID of the child to the non root user */ 118 if (setuid(ltp_uid) == -1) 119 tst_brkm(TBROK | TERRNO, cleanup, "setuid"); 120 do_child(); 121 tst_exit(); 122 default: 123 if (waitpid(pid, &status, 0) == -1) 124 tst_brkm(TBROK | TERRNO, cleanup, "waitpid"); 125 } 126 cleanup(); 127 tst_exit(); 128 } 129 130 static void do_child(void) 131 { 132 int i, lc; 133 134 for (lc = 0; TEST_LOOPING(lc); lc++) { 135 tst_count = 0; 136 137 for (i = 0; i < TST_TOTAL; i++) { 138 TEST(shmctl(*(TC[i].shmid), TC[i].cmd, TC[i].sbuf)); 139 if (TEST_RETURN != -1) { 140 tst_resm(TFAIL, "shmctl succeeded " 141 "unexpectedly"); 142 continue; 143 } 144 if (TEST_ERRNO == TC[i].error) 145 tst_resm(TPASS | TTERRNO, "shmctl failed " 146 "as expected"); 147 else 148 tst_resm(TFAIL | TTERRNO, "shmctl failed " 149 "unexpectedly - expect errno = " 150 "%d, got", TC[i].error); 151 } 152 } 153 } 154 155 void setup(void) 156 { 157 long hpage_size; 158 159 tst_require_root(); 160 check_hugepage(); 161 tst_sig(FORK, DEF_HANDLER, cleanup); 162 tst_tmpdir(); 163 164 orig_hugepages = get_sys_tune("nr_hugepages"); 165 set_sys_tune("nr_hugepages", hugepages, 1); 166 hpage_size = read_meminfo("Hugepagesize:") * 1024; 167 168 shm_size = hpage_size * hugepages / 2; 169 update_shm_size(&shm_size); 170 shmkey = getipckey(cleanup); 171 shm_id_1 = shmget(shmkey, shm_size, 172 SHM_HUGETLB | IPC_CREAT | IPC_EXCL | SHM_RW); 173 if (shm_id_1 == -1) 174 tst_brkm(TBROK | TERRNO, cleanup, "shmget"); 175 176 /* get the userid for a non root user */ 177 ltp_uid = getuserid(cleanup, ltp_user); 178 179 TEST_PAUSE; 180 } 181 182 void cleanup(void) 183 { 184 rm_shm(shm_id_1); 185 186 set_sys_tune("nr_hugepages", orig_hugepages, 0); 187 188 tst_rmdir(); 189 } 190