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 * DESCRIPTION
22 * semop02 - test for E2BIG, EACCES, EFAULT, EINVAL and ERANGE errors
23 *
24 * HISTORY
25 * 03/2001 - Written by Wayne Boyer
26 *
27 * 10/03/2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com)
28 * - Fix concurrency issue. The second key used for this test could
29 * conflict with the key from another task.
30 */
31
32 #define _GNU_SOURCE
33 #include <pwd.h>
34 #include "test.h"
35 #include "safe_macros.h"
36 #include "ipcsem.h"
37
38 char *TCID = "semop02";
39
40 static void semop_verify(int i);
41 int sem_id_1 = -1; /* a semaphore set with read & alter permissions */
42 int sem_id_2 = -1; /* a semaphore set without read & alter permissions */
43 int bad_id = -1;
44
45 struct sembuf s_buf[PSEMS];
46
47 int badbuf = -1;
48
49 #define NSOPS 5 /* a resonable number of operations */
50 #define BIGOPS 1024 /* a value that is too large for the number */
51 /* of semop operations that are permitted */
52 struct test_case_t {
53 int *semid;
54 struct sembuf *t_sbuf;
55 unsigned t_ops;
56 int error;
57 } TC[] = {
58 {&sem_id_1, (struct sembuf *)&s_buf, BIGOPS, E2BIG},
59 {&sem_id_2, (struct sembuf *)&s_buf, NSOPS, EACCES},
60 {&sem_id_1, (struct sembuf *)-1, NSOPS, EFAULT},
61 {&sem_id_1, (struct sembuf *)&s_buf, 0, EINVAL},
62 {&bad_id, (struct sembuf *)&s_buf, NSOPS, EINVAL},
63 {&sem_id_1, (struct sembuf *)&s_buf, 1, ERANGE}
64 };
65
66 int TST_TOTAL = ARRAY_SIZE(TC);
67
main(int ac,char ** av)68 int main(int ac, char **av)
69 {
70 int lc;
71 int i;
72
73 tst_parse_opts(ac, av, NULL, NULL);
74
75 setup();
76
77 for (lc = 0; TEST_LOOPING(lc); lc++) {
78 tst_count = 0;
79
80 for (i = 0; i < TST_TOTAL; i++)
81 semop_verify(i);
82 }
83
84 cleanup();
85 tst_exit();
86 }
87
setup(void)88 void setup(void)
89 {
90 char nobody_uid[] = "nobody";
91 struct passwd *ltpuser;
92 key_t semkey2;
93 struct seminfo ipc_buf;
94 union semun arr;
95
96 tst_require_root();
97
98 ltpuser = SAFE_GETPWNAM(NULL, nobody_uid);
99 SAFE_SETUID(NULL, ltpuser->pw_uid);
100
101 tst_sig(NOFORK, DEF_HANDLER, cleanup);
102
103 TEST_PAUSE;
104
105 tst_tmpdir();
106
107 /* get an IPC resource key */
108 semkey = getipckey();
109
110 /* create a semaphore set with read and alter permissions */
111 sem_id_1 = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA);
112 if (sem_id_1 == -1) {
113 tst_brkm(TBROK | TERRNO, cleanup,
114 "couldn't create semaphore in setup");
115 }
116
117 /* Get an new IPC resource key. */
118 semkey2 = getipckey();
119
120 /* create a semaphore set without read and alter permissions */
121 sem_id_2 = semget(semkey2, PSEMS, IPC_CREAT | IPC_EXCL);
122 if (sem_id_2 == -1) {
123 tst_brkm(TBROK | TERRNO, cleanup,
124 "couldn't create semaphore in setup");
125 }
126
127 arr.__buf = &ipc_buf;
128 if (semctl(sem_id_1, 0, IPC_INFO, arr) == -1)
129 tst_brkm(TBROK | TERRNO, cleanup, "semctl() IPC_INFO failed");
130
131 /* for ERANGE errno test */
132 arr.val = 1;
133 s_buf[0].sem_op = ipc_buf.semvmx;
134 if (semctl(sem_id_1, 0, SETVAL, arr) == -1)
135 tst_brkm(TBROK | TERRNO, cleanup, "semctl() SETVAL failed");
136 }
137
semop_verify(int i)138 static void semop_verify(int i)
139 {
140 TEST(semop(*(TC[i].semid), TC[i].t_sbuf, TC[i].t_ops));
141
142 if (TEST_RETURN != -1) {
143 tst_resm(TFAIL, "call succeeded unexpectedly");
144 return;
145 }
146
147 if (TEST_ERRNO == TC[i].error) {
148 tst_resm(TPASS | TTERRNO, "semop failed as expected");
149 } else {
150 tst_resm(TFAIL | TTERRNO,
151 "semop failed unexpectedly; expected: "
152 "%d - %s", TC[i].error, strerror(TC[i].error));
153 }
154 }
155
cleanup(void)156 void cleanup(void)
157 {
158 /* if they exist, remove the semaphore resources */
159 rm_sema(sem_id_1);
160 rm_sema(sem_id_2);
161
162 tst_rmdir();
163 }
164