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