Lines Matching refs:to

2 *determined that it'd be good to hold in Bionic's docs, too. Due to the*
3 *ever-changing nature of code, it tries to link to a stable tag of*
11 The intent of this document is to run through the minutiae of how Clang FORTIFY
15 getting up-to-speed on how things function can be quite difficult.
19 FORTIFY is a broad suite of extensions to libc aimed at catching misuses of
22 to function at all.
24 Broadly, FORTIFY implementations try to guard against many misuses of C
28 - Arguments with incorrect values passed to libc functions (e.g.,
30 - Missing arguments to functions (e.g., `open()` with `O_CREAT`, but no mode
33 FORTIFY is traditionally enabled by passing `-D_FORTIFY_SOURCE=N` to your
38 because FORTIFY has significant flexibility in what it considers to be an
41 FORTIFY implementations use a mix of compiler diagnostics and runtime checks to
48 to provide useful run-time checks. For the purpose of this document, all
55 at Clang. While GCC also provides a set of language extensions necessary to
62 requires things like macros that expand to unbalanced braces depending on your
79 * FORTIFY_WARNING_ONLY_IF_SIZE_OF_BUF_LESS_THAN is not defined, due to its
93 All talk of GCC-focused implementations and how to merge Clang and GCC
99 for many functions. This section intends to go through real-world examples of
101 work, and how the pieces fit together to provide FORTIFY-like functionality.
104 the same patterns when implementing their checks for Clang, and they try to
105 make similar promises with respect to FORTIFY compiling to be zero-overhead in
107 many stdlibs will operate _very similarly_ to Bionic in their Clang FORTIFY
111 corner cases. The individual function breakdowns below try to not offer
116 Because FORTIFY should be mostly transparent to developers, there are inherent
119 `memcpy` call with `_FORTIFY_SOURCE` enabled needs to be able to refer to the
124 - Standard library function names preceded by `__builtin_` refer to the use of
126 - Standard library function names without a prefix refer to the use of the
137 - Producing a compile-time error if the number of bytes to copy trivially
139 - If the `mempcpy` has the potential to write to more bytes than what is
140 available at the destination, a run-time check is inserted to crash the
142 - Compiling away to be zero overhead when none of the buffer sizes can be
151 is Android-specific (and orthogonal to FORTIFY anyway), so it will be ignored.
170 Expanding some of the important macros here, this function expands to roughly:
194 So let's walk through this step by step, to see how FORTIFY does what it says on
197 [^1]: "Zero overhead" in a way [similar to C++11's `std::unique_ptr`]: this will
207 First, it's critical to notice that `mempcpy` is marked `overloadable`. This
210 - `__attribute__((overloadable))` allows us to perform overloading in C.
211 - `__attribute__((overloadable))` mangles all calls to functions marked with
214 given name to not be marked with `__attribute__((overloadable))`. Calls to
225 Finally, the prior paragraph gets thrown out if one tries to take the address of
226 `mempcpy`. It is impossible to take the address of a function with one or more
229 resolution, `(&mempcpy)(x, y, z);` is functionally identical to
233 - Direct calls to `mempcpy` should call the FORTIFY-protected `mempcpy`.
234 - Indirect calls to `&mempcpy` should call `__builtin_mempcpy`.
258 Otherwise, the rest of this subsection is dedicated to preliminary discussion
264 impossible to know, so the default value is used, or the number of bytes at
266 - Declare that the expression cannot form a constant, and lower it to
270 caller, Clang should be able to trivially determine that `buf` refers to a
274 no optimizations are required to detect a broken code pattern. To be specific,
275 clang's constexpr evaluator must be able to determine the logical object that
276 any given pointer points to in order to fold `__builtin_object_size` to a
296 it introduces a tiny additional run-time cost to ensure that functions aren't
300 - `overloadable` and `pass_object_size` prompt Clang to always select this
302 - If a call to `mempcpy` was trivially broken, Clang would produce a
306 a FORTIFY'ed function's implementation for a function call, but was unable to
308 powerless to detect bugs at this point, our focus shifts to the mechanisms that
309 LLVM uses to support FORTIFY.
311 Going back to Bionic's `mempcpy` implementation, we have the following (ignoring
335 - Otherwise, if `copy_amount` can be folded to a constant, and if
350 lowers it to LLVM's `@llvm.objectsize` intrinsic. The `@llvm.objectsize`
351 invocation corresponding to `__builtin_object_size(p, 0)` is guaranteed to
352 always fold to a constant value by the time LLVM emits machine code.
354 Hence, `bos_dst` is guaranteed to be a constant; if it's -1, the above branch
355 can be eliminated entirely, since it folds to `if (false && ...)`. Further, the
359 optimizations, so no condition is ever emitted to machine code in practice.
363 `__builtin_object_size` and `__builtin_constant_p` are forced to be constants
370 Due to its implementation, it may impact the optimizations that occur on code
371 around the literal call to the FORTIFY-hardened libc function.
373 `unique_ptr` was just the first thing that came to the author's mind for "the
375 might make it only-mostly-free to use."
390 This function itself boils down to a few small branches which abort the program
391 if they fail, and a direct call to `__builtin_mempcpy`.
395 In the above breakdown, it was shown how Clang and Bionic work together to:
449 Which may be a lot to take in.
453 real way that Bionic tries to prevent calls to `open` like
454 `open("foo", 0, "how do you convert a const char[N] to mode_t?");`. The only
456 to catch sort-of-common instances of this very uncommon typo." This isn't great.
458 More directly, no effort is made below to recognize calls that, due to
459 incompatible argument types, cannot go to any `open` implementation other than
465 - Turns calls to `open` with too many arguments into a compile-time error.
466 - Diagnoses calls to `open` with missing modes at compile-time and run-time
468 - Emits warnings on calls to `open` with useless mode bits, unless the mode bits
476 This exists as a way for us to call `__builtin_open` without needing clang to
487 Which matches most calls to open that supply too many arguments, since
490 converted to `mode_t` without too much effort. Because of the `diagnose_if`
494 The following overload handles all two-argument calls to `open`.
515 to `open` is broken in a way that's visible to Clang's frontend. This
516 essentially boils down to "`open` is being called with a `flags` value that
517 requires mode bits to be set."
519 If that fails to catch a bug, we [unconditionally call `__open_2`], which
545 isn't necessary. Due to conventions in existing code, a `modes` value of `0` is
552 - It happens that `pass_object_size` -- an attribute only applicable to
553 parameters of type `T*` -- makes it impossible to take the address of a
562 builtin. `__builtin_poll` is referenced below to remain consistent with the
565 Bionic's `poll` implementation is closest to `mempcpy` above, though it has a
584 "in call to 'poll', fd_count is larger than the given buffer"))) {
598 references to `&poll` actually reference `__builtin_poll`.
599 - When `fds` is too small to hold `fd_count` `pollfd`s, Clang will emit a
602 - When `fds` is a constant according to `__builtin_constant_p`, this always
603 compiles into `__poll_chk` for always-broken calls to `poll`, or
604 `__builtin_poll` for always-safe calls to `poll`.
606 The critical bits to highlight here are on this line:
619 resolves to the function without any `pass_object_size` attributes.
629 attribute/builtin necessary to power FORTIFY was out of scope. This is... only
637 data that's currently entirely inaccessible to LLVM, and that is difficult to
641 `__builtin_object_size(p, N)` to the caller is critical, since it allows Clang
642 full visibility into the expression passed to e.g., `poll(&foo->bar, baz, qux)`.
643 It's not a perfect solution, but it allows `N == 1` to be fully accurate in at
647 Clang's implementation of `__builtin_object_size` aims to be compatible with
649 `__builtin_object_size(p, N)` is intended to evaluate at compile-time how many
658 This should hold for all values of N that are valid to pass to
667 If there are multiple possible values of `p` in a call to
684 Background section directly above. When Clang attempts to evaluate
685 `__builtin_object_size(p, 0);` and when LLVM tries to determine the result of a
686 corresponding `@llvm.objectsize` call to, they search for the storage underlying
693 Clang. According to GCC's documentation, "If the least significant bit [of
696 points to."
699 information in order to operate in many cases. Consider the following examples:
733 C++ data types, so calls to `__builtin_object_size(p, N)` that cannot be
734 resolved by clang are lowered to the equivalent of
737 Moreover, Clang's frontend is the best-equipped part of the compiler to
739 what `p` is. LLVM is the best-equipped part of the compiler to determine the
745 passes the value of that into the callee as an invisible parameter. All calls to
746 `__builtin_object_size(parameter, N)` are substituted with references to this
749 Putting this plainly, Clang's frontend struggles to evaluate the following:
757 // The frontend can't figure this interprocedural objectsize out, so it gets lowered to
763 However, with the magic of `pass_object_size`, we get one level of inlining to
772 // Due to pass_object_size, this is equivalent to:
774 // ...and `int foo(void *)` is actually equivalent to:
787 FORTIFY exists mostly for visual consistency, simplicity, and as a useful way to
798 // and is able to work with that as though the function were defined inline.
809 - `__builtin_object_size(p, N)` with `(N & 1) == 1` is not easy for Clang to
816 real world. The main thing it fails to mention is the use of [the `diagnose_as_builtin` attribute] …
820 `diagnose_as_builtin` allows us to remove the `diagnose_if`s from some of the
825 since Clang can format its diagnostics to include e.g., information about the
826 sizes of buffers in a suspect call to a function. `diagnose_if` can only have
836 [similar to C++11's `std::unique_ptr`]: https://stackoverflow.com/questions/58339165/why-can-a-t-be…