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