1 /* @generated by `generate-fortify-tests.lua "stdlib"` */ 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 <poll.h> 15 #include <signal.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <strings.h> 20 #include <sysexits.h> 21 #include <unistd.h> 22 #include <wchar.h> 23 #include <atf-c.h> 24 25 static FILE * __unused 26 new_fp(size_t __len) 27 { 28 static char fpbuf[LINE_MAX]; 29 FILE *fp; 30 31 ATF_REQUIRE(__len <= sizeof(fpbuf)); 32 33 memset(fpbuf, 'A', sizeof(fpbuf) - 1); 34 fpbuf[sizeof(fpbuf) - 1] = '\0'; 35 36 fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); 37 ATF_REQUIRE(fp != NULL); 38 39 return (fp); 40 } 41 42 /* 43 * Create a new symlink to use for readlink(2) style tests, we'll just use a 44 * random target name to have something interesting to look at. 45 */ 46 static const char * __unused 47 new_symlink(size_t __len) 48 { 49 static const char linkname[] = "link"; 50 char target[MAXNAMLEN]; 51 int error; 52 53 ATF_REQUIRE(__len <= sizeof(target)); 54 55 arc4random_buf(target, sizeof(target)); 56 57 error = unlink(linkname); 58 ATF_REQUIRE(error == 0 || errno == ENOENT); 59 60 error = symlink(target, linkname); 61 ATF_REQUIRE(error == 0); 62 63 return (linkname); 64 } 65 66 /* 67 * Constructs a tmpfile that we can use for testing read(2) and friends. 68 */ 69 static int __unused 70 new_tmpfile(void) 71 { 72 char buf[1024]; 73 ssize_t rv; 74 size_t written; 75 int fd; 76 77 fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); 78 ATF_REQUIRE(fd >= 0); 79 80 written = 0; 81 while (written < TMPFILE_SIZE) { 82 rv = write(fd, buf, sizeof(buf)); 83 ATF_REQUIRE(rv > 0); 84 85 written += rv; 86 } 87 88 ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); 89 return (fd); 90 } 91 92 static void 93 disable_coredumps(void) 94 { 95 struct rlimit rl = { 0 }; 96 97 if (setrlimit(RLIMIT_CORE, &rl) == -1) 98 _exit(EX_OSERR); 99 } 100 101 /* 102 * Replaces stdin with a file that we can actually read from, for tests where 103 * we want a FILE * or fd that we can get data from. 104 */ 105 static void __unused 106 replace_stdin(void) 107 { 108 int fd; 109 110 fd = new_tmpfile(); 111 112 (void)dup2(fd, STDIN_FILENO); 113 if (fd != STDIN_FILENO) 114 close(fd); 115 } 116 117 ATF_TC_WITHOUT_HEAD(arc4random_buf_before_end); 118 ATF_TC_BODY(arc4random_buf_before_end, tc) 119 { 120 #define BUF &__stack.__buf 121 struct { 122 uint8_t padding_l; 123 unsigned char __buf[42]; 124 uint8_t padding_r; 125 } __stack; 126 const size_t __bufsz __unused = sizeof(__stack.__buf); 127 const size_t __len = 42 - 1; 128 const size_t __idx __unused = __len - 1; 129 130 arc4random_buf(__stack.__buf, __len); 131 #undef BUF 132 133 } 134 135 ATF_TC_WITHOUT_HEAD(arc4random_buf_end); 136 ATF_TC_BODY(arc4random_buf_end, tc) 137 { 138 #define BUF &__stack.__buf 139 struct { 140 uint8_t padding_l; 141 unsigned char __buf[42]; 142 uint8_t padding_r; 143 } __stack; 144 const size_t __bufsz __unused = sizeof(__stack.__buf); 145 const size_t __len = 42; 146 const size_t __idx __unused = __len - 1; 147 148 arc4random_buf(__stack.__buf, __len); 149 #undef BUF 150 151 } 152 153 ATF_TC_WITHOUT_HEAD(arc4random_buf_heap_before_end); 154 ATF_TC_BODY(arc4random_buf_heap_before_end, tc) 155 { 156 #define BUF __stack.__buf 157 struct { 158 uint8_t padding_l; 159 unsigned char * __buf; 160 uint8_t padding_r; 161 } __stack; 162 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); 163 const size_t __len = 42 - 1; 164 const size_t __idx __unused = __len - 1; 165 166 __stack.__buf = malloc(__bufsz); 167 168 arc4random_buf(__stack.__buf, __len); 169 #undef BUF 170 171 } 172 173 ATF_TC_WITHOUT_HEAD(arc4random_buf_heap_end); 174 ATF_TC_BODY(arc4random_buf_heap_end, tc) 175 { 176 #define BUF __stack.__buf 177 struct { 178 uint8_t padding_l; 179 unsigned char * __buf; 180 uint8_t padding_r; 181 } __stack; 182 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); 183 const size_t __len = 42; 184 const size_t __idx __unused = __len - 1; 185 186 __stack.__buf = malloc(__bufsz); 187 188 arc4random_buf(__stack.__buf, __len); 189 #undef BUF 190 191 } 192 193 ATF_TC_WITHOUT_HEAD(arc4random_buf_heap_after_end); 194 ATF_TC_BODY(arc4random_buf_heap_after_end, tc) 195 { 196 #define BUF __stack.__buf 197 struct { 198 uint8_t padding_l; 199 unsigned char * __buf; 200 uint8_t padding_r; 201 } __stack; 202 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); 203 const size_t __len = 42 + 1; 204 const size_t __idx __unused = __len - 1; 205 pid_t __child; 206 int __status; 207 208 __child = fork(); 209 ATF_REQUIRE(__child >= 0); 210 if (__child > 0) 211 goto monitor; 212 213 /* Child */ 214 disable_coredumps(); 215 __stack.__buf = malloc(__bufsz); 216 217 arc4random_buf(__stack.__buf, __len); 218 _exit(EX_SOFTWARE); /* Should have aborted. */ 219 220 monitor: 221 while (waitpid(__child, &__status, 0) != __child) { 222 ATF_REQUIRE_EQ(EINTR, errno); 223 } 224 225 if (!WIFSIGNALED(__status)) { 226 switch (WEXITSTATUS(__status)) { 227 case EX_SOFTWARE: 228 atf_tc_fail("FORTIFY_SOURCE failed to abort"); 229 break; 230 case EX_OSERR: 231 atf_tc_fail("setrlimit(2) failed"); 232 break; 233 default: 234 atf_tc_fail("child exited with status %d", 235 WEXITSTATUS(__status)); 236 } 237 } else { 238 ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); 239 } 240 #undef BUF 241 242 } 243 244 ATF_TC_WITHOUT_HEAD(realpath_before_end); 245 ATF_TC_BODY(realpath_before_end, tc) 246 { 247 #define BUF &__stack.__buf 248 struct { 249 uint8_t padding_l; 250 unsigned char __buf[PATH_MAX + 1]; 251 uint8_t padding_r; 252 } __stack; 253 const size_t __bufsz __unused = sizeof(__stack.__buf); 254 const size_t __len = PATH_MAX + 1; 255 const size_t __idx __unused = __len - 1; 256 257 realpath(".", __stack.__buf); 258 #undef BUF 259 260 } 261 262 ATF_TC_WITHOUT_HEAD(realpath_end); 263 ATF_TC_BODY(realpath_end, tc) 264 { 265 #define BUF &__stack.__buf 266 struct { 267 uint8_t padding_l; 268 unsigned char __buf[PATH_MAX]; 269 uint8_t padding_r; 270 } __stack; 271 const size_t __bufsz __unused = sizeof(__stack.__buf); 272 const size_t __len = PATH_MAX; 273 const size_t __idx __unused = __len - 1; 274 275 realpath(".", __stack.__buf); 276 #undef BUF 277 278 } 279 280 ATF_TC_WITHOUT_HEAD(realpath_heap_before_end); 281 ATF_TC_BODY(realpath_heap_before_end, tc) 282 { 283 #define BUF __stack.__buf 284 struct { 285 uint8_t padding_l; 286 unsigned char * __buf; 287 uint8_t padding_r; 288 } __stack; 289 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX + 1); 290 const size_t __len = PATH_MAX + 1; 291 const size_t __idx __unused = __len - 1; 292 293 __stack.__buf = malloc(__bufsz); 294 295 realpath(".", __stack.__buf); 296 #undef BUF 297 298 } 299 300 ATF_TC_WITHOUT_HEAD(realpath_heap_end); 301 ATF_TC_BODY(realpath_heap_end, tc) 302 { 303 #define BUF __stack.__buf 304 struct { 305 uint8_t padding_l; 306 unsigned char * __buf; 307 uint8_t padding_r; 308 } __stack; 309 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX); 310 const size_t __len = PATH_MAX; 311 const size_t __idx __unused = __len - 1; 312 313 __stack.__buf = malloc(__bufsz); 314 315 realpath(".", __stack.__buf); 316 #undef BUF 317 318 } 319 320 ATF_TC_WITHOUT_HEAD(realpath_heap_after_end); 321 ATF_TC_BODY(realpath_heap_after_end, tc) 322 { 323 #define BUF __stack.__buf 324 struct { 325 uint8_t padding_l; 326 unsigned char * __buf; 327 uint8_t padding_r; 328 } __stack; 329 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX - 1); 330 const size_t __len = PATH_MAX - 1; 331 const size_t __idx __unused = __len - 1; 332 pid_t __child; 333 int __status; 334 335 __child = fork(); 336 ATF_REQUIRE(__child >= 0); 337 if (__child > 0) 338 goto monitor; 339 340 /* Child */ 341 disable_coredumps(); 342 __stack.__buf = malloc(__bufsz); 343 344 realpath(".", __stack.__buf); 345 _exit(EX_SOFTWARE); /* Should have aborted. */ 346 347 monitor: 348 while (waitpid(__child, &__status, 0) != __child) { 349 ATF_REQUIRE_EQ(EINTR, errno); 350 } 351 352 if (!WIFSIGNALED(__status)) { 353 switch (WEXITSTATUS(__status)) { 354 case EX_SOFTWARE: 355 atf_tc_fail("FORTIFY_SOURCE failed to abort"); 356 break; 357 case EX_OSERR: 358 atf_tc_fail("setrlimit(2) failed"); 359 break; 360 default: 361 atf_tc_fail("child exited with status %d", 362 WEXITSTATUS(__status)); 363 } 364 } else { 365 ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); 366 } 367 #undef BUF 368 369 } 370 371 ATF_TP_ADD_TCS(tp) 372 { 373 ATF_TP_ADD_TC(tp, arc4random_buf_before_end); 374 ATF_TP_ADD_TC(tp, arc4random_buf_end); 375 ATF_TP_ADD_TC(tp, arc4random_buf_heap_before_end); 376 ATF_TP_ADD_TC(tp, arc4random_buf_heap_end); 377 ATF_TP_ADD_TC(tp, arc4random_buf_heap_after_end); 378 ATF_TP_ADD_TC(tp, realpath_before_end); 379 ATF_TP_ADD_TC(tp, realpath_end); 380 ATF_TP_ADD_TC(tp, realpath_heap_before_end); 381 ATF_TP_ADD_TC(tp, realpath_heap_end); 382 ATF_TP_ADD_TC(tp, realpath_heap_after_end); 383 return (atf_no_error()); 384 } 385