nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 1256 lines 36 kB view raw
1{ 2 lib, 3 stdenv, 4 runCommand, 5 runCommandWith, 6 runCommandCC, 7 writeText, 8 bintools, 9 hello, 10 debian-devscripts, 11}: 12 13let 14 # writeCBin from trivial-builders won't let us choose 15 # our own stdenv 16 writeCBinWithStdenv = 17 codePath: stdenv': env: 18 runCommandWith 19 { 20 name = "test-bin"; 21 stdenv = stdenv'; 22 derivationArgs = { 23 inherit codePath; 24 preferLocalBuild = true; 25 allowSubstitutes = false; 26 } 27 // env; 28 } 29 '' 30 [ -n "$postConfigure" ] && eval "$postConfigure" 31 [ -n "$preBuild" ] && eval "$preBuild" 32 n=$out/bin/test-bin 33 mkdir -p "$(dirname "$n")" 34 cp "$codePath" . 35 NIX_DEBUG=1 $CC -x ''${TEST_SOURCE_LANG:-c} "$(basename $codePath)" -O1 $TEST_EXTRA_FLAGS -o "$n" 36 ''; 37 38 f1exampleWithStdEnv = writeCBinWithStdenv ./fortify1-example.c; 39 f2exampleWithStdEnv = writeCBinWithStdenv ./fortify2-example.c; 40 f3exampleWithStdEnv = writeCBinWithStdenv ./fortify3-example.c; 41 42 flexArrF2ExampleWithStdEnv = writeCBinWithStdenv ./flex-arrays-fortify-example.c; 43 44 # we don't really have a reliable property for testing for 45 # libstdc++ we'll just have to check for the absence of libcxx 46 checkGlibcxxassertionsWithStdEnv = 47 expectDefined: stdenv': derivationArgs: 48 brokenIf (stdenv.cc.libcxx != null) ( 49 writeCBinWithStdenv 50 (writeText "main.cpp" '' 51 #if${if expectDefined then "n" else ""}def _GLIBCXX_ASSERTIONS 52 #error "Expected _GLIBCXX_ASSERTIONS to be ${if expectDefined then "" else "un"}defined" 53 #endif 54 int main() {} 55 '') 56 stdenv' 57 ( 58 derivationArgs 59 // { 60 env = (derivationArgs.env or { }) // { 61 TEST_SOURCE_LANG = derivationArgs.env.TEST_SOURCE_LANG or "c++"; 62 }; 63 } 64 ) 65 ); 66 67 checkLibcxxHardeningWithStdEnv = 68 expectValue: stdenv': env: 69 brokenIf (stdenv.cc.libcxx == null) ( 70 writeCBinWithStdenv 71 (writeText "main.cpp" ( 72 '' 73 #include <limits> 74 #ifndef _LIBCPP_HARDENING_MODE 75 #error "Expected _LIBCPP_HARDENING_MODE to be defined" 76 #endif 77 #ifndef ${expectValue} 78 #error "Expected ${expectValue} to be defined" 79 #endif 80 81 #if _LIBCPP_HARDENING_MODE != ${expectValue} 82 #error "Expected _LIBCPP_HARDENING_MODE to equal ${expectValue}" 83 #endif 84 '' 85 + '' 86 int main() {} 87 '' 88 )) 89 stdenv' 90 ( 91 env 92 // { 93 env = (env.env or { }) // { 94 TEST_SOURCE_LANG = env.env.TEST_SOURCE_LANG or "c++"; 95 }; 96 } 97 ) 98 ); 99 100 # for when we need a slightly more complicated program 101 helloWithStdEnv = 102 stdenv': env: 103 (hello.override { stdenv = stdenv'; }).overrideAttrs ( 104 { 105 preBuild = '' 106 export CFLAGS="$TEST_EXTRA_FLAGS" 107 ''; 108 NIX_DEBUG = "1"; 109 postFixup = '' 110 cp $out/bin/hello $out/bin/test-bin 111 ''; 112 } 113 // env 114 ); 115 116 stdenvUnsupport = 117 additionalUnsupported: 118 stdenv.override { 119 cc = stdenv.cc.override { 120 cc = ( 121 lib.extendDerivation true rec { 122 # this is ugly - have to cross-reference from 123 # hardeningUnsupportedFlagsByTargetPlatform to hardeningUnsupportedFlags 124 # because the finalAttrs mechanism that hardeningUnsupportedFlagsByTargetPlatform 125 # implementations use to do this won't work with lib.extendDerivation. 126 # but it's simplified by the fact that targetPlatform is already fixed 127 # at this point. 128 hardeningUnsupportedFlagsByTargetPlatform = _: hardeningUnsupportedFlags; 129 hardeningUnsupportedFlags = 130 ( 131 if stdenv.cc.cc ? hardeningUnsupportedFlagsByTargetPlatform then 132 stdenv.cc.cc.hardeningUnsupportedFlagsByTargetPlatform stdenv.targetPlatform 133 else 134 (stdenv.cc.cc.hardeningUnsupportedFlags or [ ]) 135 ) 136 ++ additionalUnsupported; 137 } stdenv.cc.cc 138 ); 139 }; 140 allowedRequisites = null; 141 }; 142 143 checkTestBin = 144 testBin: 145 { 146 # can only test flags that are detectable by hardening-check 147 ignoreBindNow ? true, 148 ignoreFortify ? true, 149 ignorePie ? true, 150 ignoreRelRO ? true, 151 ignoreStackProtector ? true, 152 ignoreStackClashProtection ? true, 153 expectFailure ? false, 154 }: 155 let 156 stackClashStr = "Stack clash protection: yes"; 157 expectFailureClause = lib.optionalString expectFailure " && echo 'ERROR: Expected hardening-check to fail, but it passed!' >&2 && false"; 158 in 159 runCommandCC "check-test-bin" 160 { 161 nativeBuildInputs = [ debian-devscripts ]; 162 buildInputs = [ testBin ]; 163 meta = { 164 platforms = 165 if ignoreStackClashProtection then 166 lib.platforms.linux # ELF-reliant 167 else 168 [ "x86_64-linux" ]; # stackclashprotection test looks for x86-specific instructions 169 # musl implementation of fortify undetectable by this means even if present, 170 # static similarly 171 broken = (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isStatic) && !ignoreFortify; 172 }; 173 } 174 ( 175 '' 176 if ${lib.optionalString (!expectFailure) "!"} { 177 hardening-check --nocfprotection --nobranchprotection \ 178 ${lib.optionalString ignoreBindNow "--nobindnow"} \ 179 ${lib.optionalString ignoreFortify "--nofortify"} \ 180 ${lib.optionalString ignorePie "--nopie"} \ 181 ${lib.optionalString ignoreRelRO "--norelro"} \ 182 ${lib.optionalString ignoreStackProtector "--nostackprotector"} \ 183 $(PATH=$HOST_PATH type -P test-bin) | tee $out 184 '' 185 + lib.optionalString (!ignoreStackClashProtection) '' 186 # stack clash protection doesn't actually affect the exit code of 187 # hardening-check (likely authors think false negatives too common) 188 { grep -F '${stackClashStr}' $out || { echo "Didn't find '${stackClashStr}' in output" && false ;} ;} 189 '' 190 + '' 191 } ; then 192 '' 193 + lib.optionalString expectFailure '' 194 echo 'ERROR: Expected hardening-check to fail, but it passed!' >&2 195 '' 196 + '' 197 exit 2 198 fi 199 '' 200 ); 201 202 nameDrvAfterAttrName = builtins.mapAttrs ( 203 name: drv: 204 drv.overrideAttrs (_: { 205 name = "test-${name}"; 206 }) 207 ); 208 209 fortifyExecTest = fortifyExecTestFull true "012345 7" "0123456 7"; 210 211 # returning a specific exit code when aborting due to a fortify 212 # check isn't mandated. so it's better to just ensure that a 213 # nonzero exit code is returned when we go a single byte beyond 214 # the buffer, with the example programs being designed to be 215 # unlikely to genuinely segfault for such a small overflow. 216 fortifyExecTestFull = 217 expectProtection: saturatedArgs: oneTooFarArgs: testBin: 218 runCommand "exec-test" 219 { 220 buildInputs = [ 221 testBin 222 ]; 223 meta.broken = !(stdenv.buildPlatform.canExecute stdenv.hostPlatform); 224 } 225 '' 226 ( 227 export PATH=$HOST_PATH 228 echo "Saturated buffer:" # check program isn't completly broken 229 test-bin ${saturatedArgs} 230 echo "One byte too far:" # overflow byte being the null terminator? 231 ( 232 ${if expectProtection then "!" else ""} test-bin ${oneTooFarArgs} 233 ) || ( 234 echo 'Expected ${if expectProtection then "failure" else "success"}, but ${ 235 if expectProtection then "succeeded" else "failed" 236 }!' && exit 1 237 ) 238 ) 239 echo "Expected behaviour observed" 240 touch $out 241 ''; 242 243 brokenIf = 244 cond: drv: 245 if cond then 246 drv.overrideAttrs (old: { 247 meta = old.meta or { } // { 248 broken = true; 249 }; 250 }) 251 else 252 drv; 253 overridePlatforms = 254 platforms: drv: 255 drv.overrideAttrs (old: { 256 meta = old.meta or { } // { 257 inherit platforms; 258 }; 259 }); 260 261 instructionPresenceTest = 262 label: mnemonicPattern: testBin: expectFailure: 263 runCommand "${label}-instr-test" 264 { 265 nativeBuildInputs = [ 266 bintools 267 ]; 268 buildInputs = [ 269 testBin 270 ]; 271 } 272 '' 273 touch $out 274 if $OBJDUMP -d \ 275 --no-addresses \ 276 --no-show-raw-insn \ 277 "$(PATH=$HOST_PATH type -P test-bin)" \ 278 | grep -E '${mnemonicPattern}' > /dev/null ; then 279 echo "Found ${label} instructions" >&2 280 ${lib.optionalString expectFailure "exit 1"} 281 else 282 echo "Did not find ${label} instructions" >&2 283 ${lib.optionalString (!expectFailure) "exit 1"} 284 fi 285 ''; 286 287 pacRetTest = 288 testBin: expectFailure: 289 overridePlatforms [ "aarch64-linux" ] ( 290 instructionPresenceTest "pacret" "\\bpaciasp\\b" testBin expectFailure 291 ); 292 293 elfNoteTest = 294 label: pattern: testBin: expectFailure: 295 runCommand "${label}-elf-note-test" 296 { 297 nativeBuildInputs = [ 298 bintools 299 ]; 300 buildInputs = [ 301 testBin 302 ]; 303 } 304 '' 305 touch $out 306 if $READELF -n "$(PATH=$HOST_PATH type -P test-bin)" \ 307 | grep -E '${pattern}' > /dev/null ; then 308 echo "Found ${label} note" >&2 309 ${lib.optionalString expectFailure "exit 1"} 310 else 311 echo "Did not find ${label} note" >&2 312 ${lib.optionalString (!expectFailure) "exit 1"} 313 fi 314 ''; 315 316 shadowStackTest = 317 testBin: expectFailure: 318 brokenIf stdenv.hostPlatform.isMusl ( 319 overridePlatforms [ "x86_64-linux" ] (elfNoteTest "shadowstack" "\\bSHSTK\\b" testBin expectFailure) 320 ); 321 322in 323nameDrvAfterAttrName ( 324 { 325 bindNowExplicitEnabled = brokenIf stdenv.hostPlatform.isStatic ( 326 checkTestBin 327 (f2exampleWithStdEnv stdenv { 328 hardeningEnable = [ "bindnow" ]; 329 }) 330 { 331 ignoreBindNow = false; 332 } 333 ); 334 335 fortifyExplicitEnabled = ( 336 checkTestBin 337 (f2exampleWithStdEnv stdenv { 338 hardeningEnable = [ "fortify" ]; 339 }) 340 { 341 ignoreFortify = false; 342 } 343 ); 344 345 fortify1ExplicitEnabledExecTest = fortifyExecTest ( 346 f1exampleWithStdEnv stdenv { 347 hardeningEnable = [ "fortify" ]; 348 } 349 ); 350 351 # musl implementation is effectively FORTIFY_SOURCE=1-only, 352 fortifyExplicitEnabledExecTest = brokenIf stdenv.hostPlatform.isMusl ( 353 fortifyExecTest ( 354 f2exampleWithStdEnv stdenv { 355 hardeningEnable = [ "fortify" ]; 356 } 357 ) 358 ); 359 360 fortify3ExplicitEnabled = brokenIf (!stdenv.cc.isGNU || lib.versionOlder stdenv.cc.version "12") ( 361 checkTestBin 362 (f3exampleWithStdEnv stdenv { 363 hardeningEnable = [ "fortify3" ]; 364 }) 365 { 366 ignoreFortify = false; 367 } 368 ); 369 370 # musl implementation is effectively FORTIFY_SOURCE=1-only 371 fortify3ExplicitEnabledExecTest = 372 brokenIf (stdenv.hostPlatform.isMusl || !stdenv.cc.isGNU || lib.versionOlder stdenv.cc.version "12") 373 ( 374 fortifyExecTest ( 375 f3exampleWithStdEnv stdenv { 376 hardeningEnable = [ "fortify3" ]; 377 } 378 ) 379 ); 380 381 sfa1explicitEnabled = 382 checkTestBin 383 (flexArrF2ExampleWithStdEnv stdenv { 384 hardeningEnable = [ 385 "fortify" 386 "strictflexarrays1" 387 ]; 388 env = { 389 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=7"; 390 }; 391 }) 392 { 393 ignoreFortify = false; 394 }; 395 396 # musl implementation is effectively FORTIFY_SOURCE=1-only 397 sfa1explicitEnabledExecTest = brokenIf stdenv.hostPlatform.isMusl ( 398 fortifyExecTestFull true "012345" "0123456" ( 399 flexArrF2ExampleWithStdEnv stdenv { 400 hardeningEnable = [ 401 "fortify" 402 "strictflexarrays1" 403 ]; 404 env = { 405 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=7"; 406 }; 407 } 408 ) 409 ); 410 411 sfa1explicitEnabledDoesntProtectDefLen1 = 412 checkTestBin 413 (flexArrF2ExampleWithStdEnv stdenv { 414 hardeningEnable = [ 415 "fortify" 416 "strictflexarrays1" 417 ]; 418 env = { 419 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=1"; 420 }; 421 }) 422 { 423 ignoreFortify = false; 424 expectFailure = true; 425 }; 426 427 # musl implementation is effectively FORTIFY_SOURCE=1-only 428 sfa1explicitEnabledDoesntProtectDefLen1ExecTest = brokenIf stdenv.hostPlatform.isMusl ( 429 fortifyExecTestFull false "''" "0" ( 430 flexArrF2ExampleWithStdEnv stdenv { 431 hardeningEnable = [ 432 "fortify" 433 "strictflexarrays1" 434 ]; 435 env = { 436 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=1"; 437 }; 438 } 439 ) 440 ); 441 442 sfa3explicitEnabledProtectsDefLen1 = 443 checkTestBin 444 (flexArrF2ExampleWithStdEnv stdenv { 445 hardeningEnable = [ 446 "fortify" 447 "strictflexarrays3" 448 ]; 449 env = { 450 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=1"; 451 }; 452 }) 453 { 454 ignoreFortify = false; 455 }; 456 457 # musl implementation is effectively FORTIFY_SOURCE=1-only 458 sfa3explicitEnabledProtectsDefLen1ExecTest = brokenIf stdenv.hostPlatform.isMusl ( 459 fortifyExecTestFull true "''" "0" ( 460 flexArrF2ExampleWithStdEnv stdenv { 461 hardeningEnable = [ 462 "fortify" 463 "strictflexarrays3" 464 ]; 465 env = { 466 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=1"; 467 }; 468 } 469 ) 470 ); 471 472 sfa3explicitEnabledDoesntProtectCorrectFlex = 473 checkTestBin 474 (flexArrF2ExampleWithStdEnv stdenv { 475 hardeningEnable = [ 476 "fortify" 477 "strictflexarrays3" 478 ]; 479 env = { 480 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE="; 481 }; 482 }) 483 { 484 ignoreFortify = false; 485 expectFailure = true; 486 }; 487 488 # musl implementation is effectively FORTIFY_SOURCE=1-only 489 sfa3explicitEnabledDoesntProtectCorrectFlexExecTest = brokenIf stdenv.hostPlatform.isMusl ( 490 fortifyExecTestFull false "" "0" ( 491 flexArrF2ExampleWithStdEnv stdenv { 492 hardeningEnable = [ 493 "fortify" 494 "strictflexarrays3" 495 ]; 496 env = { 497 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE="; 498 }; 499 } 500 ) 501 ); 502 503 pieAlwaysEnabled = brokenIf stdenv.hostPlatform.isStatic ( 504 checkTestBin (f2exampleWithStdEnv stdenv { }) { 505 ignorePie = false; 506 } 507 ); 508 509 relROExplicitEnabled = 510 checkTestBin 511 (f2exampleWithStdEnv stdenv { 512 hardeningEnable = [ "relro" ]; 513 }) 514 { 515 ignoreRelRO = false; 516 }; 517 518 stackProtectorExplicitEnabled = brokenIf stdenv.hostPlatform.isStatic ( 519 checkTestBin 520 (f2exampleWithStdEnv stdenv { 521 hardeningEnable = [ "stackprotector" ]; 522 }) 523 { 524 ignoreStackProtector = false; 525 } 526 ); 527 528 # protection patterns generated by clang not detectable? 529 stackClashProtectionExplicitEnabled = brokenIf stdenv.cc.isClang ( 530 checkTestBin 531 (helloWithStdEnv stdenv { 532 hardeningEnable = [ "stackclashprotection" ]; 533 }) 534 { 535 ignoreStackClashProtection = false; 536 } 537 ); 538 539 pacRetExplicitEnabled = pacRetTest (helloWithStdEnv stdenv { 540 hardeningEnable = [ "pacret" ]; 541 }) false; 542 543 shadowStackExplicitEnabled = shadowStackTest (f1exampleWithStdEnv stdenv { 544 hardeningEnable = [ "shadowstack" ]; 545 }) false; 546 547 glibcxxassertionsExplicitEnabled = checkGlibcxxassertionsWithStdEnv true stdenv { 548 hardeningEnable = [ "glibcxxassertions" ]; 549 }; 550 551 bindNowExplicitDisabled = 552 checkTestBin 553 (f2exampleWithStdEnv stdenv { 554 hardeningDisable = [ "bindnow" ]; 555 }) 556 { 557 ignoreBindNow = false; 558 expectFailure = true; 559 }; 560 561 fortifyExplicitDisabled = 562 checkTestBin 563 (f2exampleWithStdEnv stdenv { 564 hardeningDisable = [ "fortify" ]; 565 }) 566 { 567 ignoreFortify = false; 568 expectFailure = true; 569 }; 570 571 fortify3ExplicitDisabled = 572 checkTestBin 573 (f3exampleWithStdEnv stdenv { 574 hardeningDisable = [ "fortify3" ]; 575 }) 576 { 577 ignoreFortify = false; 578 expectFailure = true; 579 }; 580 581 fortifyExplicitDisabledDisablesFortify3 = 582 checkTestBin 583 (f3exampleWithStdEnv stdenv { 584 hardeningEnable = [ "fortify3" ]; 585 hardeningDisable = [ "fortify" ]; 586 }) 587 { 588 ignoreFortify = false; 589 expectFailure = true; 590 }; 591 592 fortify3ExplicitDisabledDoesntDisableFortify = 593 checkTestBin 594 (f2exampleWithStdEnv stdenv { 595 hardeningEnable = [ "fortify" ]; 596 hardeningDisable = [ "fortify3" ]; 597 }) 598 { 599 ignoreFortify = false; 600 }; 601 602 # musl implementation is effectively FORTIFY_SOURCE=1-only 603 sfa1explicitDisabled = brokenIf stdenv.hostPlatform.isMusl ( 604 checkTestBin 605 (flexArrF2ExampleWithStdEnv stdenv { 606 hardeningEnable = [ "fortify" ]; 607 hardeningDisable = [ "strictflexarrays1" ]; 608 env = { 609 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=7"; 610 }; 611 }) 612 { 613 ignoreFortify = false; 614 expectFailure = true; 615 } 616 ); 617 618 sfa1explicitDisabledExecTest = fortifyExecTestFull false "012345" "0123456" ( 619 flexArrF2ExampleWithStdEnv stdenv { 620 hardeningEnable = [ "fortify" ]; 621 hardeningDisable = [ "strictflexarrays1" ]; 622 env = { 623 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=7"; 624 }; 625 } 626 ); 627 628 # musl implementation is effectively FORTIFY_SOURCE=1-only 629 sfa1explicitDisabledDisablesSfa3 = brokenIf stdenv.hostPlatform.isMusl ( 630 checkTestBin 631 (flexArrF2ExampleWithStdEnv stdenv { 632 hardeningEnable = [ 633 "fortify" 634 "strictflexarrays3" 635 ]; 636 hardeningDisable = [ "strictflexarrays1" ]; 637 env = { 638 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=1"; 639 }; 640 }) 641 { 642 ignoreFortify = false; 643 expectFailure = true; 644 } 645 ); 646 647 # musl implementation is effectively FORTIFY_SOURCE=1-only 648 sfa1explicitDisabledDisablesSfa3ExecTest = brokenIf stdenv.hostPlatform.isMusl ( 649 fortifyExecTestFull false "''" "0" ( 650 flexArrF2ExampleWithStdEnv stdenv { 651 hardeningEnable = [ 652 "fortify" 653 "strictflexarrays3" 654 ]; 655 hardeningDisable = [ "strictflexarrays1" ]; 656 env = { 657 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=1"; 658 }; 659 } 660 ) 661 ); 662 663 sfa3explicitDisabledDoesntDisableSfa1 = 664 checkTestBin 665 (flexArrF2ExampleWithStdEnv stdenv { 666 hardeningEnable = [ 667 "fortify" 668 "strictflexarrays1" 669 ]; 670 hardeningDisable = [ "strictflexarrays3" ]; 671 env = { 672 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=7"; 673 }; 674 }) 675 { 676 ignoreFortify = false; 677 }; 678 679 # musl implementation is effectively FORTIFY_SOURCE=1-only 680 sfa3explicitDisabledDoesntDisableSfa1ExecTest = brokenIf stdenv.hostPlatform.isMusl ( 681 fortifyExecTestFull true "012345" "0123456" ( 682 flexArrF2ExampleWithStdEnv stdenv { 683 hardeningEnable = [ 684 "fortify" 685 "strictflexarrays1" 686 ]; 687 hardeningDisable = [ "strictflexarrays3" ]; 688 env = { 689 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=7"; 690 }; 691 } 692 ) 693 ); 694 695 # can't force-disable ("partial"?) relro 696 relROExplicitDisabled = brokenIf true ( 697 checkTestBin 698 (f2exampleWithStdEnv stdenv { 699 }) 700 { 701 ignoreRelRO = false; 702 expectFailure = true; 703 } 704 ); 705 706 stackProtectorExplicitDisabled = 707 checkTestBin 708 (f2exampleWithStdEnv stdenv { 709 hardeningDisable = [ "stackprotector" ]; 710 }) 711 { 712 ignoreStackProtector = false; 713 expectFailure = true; 714 }; 715 716 stackClashProtectionExplicitDisabled = 717 checkTestBin 718 (helloWithStdEnv stdenv { 719 hardeningDisable = [ "stackclashprotection" ]; 720 }) 721 { 722 ignoreStackClashProtection = false; 723 expectFailure = true; 724 }; 725 726 pacRetExplicitDisabled = pacRetTest (helloWithStdEnv stdenv { 727 hardeningDisable = [ "pacret" ]; 728 }) true; 729 730 shadowStackExplicitDisabled = shadowStackTest (f1exampleWithStdEnv stdenv { 731 hardeningDisable = [ "shadowstack" ]; 732 }) true; 733 734 glibcxxassertionsExplicitDisabled = checkGlibcxxassertionsWithStdEnv false stdenv { 735 hardeningDisable = [ "glibcxxassertions" ]; 736 }; 737 738 lchFastExplicitDisabled = checkLibcxxHardeningWithStdEnv "_LIBCPP_HARDENING_MODE_NONE" stdenv { 739 hardeningDisable = [ "libcxxhardeningfast" ]; 740 }; 741 742 lchExtensiveExplicitEnabled = 743 checkLibcxxHardeningWithStdEnv "_LIBCPP_HARDENING_MODE_EXTENSIVE" stdenv 744 { 745 hardeningEnable = [ "libcxxhardeningextensive" ]; 746 }; 747 748 lchExtensiveExplicitDisabledDoesntDisableLchFast = 749 checkLibcxxHardeningWithStdEnv "_LIBCPP_HARDENING_MODE_FAST" stdenv 750 { 751 hardeningEnable = [ "libcxxhardeningfast" ]; 752 hardeningDisable = [ "libcxxhardeningextensive" ]; 753 }; 754 755 lchFastExplicitDisabledDisablesLchExtensive = 756 checkLibcxxHardeningWithStdEnv "_LIBCPP_HARDENING_MODE_NONE" stdenv 757 { 758 hardeningEnable = [ "libcxxhardeningextensive" ]; 759 hardeningDisable = [ "libcxxhardeningfast" ]; 760 }; 761 762 lchFastExtensiveExplicitEnabledResultsInLchExtensive = 763 checkLibcxxHardeningWithStdEnv "_LIBCPP_HARDENING_MODE_EXTENSIVE" stdenv 764 { 765 hardeningEnable = [ 766 "libcxxhardeningfast" 767 "libcxxhardeningextensive" 768 ]; 769 }; 770 771 lchFastExtensiveExplicitDisabledDisablesBoth = 772 checkLibcxxHardeningWithStdEnv "_LIBCPP_HARDENING_MODE_NONE" stdenv 773 { 774 hardeningDisable = [ 775 "libcxxhardeningfast" 776 "libcxxhardeningextensive" 777 ]; 778 }; 779 780 # most flags can't be "unsupported" by compiler alone and 781 # binutils doesn't have an accessible hardeningUnsupportedFlags 782 # mechanism, so can only test a couple of flags through altered 783 # stdenv trickery 784 785 fortifyStdenvUnsupp = 786 checkTestBin 787 (f2exampleWithStdEnv 788 (stdenvUnsupport [ 789 "fortify" 790 "fortify3" 791 ]) 792 { 793 hardeningEnable = [ "fortify" ]; 794 } 795 ) 796 { 797 ignoreFortify = false; 798 expectFailure = true; 799 }; 800 801 fortify3StdenvUnsupp = 802 checkTestBin 803 (f3exampleWithStdEnv (stdenvUnsupport [ "fortify3" ]) { 804 hardeningEnable = [ "fortify3" ]; 805 }) 806 { 807 ignoreFortify = false; 808 expectFailure = true; 809 }; 810 811 fortifyStdenvUnsuppUnsupportsFortify3 = 812 checkTestBin 813 (f3exampleWithStdEnv (stdenvUnsupport [ "fortify" ]) { 814 hardeningEnable = [ "fortify3" ]; 815 }) 816 { 817 ignoreFortify = false; 818 expectFailure = true; 819 }; 820 821 fortify3StdenvUnsuppDoesntUnsuppFortify1 = 822 checkTestBin 823 (f1exampleWithStdEnv (stdenvUnsupport [ "fortify3" ]) { 824 hardeningEnable = [ "fortify" ]; 825 }) 826 { 827 ignoreFortify = false; 828 }; 829 830 fortify3StdenvUnsuppDoesntUnsuppFortify1ExecTest = fortifyExecTest ( 831 f1exampleWithStdEnv (stdenvUnsupport [ "fortify3" ]) { 832 hardeningEnable = [ "fortify" ]; 833 } 834 ); 835 836 sfa1StdenvUnsupp = 837 checkTestBin 838 (flexArrF2ExampleWithStdEnv 839 (stdenvUnsupport [ 840 "strictflexarrays1" 841 "strictflexarrays3" 842 ]) 843 { 844 hardeningEnable = [ 845 "fortify" 846 "strictflexarrays1" 847 ]; 848 env = { 849 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=7"; 850 }; 851 } 852 ) 853 { 854 ignoreFortify = false; 855 expectFailure = true; 856 }; 857 858 sfa3StdenvUnsupp = 859 checkTestBin 860 (flexArrF2ExampleWithStdEnv (stdenvUnsupport [ "strictflexarrays3" ]) { 861 hardeningEnable = [ 862 "fortify" 863 "strictflexarrays3" 864 ]; 865 env = { 866 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=1"; 867 }; 868 }) 869 { 870 ignoreFortify = false; 871 expectFailure = true; 872 }; 873 874 sfa1StdenvUnsuppUnsupportsSfa3 = 875 checkTestBin 876 (flexArrF2ExampleWithStdEnv (stdenvUnsupport [ "strictflexarrays1" ]) { 877 hardeningEnable = [ 878 "fortify" 879 "strictflexarrays3" 880 ]; 881 env = { 882 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=1"; 883 }; 884 }) 885 { 886 ignoreFortify = false; 887 expectFailure = true; 888 }; 889 890 sfa3StdenvUnsuppDoesntUnsuppSfa1 = 891 checkTestBin 892 (flexArrF2ExampleWithStdEnv (stdenvUnsupport [ "strictflexarrays3" ]) { 893 hardeningEnable = [ 894 "fortify" 895 "strictflexarrays1" 896 ]; 897 env = { 898 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=7"; 899 }; 900 }) 901 { 902 ignoreFortify = false; 903 }; 904 905 # musl implementation is effectively FORTIFY_SOURCE=1-only 906 sfa3StdenvUnsuppDoesntUnsuppSfa1ExecTest = brokenIf stdenv.hostPlatform.isMusl ( 907 fortifyExecTestFull true "012345" "0123456" ( 908 flexArrF2ExampleWithStdEnv (stdenvUnsupport [ "strictflexarrays3" ]) { 909 hardeningEnable = [ 910 "fortify" 911 "strictflexarrays1" 912 ]; 913 env = { 914 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=7"; 915 }; 916 } 917 ) 918 ); 919 920 stackProtectorStdenvUnsupp = 921 checkTestBin 922 (f2exampleWithStdEnv (stdenvUnsupport [ "stackprotector" ]) { 923 hardeningEnable = [ "stackprotector" ]; 924 }) 925 { 926 ignoreStackProtector = false; 927 expectFailure = true; 928 }; 929 930 stackClashProtectionStdenvUnsupp = 931 checkTestBin 932 (helloWithStdEnv (stdenvUnsupport [ "stackclashprotection" ]) { 933 hardeningEnable = [ "stackclashprotection" ]; 934 }) 935 { 936 ignoreStackClashProtection = false; 937 expectFailure = true; 938 }; 939 940 # NIX_HARDENING_ENABLE set in the shell overrides hardeningDisable 941 # and hardeningEnable 942 943 stackProtectorReenabledEnv = 944 checkTestBin 945 (f2exampleWithStdEnv stdenv { 946 hardeningDisable = [ "stackprotector" ]; 947 postConfigure = '' 948 export NIX_HARDENING_ENABLE="stackprotector" 949 ''; 950 }) 951 { 952 ignoreStackProtector = false; 953 }; 954 955 stackProtectorReenabledFromAllEnv = 956 checkTestBin 957 (f2exampleWithStdEnv stdenv { 958 hardeningDisable = [ "all" ]; 959 postConfigure = '' 960 export NIX_HARDENING_ENABLE="stackprotector" 961 ''; 962 }) 963 { 964 ignoreStackProtector = false; 965 }; 966 967 stackProtectorRedisabledEnv = 968 checkTestBin 969 (f2exampleWithStdEnv stdenv { 970 hardeningEnable = [ "stackprotector" ]; 971 postConfigure = '' 972 export NIX_HARDENING_ENABLE="" 973 ''; 974 }) 975 { 976 ignoreStackProtector = false; 977 expectFailure = true; 978 }; 979 980 glibcxxassertionsStdenvUnsupp = 981 checkGlibcxxassertionsWithStdEnv false (stdenvUnsupport [ "glibcxxassertions" ]) 982 { 983 hardeningEnable = [ "glibcxxassertions" ]; 984 }; 985 986 lchFastStdenvUnsupp = 987 checkLibcxxHardeningWithStdEnv "_LIBCPP_HARDENING_MODE_NONE" 988 (stdenvUnsupport [ "libcxxhardeningfast" ]) 989 { 990 hardeningEnable = [ "libcxxhardeningfast" ]; 991 }; 992 993 lchFastStdenvUnsuppUnsupportsLchExtensive = 994 checkLibcxxHardeningWithStdEnv "_LIBCPP_HARDENING_MODE_NONE" 995 (stdenvUnsupport [ "libcxxhardeningfast" ]) 996 { 997 hardeningEnable = [ "libcxxhardeningextensive" ]; 998 }; 999 1000 lchExtensiveStdenvUnsuppDoesntUnsupportLchFast = 1001 checkLibcxxHardeningWithStdEnv "_LIBCPP_HARDENING_MODE_FAST" 1002 (stdenvUnsupport [ "libcxxhardeningextensive" ]) 1003 { 1004 hardeningEnable = [ 1005 "libcxxhardeningfast" 1006 "libcxxhardeningextensive" 1007 ]; 1008 }; 1009 1010 fortify3EnabledEnvEnablesFortify1 = 1011 checkTestBin 1012 (f1exampleWithStdEnv stdenv { 1013 hardeningDisable = [ 1014 "fortify" 1015 "fortify3" 1016 ]; 1017 postConfigure = '' 1018 export NIX_HARDENING_ENABLE="fortify3" 1019 ''; 1020 }) 1021 { 1022 ignoreFortify = false; 1023 }; 1024 1025 fortify3EnabledEnvEnablesFortify1ExecTest = fortifyExecTest ( 1026 f1exampleWithStdEnv stdenv { 1027 hardeningDisable = [ 1028 "fortify" 1029 "fortify3" 1030 ]; 1031 postConfigure = '' 1032 export NIX_HARDENING_ENABLE="fortify3" 1033 ''; 1034 } 1035 ); 1036 1037 fortifyEnabledEnvDoesntEnableFortify3 = 1038 checkTestBin 1039 (f3exampleWithStdEnv stdenv { 1040 hardeningDisable = [ 1041 "fortify" 1042 "fortify3" 1043 ]; 1044 postConfigure = '' 1045 export NIX_HARDENING_ENABLE="fortify" 1046 ''; 1047 }) 1048 { 1049 ignoreFortify = false; 1050 expectFailure = true; 1051 }; 1052 1053 sfa3EnabledEnvEnablesSfa1 = 1054 checkTestBin 1055 (flexArrF2ExampleWithStdEnv stdenv { 1056 hardeningDisable = [ 1057 "strictflexarrays1" 1058 "strictflexarrays3" 1059 ]; 1060 postConfigure = '' 1061 export NIX_HARDENING_ENABLE="fortify strictflexarrays3" 1062 ''; 1063 env = { 1064 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=7"; 1065 }; 1066 }) 1067 { 1068 ignoreFortify = false; 1069 }; 1070 1071 sfa3EnabledEnvEnablesSfa1ExecTest = fortifyExecTestFull true "012345" "0123456" ( 1072 f1exampleWithStdEnv stdenv { 1073 hardeningDisable = [ 1074 "strictflexarrays1" 1075 "strictflexarrays3" 1076 ]; 1077 postConfigure = '' 1078 export NIX_HARDENING_ENABLE="fortify strictflexarrays3" 1079 ''; 1080 env = { 1081 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=7"; 1082 }; 1083 } 1084 ); 1085 1086 sfa1EnabledEnvDoesntEnableSfa3 = 1087 checkTestBin 1088 (flexArrF2ExampleWithStdEnv stdenv { 1089 hardeningDisable = [ 1090 "strictflexarrays1" 1091 "strictflexarrays3" 1092 ]; 1093 postConfigure = '' 1094 export NIX_HARDENING_ENABLE="fortify strictflexarrays1" 1095 ''; 1096 env = { 1097 TEST_EXTRA_FLAGS = "-DBUFFER_DEF_SIZE=1"; 1098 }; 1099 }) 1100 { 1101 ignoreFortify = false; 1102 expectFailure = true; 1103 }; 1104 1105 lchFastEnabledEnv = checkLibcxxHardeningWithStdEnv "_LIBCPP_HARDENING_MODE_FAST" stdenv { 1106 hardeningDisable = [ 1107 "libcxxhardeningfast" 1108 "libcxxhardeningextensive" 1109 ]; 1110 postConfigure = '' 1111 export NIX_HARDENING_ENABLE="libcxxhardeningfast" 1112 ''; 1113 }; 1114 1115 lchExtensiveEnabledEnv = checkLibcxxHardeningWithStdEnv "_LIBCPP_HARDENING_MODE_EXTENSIVE" stdenv { 1116 hardeningDisable = [ 1117 "libcxxhardeningfast" 1118 "libcxxhardeningextensive" 1119 ]; 1120 postConfigure = '' 1121 export NIX_HARDENING_ENABLE="libcxxhardeningextensive" 1122 ''; 1123 }; 1124 1125 lchFastExtensiveEnabledEnvResultsInLchExtensive = 1126 checkLibcxxHardeningWithStdEnv "_LIBCPP_HARDENING_MODE_EXTENSIVE" stdenv 1127 { 1128 hardeningDisable = [ 1129 "libcxxhardeningfast" 1130 "libcxxhardeningextensive" 1131 ]; 1132 postConfigure = '' 1133 export NIX_HARDENING_ENABLE="libcxxhardeningextensive libcxxhardeningfast" 1134 ''; 1135 }; 1136 1137 # NIX_HARDENING_ENABLE can't enable an unsupported feature 1138 stackProtectorUnsupportedEnabledEnv = 1139 checkTestBin 1140 (f2exampleWithStdEnv (stdenvUnsupport [ "stackprotector" ]) { 1141 postConfigure = '' 1142 export NIX_HARDENING_ENABLE="stackprotector" 1143 ''; 1144 }) 1145 { 1146 ignoreStackProtector = false; 1147 expectFailure = true; 1148 }; 1149 1150 # current implementation prevents the command-line from disabling 1151 # fortify if cc-wrapper is enabling it. 1152 1153 fortify1ExplicitEnabledCmdlineDisabled = 1154 checkTestBin 1155 (f1exampleWithStdEnv stdenv { 1156 hardeningEnable = [ "fortify" ]; 1157 postConfigure = '' 1158 export TEST_EXTRA_FLAGS='-D_FORTIFY_SOURCE=0' 1159 ''; 1160 }) 1161 { 1162 ignoreFortify = false; 1163 expectFailure = false; 1164 }; 1165 1166 # current implementation doesn't force-disable fortify if 1167 # command-line enables it even if we use hardeningDisable. 1168 1169 fortify1ExplicitDisabledCmdlineEnabled = 1170 checkTestBin 1171 (f1exampleWithStdEnv stdenv { 1172 hardeningDisable = [ "fortify" ]; 1173 postConfigure = '' 1174 export TEST_EXTRA_FLAGS='-D_FORTIFY_SOURCE=1' 1175 ''; 1176 }) 1177 { 1178 ignoreFortify = false; 1179 }; 1180 1181 fortify1ExplicitDisabledCmdlineEnabledExecTest = fortifyExecTest ( 1182 f1exampleWithStdEnv stdenv { 1183 hardeningDisable = [ "fortify" ]; 1184 postConfigure = '' 1185 export TEST_EXTRA_FLAGS='-D_FORTIFY_SOURCE=1' 1186 ''; 1187 } 1188 ); 1189 1190 fortify1ExplicitEnabledCmdlineDisabledNoWarn = f1exampleWithStdEnv stdenv { 1191 hardeningEnable = [ "fortify" ]; 1192 postConfigure = '' 1193 export TEST_EXTRA_FLAGS='-D_FORTIFY_SOURCE=0 -Werror' 1194 ''; 1195 }; 1196 1197 } 1198 // ( 1199 let 1200 tb = f2exampleWithStdEnv stdenv { 1201 hardeningDisable = [ "all" ]; 1202 hardeningEnable = [ 1203 "fortify" 1204 ]; 1205 }; 1206 in 1207 { 1208 1209 allExplicitDisabledBindNow = checkTestBin tb { 1210 ignoreBindNow = false; 1211 expectFailure = true; 1212 }; 1213 1214 allExplicitDisabledFortify = checkTestBin tb { 1215 ignoreFortify = false; 1216 expectFailure = true; 1217 }; 1218 1219 # can't force-disable ("partial"?) relro 1220 allExplicitDisabledRelRO = brokenIf true ( 1221 checkTestBin tb { 1222 ignoreRelRO = false; 1223 expectFailure = true; 1224 } 1225 ); 1226 1227 allExplicitDisabledStackProtector = checkTestBin tb { 1228 ignoreStackProtector = false; 1229 expectFailure = true; 1230 }; 1231 1232 allExplicitDisabledStackClashProtection = checkTestBin tb { 1233 ignoreStackClashProtection = false; 1234 expectFailure = true; 1235 }; 1236 1237 allExplicitDisabledPacRet = pacRetTest (helloWithStdEnv stdenv { 1238 hardeningDisable = [ "all" ]; 1239 }) true; 1240 1241 allExplicitDisabledShadowStack = shadowStackTest (f1exampleWithStdEnv stdenv { 1242 hardeningDisable = [ "all" ]; 1243 }) true; 1244 1245 allExplicitDisabledGlibcxxAssertions = checkGlibcxxassertionsWithStdEnv false stdenv { 1246 hardeningDisable = [ "all" ]; 1247 }; 1248 1249 allExplicitDisabledLibcxxHardening = 1250 checkLibcxxHardeningWithStdEnv "_LIBCPP_HARDENING_MODE_NONE" stdenv 1251 { 1252 hardeningDisable = [ "all" ]; 1253 }; 1254 } 1255 ) 1256)