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 * shmctl03.c
23 *
24 * DESCRIPTION
25 * shmctl03 - check for EACCES, and EPERM errors
26 *
27 * ALGORITHM
28 * create a shared memory segment with root only read & write permissions
29 * 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 shared memory segment
43 *
44 * USAGE: <for command-line>
45 * shmctl03 [-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 *
56 * RESTRICTIONS
57 * test must be run as root
58 */
59
60 #include "ipcshm.h"
61 #include <sys/types.h>
62 #include <sys/wait.h>
63 #include "safe_macros.h"
64
65 char *TCID = "shmctl03";
66 int shm_id_1 = -1;
67
68 uid_t ltp_uid;
69 char *ltp_user = "nobody";
70
71 struct shmid_ds buf;
72
73 struct test_case_t {
74 int *shmid;
75 int cmd;
76 struct shmid_ds *sbuf;
77 int error;
78 } TC[] = {
79 /* EACCES - child has no read permission for segment */
80 {
81 &shm_id_1, IPC_STAT, &buf, EACCES},
82 /* EPERM - IPC_SET - child doesn't have permission to change segment */
83 {
84 &shm_id_1, IPC_SET, &buf, EPERM},
85 /* EPERM - IPC_RMID - child can not remove the segment */
86 {
87 &shm_id_1, IPC_RMID, &buf, EPERM},};
88
89 int TST_TOTAL = ARRAY_SIZE(TC);
90
main(int ac,char ** av)91 int main(int ac, char **av)
92 {
93 int pid;
94 void do_child(void);
95
96 tst_parse_opts(ac, av, NULL, NULL);
97
98 setup(); /* global setup */
99
100 if ((pid = FORK_OR_VFORK()) == -1) {
101 tst_brkm(TBROK, cleanup, "could not fork");
102 }
103
104 if (pid == 0) { /* child */
105 /* set the user ID of the child to the non root user */
106 if (setuid(ltp_uid) == -1) {
107 tst_resm(TBROK, "setuid() failed");
108 exit(1);
109 }
110
111 do_child();
112 } else {
113 /* wait for the child to return */
114 SAFE_WAITPID(cleanup, pid, NULL, 0);
115
116 /* if it exists, remove the shared memory resource */
117 rm_shm(shm_id_1);
118
119 tst_rmdir();
120 }
121
122 cleanup();
123 tst_exit();
124 }
125
126 /*
127 * do_child - make the call as the child process
128 */
do_child(void)129 void do_child(void)
130 {
131 int i, lc;
132
133 /* The following loop checks looping state if -i option given */
134
135 for (lc = 0; TEST_LOOPING(lc); lc++) {
136 /* reset tst_count in case we are looping */
137 tst_count = 0;
138
139 /* loop through the test cases */
140 for (i = 0; i < TST_TOTAL; i++) {
141 /*
142 * use the TEST() macro to make the call
143 */
144
145 TEST(shmctl(*(TC[i].shmid), TC[i].cmd, TC[i].sbuf));
146
147 if (TEST_RETURN != -1) {
148 tst_resm(TFAIL, "call succeeded unexpectedly");
149 continue;
150 }
151
152 if (TEST_ERRNO == TC[i].error) {
153 tst_resm(TPASS, "expected failure - errno = "
154 "%d : %s", TEST_ERRNO,
155 strerror(TEST_ERRNO));
156 } else {
157 tst_resm(TFAIL, "call failed with an "
158 "unexpected error - %d : %s",
159 TEST_ERRNO, strerror(TEST_ERRNO));
160 }
161 }
162 }
163 }
164
165 /*
166 * setup() - performs all the ONE TIME setup for this test.
167 */
setup(void)168 void setup(void)
169 {
170 tst_require_root();
171
172 tst_sig(FORK, DEF_HANDLER, cleanup);
173
174 TEST_PAUSE;
175
176 /*
177 * Create a temporary directory and cd into it.
178 * This helps to ensure that a unique msgkey is created.
179 * See ../lib/libipc.c for more information.
180 */
181 tst_tmpdir();
182
183 /* get an IPC resource key */
184 shmkey = getipckey();
185
186 /* create a shared memory segment with read and write permissions */
187 if ((shm_id_1 = shmget(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL |
188 SHM_RW)) == -1) {
189 tst_brkm(TBROK, cleanup, "couldn't create shared memory "
190 "segment in setup()");
191 }
192
193 /* get the userid for a non root user */
194 ltp_uid = getuserid(ltp_user);
195 }
196
197 /*
198 * cleanup() - performs all the ONE TIME cleanup for this test at completion
199 * or premature exit.
200 */
cleanup(void)201 void cleanup(void)
202 {
203
204 }
205