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