1 /* @generated by `generate-fortify-tests.lua "unistd"` */ 2 3 #define _FORTIFY_SOURCE 2 4 #define TMPFILE_SIZE (1024 * 32) 5 6 #include <sys/param.h> 7 #include <sys/resource.h> 8 #include <sys/time.h> 9 #include <sys/wait.h> 10 #include <dirent.h> 11 #include <errno.h> 12 #include <fcntl.h> 13 #include <limits.h> 14 #include <signal.h> 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <strings.h> 19 #include <sysexits.h> 20 #include <unistd.h> 21 #include <atf-c.h> 22 23 /* 24 * Create a new symlink to use for readlink(2) style tests, we'll just use a 25 * random target name to have something interesting to look at. 26 */ 27 static const char * __unused 28 new_symlink(size_t __len) 29 { 30 static const char linkname[] = "link"; 31 char target[MAXNAMLEN]; 32 int error; 33 34 ATF_REQUIRE(__len <= sizeof(target)); 35 36 arc4random_buf(target, sizeof(target)); 37 38 error = unlink(linkname); 39 ATF_REQUIRE(error == 0 || errno == ENOENT); 40 41 error = symlink(target, linkname); 42 ATF_REQUIRE(error == 0); 43 44 return (linkname); 45 } 46 47 /* 48 * Constructs a tmpfile that we can use for testing read(2) and friends. 49 */ 50 static int __unused 51 new_tmpfile(void) 52 { 53 char buf[1024]; 54 ssize_t rv; 55 size_t written; 56 int fd; 57 58 fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); 59 ATF_REQUIRE(fd >= 0); 60 61 written = 0; 62 while (written < TMPFILE_SIZE) { 63 rv = write(fd, buf, sizeof(buf)); 64 ATF_REQUIRE(rv > 0); 65 66 written += rv; 67 } 68 69 ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); 70 return (fd); 71 } 72 73 static void 74 disable_coredumps(void) 75 { 76 struct rlimit rl = { 0 }; 77 78 if (setrlimit(RLIMIT_CORE, &rl) == -1) 79 _exit(EX_OSERR); 80 } 81 82 ATF_TC_WITHOUT_HEAD(getcwd_before_end); 83 ATF_TC_BODY(getcwd_before_end, tc) 84 { 85 #define BUF &__stack.__buf 86 struct { 87 uint8_t padding_l; 88 unsigned char __buf[8]; 89 uint8_t padding_r; 90 } __stack; 91 const size_t __bufsz __unused = sizeof(__stack.__buf); 92 const size_t __len = 8 - 1; 93 const size_t __idx __unused = __len - 1; 94 95 getcwd(__stack.__buf, __len); 96 #undef BUF 97 98 } 99 100 ATF_TC_WITHOUT_HEAD(getcwd_end); 101 ATF_TC_BODY(getcwd_end, tc) 102 { 103 #define BUF &__stack.__buf 104 struct { 105 uint8_t padding_l; 106 unsigned char __buf[8]; 107 uint8_t padding_r; 108 } __stack; 109 const size_t __bufsz __unused = sizeof(__stack.__buf); 110 const size_t __len = 8; 111 const size_t __idx __unused = __len - 1; 112 113 getcwd(__stack.__buf, __len); 114 #undef BUF 115 116 } 117 118 ATF_TC_WITHOUT_HEAD(getcwd_heap_before_end); 119 ATF_TC_BODY(getcwd_heap_before_end, tc) 120 { 121 #define BUF __stack.__buf 122 struct { 123 uint8_t padding_l; 124 unsigned char * __buf; 125 uint8_t padding_r; 126 } __stack; 127 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (8); 128 const size_t __len = 8 - 1; 129 const size_t __idx __unused = __len - 1; 130 131 __stack.__buf = malloc(__bufsz); 132 133 getcwd(__stack.__buf, __len); 134 #undef BUF 135 136 } 137 138 ATF_TC_WITHOUT_HEAD(getcwd_heap_end); 139 ATF_TC_BODY(getcwd_heap_end, tc) 140 { 141 #define BUF __stack.__buf 142 struct { 143 uint8_t padding_l; 144 unsigned char * __buf; 145 uint8_t padding_r; 146 } __stack; 147 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (8); 148 const size_t __len = 8; 149 const size_t __idx __unused = __len - 1; 150 151 __stack.__buf = malloc(__bufsz); 152 153 getcwd(__stack.__buf, __len); 154 #undef BUF 155 156 } 157 158 ATF_TC_WITHOUT_HEAD(getcwd_heap_after_end); 159 ATF_TC_BODY(getcwd_heap_after_end, tc) 160 { 161 #define BUF __stack.__buf 162 struct { 163 uint8_t padding_l; 164 unsigned char * __buf; 165 uint8_t padding_r; 166 } __stack; 167 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (8); 168 const size_t __len = 8 + 1; 169 const size_t __idx __unused = __len - 1; 170 pid_t __child; 171 int __status; 172 173 __child = fork(); 174 ATF_REQUIRE(__child >= 0); 175 if (__child > 0) 176 goto monitor; 177 178 /* Child */ 179 disable_coredumps(); 180 __stack.__buf = malloc(__bufsz); 181 182 getcwd(__stack.__buf, __len); 183 _exit(EX_SOFTWARE); /* Should have aborted. */ 184 185 monitor: 186 while (waitpid(__child, &__status, 0) != __child) { 187 ATF_REQUIRE_EQ(EINTR, errno); 188 } 189 190 if (!WIFSIGNALED(__status)) { 191 switch (WEXITSTATUS(__status)) { 192 case EX_SOFTWARE: 193 atf_tc_fail("FORTIFY_SOURCE failed to abort"); 194 break; 195 case EX_OSERR: 196 atf_tc_fail("setrlimit(2) failed"); 197 break; 198 default: 199 atf_tc_fail("child exited with status %d", 200 WEXITSTATUS(__status)); 201 } 202 } else { 203 ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); 204 } 205 #undef BUF 206 207 } 208 209 ATF_TC_WITHOUT_HEAD(read_before_end); 210 ATF_TC_BODY(read_before_end, tc) 211 { 212 #define BUF &__stack.__buf 213 struct { 214 uint8_t padding_l; 215 unsigned char __buf[41]; 216 uint8_t padding_r; 217 } __stack; 218 const size_t __bufsz __unused = sizeof(__stack.__buf); 219 const size_t __len = 41 - 1; 220 const size_t __idx __unused = __len - 1; 221 int fd; 222 223 fd = new_tmpfile(); /* Cannot fail */ 224 225 read(fd, __stack.__buf, __len); 226 #undef BUF 227 228 } 229 230 ATF_TC_WITHOUT_HEAD(read_end); 231 ATF_TC_BODY(read_end, tc) 232 { 233 #define BUF &__stack.__buf 234 struct { 235 uint8_t padding_l; 236 unsigned char __buf[41]; 237 uint8_t padding_r; 238 } __stack; 239 const size_t __bufsz __unused = sizeof(__stack.__buf); 240 const size_t __len = 41; 241 const size_t __idx __unused = __len - 1; 242 int fd; 243 244 fd = new_tmpfile(); /* Cannot fail */ 245 246 read(fd, __stack.__buf, __len); 247 #undef BUF 248 249 } 250 251 ATF_TC_WITHOUT_HEAD(read_heap_before_end); 252 ATF_TC_BODY(read_heap_before_end, tc) 253 { 254 #define BUF __stack.__buf 255 struct { 256 uint8_t padding_l; 257 unsigned char * __buf; 258 uint8_t padding_r; 259 } __stack; 260 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); 261 const size_t __len = 41 - 1; 262 const size_t __idx __unused = __len - 1; 263 int fd; 264 265 __stack.__buf = malloc(__bufsz); 266 fd = new_tmpfile(); /* Cannot fail */ 267 268 read(fd, __stack.__buf, __len); 269 #undef BUF 270 271 } 272 273 ATF_TC_WITHOUT_HEAD(read_heap_end); 274 ATF_TC_BODY(read_heap_end, tc) 275 { 276 #define BUF __stack.__buf 277 struct { 278 uint8_t padding_l; 279 unsigned char * __buf; 280 uint8_t padding_r; 281 } __stack; 282 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); 283 const size_t __len = 41; 284 const size_t __idx __unused = __len - 1; 285 int fd; 286 287 __stack.__buf = malloc(__bufsz); 288 fd = new_tmpfile(); /* Cannot fail */ 289 290 read(fd, __stack.__buf, __len); 291 #undef BUF 292 293 } 294 295 ATF_TC_WITHOUT_HEAD(read_heap_after_end); 296 ATF_TC_BODY(read_heap_after_end, tc) 297 { 298 #define BUF __stack.__buf 299 struct { 300 uint8_t padding_l; 301 unsigned char * __buf; 302 uint8_t padding_r; 303 } __stack; 304 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); 305 const size_t __len = 41 + 1; 306 const size_t __idx __unused = __len - 1; 307 pid_t __child; 308 int __status; 309 int fd; 310 311 __child = fork(); 312 ATF_REQUIRE(__child >= 0); 313 if (__child > 0) 314 goto monitor; 315 316 /* Child */ 317 disable_coredumps(); 318 __stack.__buf = malloc(__bufsz); 319 fd = new_tmpfile(); /* Cannot fail */ 320 321 read(fd, __stack.__buf, __len); 322 _exit(EX_SOFTWARE); /* Should have aborted. */ 323 324 monitor: 325 while (waitpid(__child, &__status, 0) != __child) { 326 ATF_REQUIRE_EQ(EINTR, errno); 327 } 328 329 if (!WIFSIGNALED(__status)) { 330 switch (WEXITSTATUS(__status)) { 331 case EX_SOFTWARE: 332 atf_tc_fail("FORTIFY_SOURCE failed to abort"); 333 break; 334 case EX_OSERR: 335 atf_tc_fail("setrlimit(2) failed"); 336 break; 337 default: 338 atf_tc_fail("child exited with status %d", 339 WEXITSTATUS(__status)); 340 } 341 } else { 342 ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); 343 } 344 #undef BUF 345 346 } 347 348 ATF_TC_WITHOUT_HEAD(readlink_before_end); 349 ATF_TC_BODY(readlink_before_end, tc) 350 { 351 #define BUF &__stack.__buf 352 struct { 353 uint8_t padding_l; 354 unsigned char __buf[42]; 355 uint8_t padding_r; 356 } __stack; 357 const size_t __bufsz __unused = sizeof(__stack.__buf); 358 const size_t __len = 42 - 1; 359 const size_t __idx __unused = __len - 1; 360 const char *path; 361 362 path = new_symlink(__len); /* Cannot fail */ 363 364 readlink(path, __stack.__buf, __len); 365 #undef BUF 366 367 } 368 369 ATF_TC_WITHOUT_HEAD(readlink_end); 370 ATF_TC_BODY(readlink_end, tc) 371 { 372 #define BUF &__stack.__buf 373 struct { 374 uint8_t padding_l; 375 unsigned char __buf[42]; 376 uint8_t padding_r; 377 } __stack; 378 const size_t __bufsz __unused = sizeof(__stack.__buf); 379 const size_t __len = 42; 380 const size_t __idx __unused = __len - 1; 381 const char *path; 382 383 path = new_symlink(__len); /* Cannot fail */ 384 385 readlink(path, __stack.__buf, __len); 386 #undef BUF 387 388 } 389 390 ATF_TC_WITHOUT_HEAD(readlink_heap_before_end); 391 ATF_TC_BODY(readlink_heap_before_end, tc) 392 { 393 #define BUF __stack.__buf 394 struct { 395 uint8_t padding_l; 396 unsigned char * __buf; 397 uint8_t padding_r; 398 } __stack; 399 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); 400 const size_t __len = 42 - 1; 401 const size_t __idx __unused = __len - 1; 402 const char *path; 403 404 __stack.__buf = malloc(__bufsz); 405 path = new_symlink(__len); /* Cannot fail */ 406 407 readlink(path, __stack.__buf, __len); 408 #undef BUF 409 410 } 411 412 ATF_TC_WITHOUT_HEAD(readlink_heap_end); 413 ATF_TC_BODY(readlink_heap_end, tc) 414 { 415 #define BUF __stack.__buf 416 struct { 417 uint8_t padding_l; 418 unsigned char * __buf; 419 uint8_t padding_r; 420 } __stack; 421 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); 422 const size_t __len = 42; 423 const size_t __idx __unused = __len - 1; 424 const char *path; 425 426 __stack.__buf = malloc(__bufsz); 427 path = new_symlink(__len); /* Cannot fail */ 428 429 readlink(path, __stack.__buf, __len); 430 #undef BUF 431 432 } 433 434 ATF_TC_WITHOUT_HEAD(readlink_heap_after_end); 435 ATF_TC_BODY(readlink_heap_after_end, tc) 436 { 437 #define BUF __stack.__buf 438 struct { 439 uint8_t padding_l; 440 unsigned char * __buf; 441 uint8_t padding_r; 442 } __stack; 443 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); 444 const size_t __len = 42 + 1; 445 const size_t __idx __unused = __len - 1; 446 pid_t __child; 447 int __status; 448 const char *path; 449 450 __child = fork(); 451 ATF_REQUIRE(__child >= 0); 452 if (__child > 0) 453 goto monitor; 454 455 /* Child */ 456 disable_coredumps(); 457 __stack.__buf = malloc(__bufsz); 458 path = new_symlink(__len); /* Cannot fail */ 459 460 readlink(path, __stack.__buf, __len); 461 _exit(EX_SOFTWARE); /* Should have aborted. */ 462 463 monitor: 464 while (waitpid(__child, &__status, 0) != __child) { 465 ATF_REQUIRE_EQ(EINTR, errno); 466 } 467 468 if (!WIFSIGNALED(__status)) { 469 switch (WEXITSTATUS(__status)) { 470 case EX_SOFTWARE: 471 atf_tc_fail("FORTIFY_SOURCE failed to abort"); 472 break; 473 case EX_OSERR: 474 atf_tc_fail("setrlimit(2) failed"); 475 break; 476 default: 477 atf_tc_fail("child exited with status %d", 478 WEXITSTATUS(__status)); 479 } 480 } else { 481 ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); 482 } 483 #undef BUF 484 485 } 486 487 ATF_TP_ADD_TCS(tp) 488 { 489 ATF_TP_ADD_TC(tp, getcwd_before_end); 490 ATF_TP_ADD_TC(tp, getcwd_end); 491 ATF_TP_ADD_TC(tp, getcwd_heap_before_end); 492 ATF_TP_ADD_TC(tp, getcwd_heap_end); 493 ATF_TP_ADD_TC(tp, getcwd_heap_after_end); 494 ATF_TP_ADD_TC(tp, read_before_end); 495 ATF_TP_ADD_TC(tp, read_end); 496 ATF_TP_ADD_TC(tp, read_heap_before_end); 497 ATF_TP_ADD_TC(tp, read_heap_end); 498 ATF_TP_ADD_TC(tp, read_heap_after_end); 499 ATF_TP_ADD_TC(tp, readlink_before_end); 500 ATF_TP_ADD_TC(tp, readlink_end); 501 ATF_TP_ADD_TC(tp, readlink_heap_before_end); 502 ATF_TP_ADD_TC(tp, readlink_heap_end); 503 ATF_TP_ADD_TC(tp, readlink_heap_after_end); 504 return (atf_no_error()); 505 } 506