xref: /freebsd/tests/sys/audit/inter-process.c (revision d7d1ecc0710a64ec2375a3d4ec7b1634a0d6a554)
1 /*-
2  * Copyright (c) 2018 Aniket Pandey
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD$
26  */
27 
28 #include <sys/types.h>
29 #include <sys/ipc.h>
30 #include <sys/mman.h>
31 #include <sys/msg.h>
32 #include <sys/stat.h>
33 
34 #include <atf-c.h>
35 #include <fcntl.h>
36 #include <string.h>
37 #include <unistd.h>
38 
39 #include "utils.h"
40 #define BUFFSIZE 80
41 
42 struct msgstr {
43 	long int	 mtype;
44 	char		 mtext[BUFFSIZE];
45 };
46 typedef struct msgstr msgstr_t;
47 
48 static int msqid;
49 static struct pollfd fds[1];
50 static struct msqid_ds msgbuff;
51 static char ipcregex[BUFFSIZE];
52 static const char *auclass = "ip";
53 
54 
55 ATF_TC_WITH_CLEANUP(msgget_success);
56 ATF_TC_HEAD(msgget_success, tc)
57 {
58 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
59 					"msgget(2) call");
60 }
61 
62 ATF_TC_BODY(msgget_success, tc)
63 {
64 	FILE *pipefd = setup(fds, auclass);
65 	/* Create a message queue and obtain the corresponding identifier */
66 	ATF_REQUIRE((msqid = msgget(IPC_PRIVATE, IPC_CREAT | S_IRUSR)) != -1);
67 	/* Check the presence of message queue ID in audit record */
68 	snprintf(ipcregex, sizeof(ipcregex),
69 			"msgget.*return,success,%d", msqid);
70 	check_audit(fds, ipcregex, pipefd);
71 
72 	/* Destroy the message queue with ID = msqid */
73 	ATF_REQUIRE_EQ(0, msgctl(msqid, IPC_RMID, NULL));
74 }
75 
76 ATF_TC_CLEANUP(msgget_success, tc)
77 {
78 	cleanup();
79 }
80 
81 
82 ATF_TC_WITH_CLEANUP(msgget_failure);
83 ATF_TC_HEAD(msgget_failure, tc)
84 {
85 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
86 					"msgget(2) call");
87 }
88 
89 ATF_TC_BODY(msgget_failure, tc)
90 {
91 	const char *regex = "msgget.*return,failure.*No such file or directory";
92 	FILE *pipefd = setup(fds, auclass);
93 	ATF_REQUIRE_EQ(-1, msgget((key_t)(-1), 0));
94 	check_audit(fds, regex, pipefd);
95 }
96 
97 ATF_TC_CLEANUP(msgget_failure, tc)
98 {
99 	cleanup();
100 }
101 
102 
103 ATF_TC_WITH_CLEANUP(msgsnd_success);
104 ATF_TC_HEAD(msgsnd_success, tc)
105 {
106 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
107 					"msgsnd(2) call");
108 }
109 
110 ATF_TC_BODY(msgsnd_success, tc)
111 {
112 	/* Create a message queue and obtain the corresponding identifier */
113 	ATF_REQUIRE((msqid = msgget(IPC_PRIVATE, IPC_CREAT | S_IRUSR)) != -1);
114 
115 	/* Initialize a msgstr_t structure to store message */
116 	msgstr_t msg;
117 	msg.mtype = 1;
118 	memset(msg.mtext, 0, BUFFSIZE);
119 
120 	/* Check the presence of message queue ID in audit record */
121 	snprintf(ipcregex, sizeof(ipcregex),
122 		"msgsnd.*Message IPC.*%d.*return,success", msqid);
123 
124 	FILE *pipefd = setup(fds, auclass);
125 	ATF_REQUIRE_EQ(0, msgsnd(msqid, &msg, BUFFSIZE, IPC_NOWAIT));
126 	check_audit(fds, ipcregex, pipefd);
127 
128 	/* Destroy the message queue with ID = msqid */
129 	ATF_REQUIRE_EQ(0, msgctl(msqid, IPC_RMID, NULL));
130 }
131 
132 ATF_TC_CLEANUP(msgsnd_success, tc)
133 {
134 	cleanup();
135 }
136 
137 
138 ATF_TC_WITH_CLEANUP(msgsnd_failure);
139 ATF_TC_HEAD(msgsnd_failure, tc)
140 {
141 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
142 					"msgsnd(2) call");
143 }
144 
145 ATF_TC_BODY(msgsnd_failure, tc)
146 {
147 	const char *regex = "msgsnd.*Message IPC.*return,failure : Bad address";
148 	FILE *pipefd = setup(fds, auclass);
149 	ATF_REQUIRE_EQ(-1, msgsnd(-1, NULL, 0, IPC_NOWAIT));
150 	check_audit(fds, regex, pipefd);
151 }
152 
153 ATF_TC_CLEANUP(msgsnd_failure, tc)
154 {
155 	cleanup();
156 }
157 
158 
159 ATF_TC_WITH_CLEANUP(msgrcv_success);
160 ATF_TC_HEAD(msgrcv_success, tc)
161 {
162 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
163 					"msgrcv(2) call");
164 }
165 
166 ATF_TC_BODY(msgrcv_success, tc)
167 {
168 	ssize_t recv_bytes;
169 	/* Create a message queue and obtain the corresponding identifier */
170 	ATF_REQUIRE((msqid = msgget(IPC_PRIVATE, IPC_CREAT | S_IRUSR)) != -1);
171 
172 	/* Initialize two msgstr_t structures to store respective messages */
173 	msgstr_t msg1, msg2;
174 	msg1.mtype = 1;
175 	memset(msg1.mtext, 0, BUFFSIZE);
176 
177 	/* Send a message to the queue with ID = msqid */
178 	ATF_REQUIRE_EQ(0, msgsnd(msqid, &msg1, BUFFSIZE, IPC_NOWAIT));
179 
180 	FILE *pipefd = setup(fds, auclass);
181 	ATF_REQUIRE((recv_bytes = msgrcv(msqid, &msg2,
182 			BUFFSIZE, 0, MSG_NOERROR | IPC_NOWAIT)) != -1);
183 	/* Check the presence of queue ID and returned bytes in audit record */
184 	snprintf(ipcregex, sizeof(ipcregex),
185 	"msgrcv.*Message IPC,*%d.*return,success,%zd", msqid, recv_bytes);
186 	check_audit(fds, ipcregex, pipefd);
187 
188 	/* Destroy the message queue with ID = msqid */
189 	ATF_REQUIRE_EQ(0, msgctl(msqid, IPC_RMID, NULL));
190 }
191 
192 ATF_TC_CLEANUP(msgrcv_success, tc)
193 {
194 	cleanup();
195 }
196 
197 
198 ATF_TC_WITH_CLEANUP(msgrcv_failure);
199 ATF_TC_HEAD(msgrcv_failure, tc)
200 {
201 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
202 					"msgrcv(2) call");
203 }
204 
205 ATF_TC_BODY(msgrcv_failure, tc)
206 {
207 	const char *regex = "msgrcv.*return,failure : Invalid argument";
208 	FILE *pipefd = setup(fds, auclass);
209 	ATF_REQUIRE_EQ(-1, msgrcv(-1, NULL, 0, 0, MSG_NOERROR | IPC_NOWAIT));
210 	check_audit(fds, regex, pipefd);
211 }
212 
213 ATF_TC_CLEANUP(msgrcv_failure, tc)
214 {
215 	cleanup();
216 }
217 
218 
219 ATF_TC_WITH_CLEANUP(msgctl_rmid_success);
220 ATF_TC_HEAD(msgctl_rmid_success, tc)
221 {
222 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
223 					"msgctl(2) call for IPC_RMID command");
224 }
225 
226 ATF_TC_BODY(msgctl_rmid_success, tc)
227 {
228 	/* Create a message queue and obtain the corresponding identifier */
229 	ATF_REQUIRE((msqid = msgget(IPC_PRIVATE, IPC_CREAT | S_IRUSR)) != -1);
230 
231 	FILE *pipefd = setup(fds, auclass);
232 	ATF_REQUIRE_EQ(0, msgctl(msqid, IPC_RMID, NULL));
233 	/* Check the presence of queue ID and IPC_RMID in audit record */
234 	snprintf(ipcregex, sizeof(ipcregex),
235 			"msgctl.*IPC_RMID.*%d.*return,success", msqid);
236 	check_audit(fds, ipcregex, pipefd);
237 }
238 
239 ATF_TC_CLEANUP(msgctl_rmid_success, tc)
240 {
241 	cleanup();
242 }
243 
244 
245 ATF_TC_WITH_CLEANUP(msgctl_rmid_failure);
246 ATF_TC_HEAD(msgctl_rmid_failure, tc)
247 {
248 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
249 					"msgctl(2) call for IPC_RMID command");
250 }
251 
252 ATF_TC_BODY(msgctl_rmid_failure, tc)
253 {
254 	const char *regex = "msgctl.*IPC_RMID.*return,failur.*Invalid argument";
255 	FILE *pipefd = setup(fds, auclass);
256 	ATF_REQUIRE_EQ(-1, msgctl(-1, IPC_RMID, NULL));
257 	check_audit(fds, regex, pipefd);
258 }
259 
260 ATF_TC_CLEANUP(msgctl_rmid_failure, tc)
261 {
262 	cleanup();
263 }
264 
265 
266 ATF_TC_WITH_CLEANUP(msgctl_stat_success);
267 ATF_TC_HEAD(msgctl_stat_success, tc)
268 {
269 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
270 					"msgctl(2) call for IPC_STAT command");
271 }
272 
273 ATF_TC_BODY(msgctl_stat_success, tc)
274 {
275 	/* Create a message queue and obtain the corresponding identifier */
276 	ATF_REQUIRE((msqid = msgget(IPC_PRIVATE, IPC_CREAT | S_IRUSR)) != -1);
277 
278 	FILE *pipefd = setup(fds, auclass);
279 	ATF_REQUIRE_EQ(0, msgctl(msqid, IPC_STAT, &msgbuff));
280 	/* Check the presence of queue ID and IPC_STAT in audit record */
281 	snprintf(ipcregex, sizeof(ipcregex),
282 			"msgctl.*IPC_STAT.*%d.*return,success", msqid);
283 	check_audit(fds, ipcregex, pipefd);
284 
285 	/* Destroy the message queue with ID = msqid */
286 	ATF_REQUIRE_EQ(0, msgctl(msqid, IPC_RMID, NULL));
287 }
288 
289 ATF_TC_CLEANUP(msgctl_stat_success, tc)
290 {
291 	cleanup();
292 }
293 
294 
295 ATF_TC_WITH_CLEANUP(msgctl_stat_failure);
296 ATF_TC_HEAD(msgctl_stat_failure, tc)
297 {
298 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
299 					"msgctl(2) call for IPC_STAT command");
300 }
301 
302 ATF_TC_BODY(msgctl_stat_failure, tc)
303 {
304 	const char *regex = "msgctl.*IPC_STAT.*return,failur.*Invalid argument";
305 	FILE *pipefd = setup(fds, auclass);
306 	ATF_REQUIRE_EQ(-1, msgctl(-1, IPC_STAT, &msgbuff));
307 	check_audit(fds, regex, pipefd);
308 }
309 
310 ATF_TC_CLEANUP(msgctl_stat_failure, tc)
311 {
312 	cleanup();
313 }
314 
315 
316 ATF_TC_WITH_CLEANUP(msgctl_set_success);
317 ATF_TC_HEAD(msgctl_set_success, tc)
318 {
319 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
320 					"msgctl(2) call for IPC_SET command");
321 }
322 
323 ATF_TC_BODY(msgctl_set_success, tc)
324 {
325 	/* Create a message queue and obtain the corresponding identifier */
326 	ATF_REQUIRE((msqid = msgget(IPC_PRIVATE, IPC_CREAT | S_IRUSR)) != -1);
327 	/* Fill up the msgbuff structure to be used with IPC_SET */
328 	ATF_REQUIRE_EQ(0, msgctl(msqid, IPC_STAT, &msgbuff));
329 
330 	FILE *pipefd = setup(fds, auclass);
331 	ATF_REQUIRE_EQ(0, msgctl(msqid, IPC_SET, &msgbuff));
332 	/* Check the presence of message queue ID in audit record */
333 	snprintf(ipcregex, sizeof(ipcregex),
334 			"msgctl.*IPC_SET.*%d.*return,success", msqid);
335 	check_audit(fds, ipcregex, pipefd);
336 
337 	/* Destroy the message queue with ID = msqid */
338 	ATF_REQUIRE_EQ(0, msgctl(msqid, IPC_RMID, NULL));
339 }
340 
341 ATF_TC_CLEANUP(msgctl_set_success, tc)
342 {
343 	cleanup();
344 }
345 
346 
347 ATF_TC_WITH_CLEANUP(msgctl_set_failure);
348 ATF_TC_HEAD(msgctl_set_failure, tc)
349 {
350 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
351 					"msgctl(2) call for IPC_SET command");
352 }
353 
354 ATF_TC_BODY(msgctl_set_failure, tc)
355 {
356 	const char *regex = "msgctl.*IPC_SET.*return,failure.*Invalid argument";
357 	FILE *pipefd = setup(fds, auclass);
358 	ATF_REQUIRE_EQ(-1, msgctl(-1, IPC_SET, &msgbuff));
359 	check_audit(fds, regex, pipefd);
360 }
361 
362 ATF_TC_CLEANUP(msgctl_set_failure, tc)
363 {
364 	cleanup();
365 }
366 
367 
368 ATF_TC_WITH_CLEANUP(msgctl_illegal_command);
369 ATF_TC_HEAD(msgctl_illegal_command, tc)
370 {
371 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
372 					"msgctl(2) call for illegal cmd value");
373 }
374 
375 ATF_TC_BODY(msgctl_illegal_command, tc)
376 {
377 	/* Create a message queue and obtain the corresponding identifier */
378 	ATF_REQUIRE((msqid = msgget(IPC_PRIVATE, IPC_CREAT | S_IRUSR)) != -1);
379 
380 	const char *regex = "msgctl.*illegal command.*failur.*Invalid argument";
381 	FILE *pipefd = setup(fds, auclass);
382 	ATF_REQUIRE_EQ(-1, msgctl(msqid, -1, &msgbuff));
383 	check_audit(fds, regex, pipefd);
384 
385 	/* Destroy the message queue with ID = msqid */
386 	ATF_REQUIRE_EQ(0, msgctl(msqid, IPC_RMID, NULL));
387 }
388 
389 ATF_TC_CLEANUP(msgctl_illegal_command, tc)
390 {
391 	cleanup();
392 }
393 
394 
395 ATF_TP_ADD_TCS(tp)
396 {
397 	ATF_TP_ADD_TC(tp, msgget_success);
398 	ATF_TP_ADD_TC(tp, msgget_failure);
399 	ATF_TP_ADD_TC(tp, msgsnd_success);
400 	ATF_TP_ADD_TC(tp, msgsnd_failure);
401 	ATF_TP_ADD_TC(tp, msgrcv_success);
402 	ATF_TP_ADD_TC(tp, msgrcv_failure);
403 
404 	ATF_TP_ADD_TC(tp, msgctl_rmid_success);
405 	ATF_TP_ADD_TC(tp, msgctl_rmid_failure);
406 	ATF_TP_ADD_TC(tp, msgctl_stat_success);
407 	ATF_TP_ADD_TC(tp, msgctl_stat_failure);
408 	ATF_TP_ADD_TC(tp, msgctl_set_success);
409 	ATF_TP_ADD_TC(tp, msgctl_set_failure);
410 	ATF_TP_ADD_TC(tp, msgctl_illegal_command);
411 
412 	return (atf_no_error());
413 }
414