Page MenuHomeFreeBSD

libc: tests: add testing infrastructure for _FORTIFY_SOURCE
ClosedPublic

Authored by kevans on Jun 21 2024, 4:59 PM.
Tags
None
Referenced Files
Unknown Object (File)
Tue, Dec 24, 5:06 PM
Unknown Object (File)
Tue, Dec 24, 12:24 PM
Unknown Object (File)
Mon, Dec 23, 11:13 AM
Unknown Object (File)
Tue, Dec 10, 9:21 PM
Unknown Object (File)
Nov 29 2024, 4:28 AM
Unknown Object (File)
Nov 25 2024, 9:24 PM
Unknown Object (File)
Nov 25 2024, 12:35 PM
Unknown Object (File)
Nov 24 2024, 8:25 PM
Subscribers

Details

Summary

The _FORTIFY_SOURCE tests will be generated by a lua script to avoid a
lot of redundancy in writing these tests. For each function that we're
fortifying, the plan is to test at least the following three scenarios:

  • Writing up to one byte before the end of the buffer,
  • Writing up to the end of the buffer,
  • Writing one byte past the end of the buffer

The buffer is shoved into a struct on the stack to guarantee a stack
layout in which we have a valid byte after the buffer so that level 2
fortification will trip and we can have confidence that it wasn't some
other stack/memory protection instead.

The generated tests are divided roughly into which header we're
attributing them to so that we can parallelize the build -- the full set
is a bit over 9000 lines of C and takes 11s to build on the hardware
that I'm testing on if it's a single monolothic file.

Sponsored by: Stormshield
Sponsored by: Klara, Inc.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

lib/libc/tests/secure/Makefile
2

Extra newline.

lib/libc/tests/secure/generate-fortify-tests.lua
616

I'd find a bit more explanation useful here:

  • Which functions are we testing?
  • What exactly are we testing for?
  • How do we actually test for it?

I can mostly figure this out by reading the code, but seeing as it's code that generates code, it's not too easy to read, so a bit more elaboration is worthwhile I think. I'd also maybe put this at the top of the file, as a "theory of operation" block comment.

kevans marked 2 inline comments as done.

Address review commentary

lib/libc/tests/secure/generate-fortify-tests.lua
38

Is it meaningful/useful to test the case where we pass some offset into the buffer? e.g., we have a stack buffer buf and pass buf + 1 to the function, just to ensure that __builtin_object_size() works properly in that case.

84
246

No checks for strlcpy()?

262

Is _FORTIFY_SOURCE supposed to be able to catch out-of-bounds reads of the source buffer?

598

Why the extra ..s?

615

new_symlink() might be a better name.

656

Check for errors from lseek()?

665

Check for errors from setrlimit()? Hmm, but this code might execute in the child, where you can't use ATF macros.

lib/libc/tests/secure/generate-fortify-tests.lua
598

To avoid @generated appearing in this file and triggering a false positive in, e.g., phab that hides @generated content by default

kevans marked 7 inline comments as done.

Address review feedback:

  • Error check lseek(2)
  • Error check setrlimit(2), handle child errors a little more usefully
  • Pick a better name for new_link
lib/libc/tests/secure/generate-fortify-tests.lua
38

I'm still thinking on this one... I'm torn because I think that specific bug is perhaps unlikely to exist per-function and might be better in a separate set of tests for __builtin_object_size correctness, but I can also see a good argument that it wouldn't exactly be complicated to test per-function since we're generating all of the other tests anyways.

246

strlcpy isn't fortified until later in D45679

262

Typically no, it was only meant to target out-of-bounds writes

665

No, but at the very least we can hack off some designated error codes and try to provide some diagnostics in the monitor

Seems ok to me, just had one inline question.

lib/libc/tests/secure/generate-fortify-tests.lua
89

Rather than excluding them at test generation time, can we simply skip the tests if they were compiled with clang? i.e., something like

#ifdef __clang__
atf_tc_skip(...);
#else
<test case>
#endif
This revision is now accepted and ready to land.Jul 2 2024, 2:01 PM
lib/libc/tests/secure/generate-fortify-tests.lua
89

We could, but right now none of this builds with the lang/gcc ports so I hadn't gone back to address it.

I think fixing the ports is as easy as removing ssp headers from each of them, I'll look into that and work this feedback into a follow-up change addressing any other GCC issues I might find.