1 /* @generated by `generate-fortify-tests.lua "stdio"` */ 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(sprintf_before_end); 83 ATF_TC_BODY(sprintf_before_end, tc) 84 { 85 #define BUF &__stack.__buf 86 struct { 87 uint8_t padding_l; 88 unsigned char __buf[42]; 89 uint8_t padding_r; 90 } __stack; 91 const size_t __bufsz __unused = sizeof(__stack.__buf); 92 const size_t __len = 42 - 1; 93 const size_t __idx __unused = __len - 1; 94 char srcvar[__len + 10]; 95 96 memset(srcvar, 'A', sizeof(srcvar) - 1); 97 srcvar[sizeof(srcvar) - 1] = '\0'; 98 99 sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); 100 #undef BUF 101 102 } 103 104 ATF_TC_WITHOUT_HEAD(sprintf_end); 105 ATF_TC_BODY(sprintf_end, tc) 106 { 107 #define BUF &__stack.__buf 108 struct { 109 uint8_t padding_l; 110 unsigned char __buf[42]; 111 uint8_t padding_r; 112 } __stack; 113 const size_t __bufsz __unused = sizeof(__stack.__buf); 114 const size_t __len = 42; 115 const size_t __idx __unused = __len - 1; 116 char srcvar[__len + 10]; 117 118 memset(srcvar, 'A', sizeof(srcvar) - 1); 119 srcvar[sizeof(srcvar) - 1] = '\0'; 120 121 sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); 122 #undef BUF 123 124 } 125 126 ATF_TC_WITHOUT_HEAD(sprintf_heap_before_end); 127 ATF_TC_BODY(sprintf_heap_before_end, tc) 128 { 129 #define BUF __stack.__buf 130 struct { 131 uint8_t padding_l; 132 unsigned char * __buf; 133 uint8_t padding_r; 134 } __stack; 135 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); 136 const size_t __len = 42 - 1; 137 const size_t __idx __unused = __len - 1; 138 char srcvar[__len + 10]; 139 140 __stack.__buf = malloc(__bufsz); 141 memset(srcvar, 'A', sizeof(srcvar) - 1); 142 srcvar[sizeof(srcvar) - 1] = '\0'; 143 144 sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); 145 #undef BUF 146 147 } 148 149 ATF_TC_WITHOUT_HEAD(sprintf_heap_end); 150 ATF_TC_BODY(sprintf_heap_end, tc) 151 { 152 #define BUF __stack.__buf 153 struct { 154 uint8_t padding_l; 155 unsigned char * __buf; 156 uint8_t padding_r; 157 } __stack; 158 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); 159 const size_t __len = 42; 160 const size_t __idx __unused = __len - 1; 161 char srcvar[__len + 10]; 162 163 __stack.__buf = malloc(__bufsz); 164 memset(srcvar, 'A', sizeof(srcvar) - 1); 165 srcvar[sizeof(srcvar) - 1] = '\0'; 166 167 sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); 168 #undef BUF 169 170 } 171 172 ATF_TC_WITHOUT_HEAD(sprintf_heap_after_end); 173 ATF_TC_BODY(sprintf_heap_after_end, tc) 174 { 175 #define BUF __stack.__buf 176 struct { 177 uint8_t padding_l; 178 unsigned char * __buf; 179 uint8_t padding_r; 180 } __stack; 181 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); 182 const size_t __len = 42 + 1; 183 const size_t __idx __unused = __len - 1; 184 pid_t __child; 185 int __status; 186 char srcvar[__len + 10]; 187 188 __child = fork(); 189 ATF_REQUIRE(__child >= 0); 190 if (__child > 0) 191 goto monitor; 192 193 /* Child */ 194 disable_coredumps(); 195 __stack.__buf = malloc(__bufsz); 196 memset(srcvar, 'A', sizeof(srcvar) - 1); 197 srcvar[sizeof(srcvar) - 1] = '\0'; 198 199 sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); 200 _exit(EX_SOFTWARE); /* Should have aborted. */ 201 202 monitor: 203 while (waitpid(__child, &__status, 0) != __child) { 204 ATF_REQUIRE_EQ(EINTR, errno); 205 } 206 207 if (!WIFSIGNALED(__status)) { 208 switch (WEXITSTATUS(__status)) { 209 case EX_SOFTWARE: 210 atf_tc_fail("FORTIFY_SOURCE failed to abort"); 211 break; 212 case EX_OSERR: 213 atf_tc_fail("setrlimit(2) failed"); 214 break; 215 default: 216 atf_tc_fail("child exited with status %d", 217 WEXITSTATUS(__status)); 218 } 219 } else { 220 ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); 221 } 222 #undef BUF 223 224 } 225 226 ATF_TC_WITHOUT_HEAD(snprintf_before_end); 227 ATF_TC_BODY(snprintf_before_end, tc) 228 { 229 #define BUF &__stack.__buf 230 struct { 231 uint8_t padding_l; 232 unsigned char __buf[42]; 233 uint8_t padding_r; 234 } __stack; 235 const size_t __bufsz __unused = sizeof(__stack.__buf); 236 const size_t __len = 42 - 1; 237 const size_t __idx __unused = __len - 1; 238 char srcvar[__len + 10]; 239 240 memset(srcvar, 'A', sizeof(srcvar) - 1); 241 srcvar[sizeof(srcvar) - 1] = '\0'; 242 243 snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); 244 #undef BUF 245 246 } 247 248 ATF_TC_WITHOUT_HEAD(snprintf_end); 249 ATF_TC_BODY(snprintf_end, tc) 250 { 251 #define BUF &__stack.__buf 252 struct { 253 uint8_t padding_l; 254 unsigned char __buf[42]; 255 uint8_t padding_r; 256 } __stack; 257 const size_t __bufsz __unused = sizeof(__stack.__buf); 258 const size_t __len = 42; 259 const size_t __idx __unused = __len - 1; 260 char srcvar[__len + 10]; 261 262 memset(srcvar, 'A', sizeof(srcvar) - 1); 263 srcvar[sizeof(srcvar) - 1] = '\0'; 264 265 snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); 266 #undef BUF 267 268 } 269 270 ATF_TC_WITHOUT_HEAD(snprintf_heap_before_end); 271 ATF_TC_BODY(snprintf_heap_before_end, tc) 272 { 273 #define BUF __stack.__buf 274 struct { 275 uint8_t padding_l; 276 unsigned char * __buf; 277 uint8_t padding_r; 278 } __stack; 279 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); 280 const size_t __len = 42 - 1; 281 const size_t __idx __unused = __len - 1; 282 char srcvar[__len + 10]; 283 284 __stack.__buf = malloc(__bufsz); 285 memset(srcvar, 'A', sizeof(srcvar) - 1); 286 srcvar[sizeof(srcvar) - 1] = '\0'; 287 288 snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); 289 #undef BUF 290 291 } 292 293 ATF_TC_WITHOUT_HEAD(snprintf_heap_end); 294 ATF_TC_BODY(snprintf_heap_end, tc) 295 { 296 #define BUF __stack.__buf 297 struct { 298 uint8_t padding_l; 299 unsigned char * __buf; 300 uint8_t padding_r; 301 } __stack; 302 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); 303 const size_t __len = 42; 304 const size_t __idx __unused = __len - 1; 305 char srcvar[__len + 10]; 306 307 __stack.__buf = malloc(__bufsz); 308 memset(srcvar, 'A', sizeof(srcvar) - 1); 309 srcvar[sizeof(srcvar) - 1] = '\0'; 310 311 snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); 312 #undef BUF 313 314 } 315 316 ATF_TC_WITHOUT_HEAD(snprintf_heap_after_end); 317 ATF_TC_BODY(snprintf_heap_after_end, tc) 318 { 319 #define BUF __stack.__buf 320 struct { 321 uint8_t padding_l; 322 unsigned char * __buf; 323 uint8_t padding_r; 324 } __stack; 325 const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); 326 const size_t __len = 42 + 1; 327 const size_t __idx __unused = __len - 1; 328 pid_t __child; 329 int __status; 330 char srcvar[__len + 10]; 331 332 __child = fork(); 333 ATF_REQUIRE(__child >= 0); 334 if (__child > 0) 335 goto monitor; 336 337 /* Child */ 338 disable_coredumps(); 339 __stack.__buf = malloc(__bufsz); 340 memset(srcvar, 'A', sizeof(srcvar) - 1); 341 srcvar[sizeof(srcvar) - 1] = '\0'; 342 343 snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); 344 _exit(EX_SOFTWARE); /* Should have aborted. */ 345 346 monitor: 347 while (waitpid(__child, &__status, 0) != __child) { 348 ATF_REQUIRE_EQ(EINTR, errno); 349 } 350 351 if (!WIFSIGNALED(__status)) { 352 switch (WEXITSTATUS(__status)) { 353 case EX_SOFTWARE: 354 atf_tc_fail("FORTIFY_SOURCE failed to abort"); 355 break; 356 case EX_OSERR: 357 atf_tc_fail("setrlimit(2) failed"); 358 break; 359 default: 360 atf_tc_fail("child exited with status %d", 361 WEXITSTATUS(__status)); 362 } 363 } else { 364 ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); 365 } 366 #undef BUF 367 368 } 369 370 ATF_TP_ADD_TCS(tp) 371 { 372 ATF_TP_ADD_TC(tp, sprintf_before_end); 373 ATF_TP_ADD_TC(tp, sprintf_end); 374 ATF_TP_ADD_TC(tp, sprintf_heap_before_end); 375 ATF_TP_ADD_TC(tp, sprintf_heap_end); 376 ATF_TP_ADD_TC(tp, sprintf_heap_after_end); 377 ATF_TP_ADD_TC(tp, snprintf_before_end); 378 ATF_TP_ADD_TC(tp, snprintf_end); 379 ATF_TP_ADD_TC(tp, snprintf_heap_before_end); 380 ATF_TP_ADD_TC(tp, snprintf_heap_end); 381 ATF_TP_ADD_TC(tp, snprintf_heap_after_end); 382 return (atf_no_error()); 383 } 384