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/param.h> 29 #include <sys/ucred.h> 30 #include <sys/mount.h> 31 #include <sys/stat.h> 32 #include <sys/syscall.h> 33 34 #include <atf-c.h> 35 #include <fcntl.h> 36 #include <unistd.h> 37 38 #include "utils.h" 39 40 static struct pollfd fds[1]; 41 static mode_t mode = 0777; 42 static pid_t pid; 43 static int filedesc; 44 static char extregex[80]; 45 static struct stat statbuff; 46 static struct statfs statfsbuff; 47 static const char *auclass = "fa"; 48 static const char *path = "fileforaudit"; 49 static const char *errpath = "dirdoesnotexist/fileforaudit"; 50 static const char *successreg = "fileforaudit.*return,success"; 51 static const char *failurereg = "fileforaudit.*return,failure"; 52 53 54 ATF_TC_WITH_CLEANUP(stat_success); 55 ATF_TC_HEAD(stat_success, tc) 56 { 57 atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful " 58 "stat(2) call"); 59 } 60 61 ATF_TC_BODY(stat_success, tc) 62 { 63 /* File needs to exist to call stat(2) */ 64 ATF_REQUIRE((filedesc = open(path, O_CREAT, mode)) != -1); 65 FILE *pipefd = setup(fds, auclass); 66 ATF_REQUIRE_EQ(0, stat(path, &statbuff)); 67 check_audit(fds, successreg, pipefd); 68 close(filedesc); 69 } 70 71 ATF_TC_CLEANUP(stat_success, tc) 72 { 73 cleanup(); 74 } 75 76 77 ATF_TC_WITH_CLEANUP(stat_failure); 78 ATF_TC_HEAD(stat_failure, tc) 79 { 80 atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful " 81 "stat(2) call"); 82 } 83 84 ATF_TC_BODY(stat_failure, tc) 85 { 86 FILE *pipefd = setup(fds, auclass); 87 /* Failure reason: file does not exist */ 88 ATF_REQUIRE_EQ(-1, stat(errpath, &statbuff)); 89 check_audit(fds, failurereg, pipefd); 90 } 91 92 ATF_TC_CLEANUP(stat_failure, tc) 93 { 94 cleanup(); 95 } 96 97 98 ATF_TC_WITH_CLEANUP(lstat_success); 99 ATF_TC_HEAD(lstat_success, tc) 100 { 101 atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful " 102 "lstat(2) call"); 103 } 104 105 ATF_TC_BODY(lstat_success, tc) 106 { 107 /* Symbolic link needs to exist to call lstat(2) */ 108 ATF_REQUIRE_EQ(0, symlink("symlink", path)); 109 FILE *pipefd = setup(fds, auclass); 110 ATF_REQUIRE_EQ(0, lstat(path, &statbuff)); 111 check_audit(fds, successreg, pipefd); 112 } 113 114 ATF_TC_CLEANUP(lstat_success, tc) 115 { 116 cleanup(); 117 } 118 119 120 ATF_TC_WITH_CLEANUP(lstat_failure); 121 ATF_TC_HEAD(lstat_failure, tc) 122 { 123 atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful " 124 "lstat(2) call"); 125 } 126 127 ATF_TC_BODY(lstat_failure, tc) 128 { 129 FILE *pipefd = setup(fds, auclass); 130 /* Failure reason: symbolic link does not exist */ 131 ATF_REQUIRE_EQ(-1, lstat(errpath, &statbuff)); 132 check_audit(fds, failurereg, pipefd); 133 } 134 135 ATF_TC_CLEANUP(lstat_failure, tc) 136 { 137 cleanup(); 138 } 139 140 141 ATF_TC_WITH_CLEANUP(fstat_success); 142 ATF_TC_HEAD(fstat_success, tc) 143 { 144 atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful " 145 "fstat(2) call"); 146 } 147 148 ATF_TC_BODY(fstat_success, tc) 149 { 150 /* File needs to exist to call fstat(2) */ 151 ATF_REQUIRE((filedesc = open(path, O_CREAT | O_RDWR, mode)) != -1); 152 FILE *pipefd = setup(fds, auclass); 153 ATF_REQUIRE_EQ(0, fstat(filedesc, &statbuff)); 154 155 snprintf(extregex, sizeof(extregex), 156 "fstat.*%jd.*return,success", (intmax_t)statbuff.st_ino); 157 check_audit(fds, extregex, pipefd); 158 close(filedesc); 159 } 160 161 ATF_TC_CLEANUP(fstat_success, tc) 162 { 163 cleanup(); 164 } 165 166 167 ATF_TC_WITH_CLEANUP(fstat_failure); 168 ATF_TC_HEAD(fstat_failure, tc) 169 { 170 atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful " 171 "fstat(2) call"); 172 } 173 174 ATF_TC_BODY(fstat_failure, tc) 175 { 176 FILE *pipefd = setup(fds, auclass); 177 const char *regex = "fstat.*return,failure : Bad file descriptor"; 178 /* Failure reason: bad file descriptor */ 179 ATF_REQUIRE_EQ(-1, fstat(-1, &statbuff)); 180 check_audit(fds, regex, pipefd); 181 } 182 183 ATF_TC_CLEANUP(fstat_failure, tc) 184 { 185 cleanup(); 186 } 187 188 189 ATF_TC_WITH_CLEANUP(fstatat_success); 190 ATF_TC_HEAD(fstatat_success, tc) 191 { 192 atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful " 193 "fstatat(2) call"); 194 } 195 196 ATF_TC_BODY(fstatat_success, tc) 197 { 198 /* File or Symbolic link needs to exist to call lstat(2) */ 199 ATF_REQUIRE_EQ(0, symlink("symlink", path)); 200 FILE *pipefd = setup(fds, auclass); 201 ATF_REQUIRE_EQ(0, fstatat(AT_FDCWD, path, &statbuff, 202 AT_SYMLINK_NOFOLLOW)); 203 check_audit(fds, successreg, pipefd); 204 } 205 206 ATF_TC_CLEANUP(fstatat_success, tc) 207 { 208 cleanup(); 209 } 210 211 212 ATF_TC_WITH_CLEANUP(fstatat_failure); 213 ATF_TC_HEAD(fstatat_failure, tc) 214 { 215 atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful " 216 "fstatat(2) call"); 217 } 218 219 ATF_TC_BODY(fstatat_failure, tc) 220 { 221 FILE *pipefd = setup(fds, auclass); 222 /* Failure reason: symbolic link does not exist */ 223 ATF_REQUIRE_EQ(-1, fstatat(AT_FDCWD, path, &statbuff, 224 AT_SYMLINK_NOFOLLOW)); 225 check_audit(fds, failurereg, pipefd); 226 } 227 228 ATF_TC_CLEANUP(fstatat_failure, tc) 229 { 230 cleanup(); 231 } 232 233 234 ATF_TC_WITH_CLEANUP(statfs_success); 235 ATF_TC_HEAD(statfs_success, tc) 236 { 237 atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful " 238 "statfs(2) call"); 239 } 240 241 ATF_TC_BODY(statfs_success, tc) 242 { 243 /* File needs to exist to call statfs(2) */ 244 ATF_REQUIRE((filedesc = open(path, O_CREAT, mode)) != -1); 245 FILE *pipefd = setup(fds, auclass); 246 ATF_REQUIRE_EQ(0, statfs(path, &statfsbuff)); 247 check_audit(fds, successreg, pipefd); 248 close(filedesc); 249 } 250 251 ATF_TC_CLEANUP(statfs_success, tc) 252 { 253 cleanup(); 254 } 255 256 257 ATF_TC_WITH_CLEANUP(statfs_failure); 258 ATF_TC_HEAD(statfs_failure, tc) 259 { 260 atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful " 261 "statfs(2) call"); 262 } 263 264 ATF_TC_BODY(statfs_failure, tc) 265 { 266 FILE *pipefd = setup(fds, auclass); 267 /* Failure reason: file does not exist */ 268 ATF_REQUIRE_EQ(-1, statfs(errpath, &statfsbuff)); 269 check_audit(fds, failurereg, pipefd); 270 } 271 272 ATF_TC_CLEANUP(statfs_failure, tc) 273 { 274 cleanup(); 275 } 276 277 278 ATF_TC_WITH_CLEANUP(fstatfs_success); 279 ATF_TC_HEAD(fstatfs_success, tc) 280 { 281 atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful " 282 "fstatfs(2) call"); 283 } 284 285 ATF_TC_BODY(fstatfs_success, tc) 286 { 287 /* File needs to exist to call fstat(2) */ 288 ATF_REQUIRE((filedesc = open(path, O_CREAT | O_RDWR, mode)) != -1); 289 /* Call stat(2) to store the Inode number of 'path' */ 290 ATF_REQUIRE_EQ(0, stat(path, &statbuff)); 291 FILE *pipefd = setup(fds, auclass); 292 ATF_REQUIRE_EQ(0, fstatfs(filedesc, &statfsbuff)); 293 294 snprintf(extregex, sizeof(extregex), "fstatfs.*%jd.*return,success", 295 (intmax_t)statbuff.st_ino); 296 check_audit(fds, extregex, pipefd); 297 close(filedesc); 298 } 299 300 ATF_TC_CLEANUP(fstatfs_success, tc) 301 { 302 cleanup(); 303 } 304 305 306 ATF_TC_WITH_CLEANUP(fstatfs_failure); 307 ATF_TC_HEAD(fstatfs_failure, tc) 308 { 309 atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful " 310 "fstatfs(2) call"); 311 } 312 313 ATF_TC_BODY(fstatfs_failure, tc) 314 { 315 FILE *pipefd = setup(fds, auclass); 316 const char *regex = "fstatfs.*return,failure : Bad file descriptor"; 317 /* Failure reason: bad file descriptor */ 318 ATF_REQUIRE_EQ(-1, fstatfs(-1, &statfsbuff)); 319 check_audit(fds, regex, pipefd); 320 } 321 322 ATF_TC_CLEANUP(fstatfs_failure, tc) 323 { 324 cleanup(); 325 } 326 327 328 ATF_TC_WITH_CLEANUP(getfsstat_success); 329 ATF_TC_HEAD(getfsstat_success, tc) 330 { 331 atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful " 332 "getfsstat(2) call"); 333 } 334 335 ATF_TC_BODY(getfsstat_success, tc) 336 { 337 pid = getpid(); 338 snprintf(extregex, sizeof(extregex), "getfsstat.*%d.*success", pid); 339 340 FILE *pipefd = setup(fds, auclass); 341 ATF_REQUIRE(getfsstat(NULL, 0, MNT_NOWAIT) != -1); 342 check_audit(fds, extregex, pipefd); 343 } 344 345 ATF_TC_CLEANUP(getfsstat_success, tc) 346 { 347 cleanup(); 348 } 349 350 351 ATF_TC_WITH_CLEANUP(getfsstat_failure); 352 ATF_TC_HEAD(getfsstat_failure, tc) 353 { 354 atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful " 355 "getfsstat(2) call"); 356 } 357 358 ATF_TC_BODY(getfsstat_failure, tc) 359 { 360 const char *regex = "getfsstat.*return,failure : Invalid argument"; 361 FILE *pipefd = setup(fds, auclass); 362 /* Failure reason: Invalid value for mode */ 363 ATF_REQUIRE_EQ(-1, getfsstat(NULL, 0, -1)); 364 check_audit(fds, regex, pipefd); 365 } 366 367 ATF_TC_CLEANUP(getfsstat_failure, tc) 368 { 369 cleanup(); 370 } 371 372 373 ATF_TP_ADD_TCS(tp) 374 { 375 ATF_TP_ADD_TC(tp, stat_success); 376 ATF_TP_ADD_TC(tp, stat_failure); 377 ATF_TP_ADD_TC(tp, lstat_success); 378 ATF_TP_ADD_TC(tp, lstat_failure); 379 ATF_TP_ADD_TC(tp, fstat_success); 380 ATF_TP_ADD_TC(tp, fstat_failure); 381 ATF_TP_ADD_TC(tp, fstatat_success); 382 ATF_TP_ADD_TC(tp, fstatat_failure); 383 384 ATF_TP_ADD_TC(tp, statfs_success); 385 ATF_TP_ADD_TC(tp, statfs_failure); 386 ATF_TP_ADD_TC(tp, fstatfs_success); 387 ATF_TP_ADD_TC(tp, fstatfs_failure); 388 389 ATF_TP_ADD_TC(tp, getfsstat_success); 390 ATF_TP_ADD_TC(tp, getfsstat_failure); 391 392 return (atf_no_error()); 393 } 394