xref: /aosp_15_r20/bionic/docs/clang_fortify_anatomy.md (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker*This document was originally written for a broad audience, and it was*
2*8d67ca89SAndroid Build Coastguard Worker*determined that it'd be good to hold in Bionic's docs, too. Due to the*
3*8d67ca89SAndroid Build Coastguard Worker*ever-changing nature of code, it tries to link to a stable tag of*
4*8d67ca89SAndroid Build Coastguard Worker*Bionic's libc, rather than the live code in Bionic. Same for Clang.*
5*8d67ca89SAndroid Build Coastguard Worker*Reader beware. :)*
6*8d67ca89SAndroid Build Coastguard Worker
7*8d67ca89SAndroid Build Coastguard Worker# The Anatomy of Clang FORTIFY
8*8d67ca89SAndroid Build Coastguard Worker
9*8d67ca89SAndroid Build Coastguard Worker## Objective
10*8d67ca89SAndroid Build Coastguard Worker
11*8d67ca89SAndroid Build Coastguard WorkerThe intent of this document is to run through the minutiae of how Clang FORTIFY
12*8d67ca89SAndroid Build Coastguard Workeractually works in Bionic at the time of writing. Other FORTIFY implementations
13*8d67ca89SAndroid Build Coastguard Workerthat target Clang should use very similar mechanics. This document exists in part
14*8d67ca89SAndroid Build Coastguard Workerbecause many Clang-specific features serve multiple purposes simultaneously, so
15*8d67ca89SAndroid Build Coastguard Workergetting up-to-speed on how things function can be quite difficult.
16*8d67ca89SAndroid Build Coastguard Worker
17*8d67ca89SAndroid Build Coastguard Worker## Background
18*8d67ca89SAndroid Build Coastguard Worker
19*8d67ca89SAndroid Build Coastguard WorkerFORTIFY is a broad suite of extensions to libc aimed at catching misuses of
20*8d67ca89SAndroid Build Coastguard Workercommon library functions. Textually, these extensions exist purely in libc, but
21*8d67ca89SAndroid Build Coastguard Workerall implementations of FORTIFY rely heavily on C language extensions in order
22*8d67ca89SAndroid Build Coastguard Workerto function at all.
23*8d67ca89SAndroid Build Coastguard Worker
24*8d67ca89SAndroid Build Coastguard WorkerBroadly, FORTIFY implementations try to guard against many misuses of C
25*8d67ca89SAndroid Build Coastguard Workerstandard(-ish) libraries:
26*8d67ca89SAndroid Build Coastguard Worker- Buffer overruns in functions where pointers+sizes are passed (e.g., `memcpy`,
27*8d67ca89SAndroid Build Coastguard Worker  `poll`), or where sizes exist implicitly (e.g., `strcpy`).
28*8d67ca89SAndroid Build Coastguard Worker- Arguments with incorrect values passed to libc functions (e.g.,
29*8d67ca89SAndroid Build Coastguard Worker  out-of-bounds bits in `umask`).
30*8d67ca89SAndroid Build Coastguard Worker- Missing arguments to functions (e.g., `open()` with `O_CREAT`, but no mode
31*8d67ca89SAndroid Build Coastguard Worker  bits).
32*8d67ca89SAndroid Build Coastguard Worker
33*8d67ca89SAndroid Build Coastguard WorkerFORTIFY is traditionally enabled by passing `-D_FORTIFY_SOURCE=N` to your
34*8d67ca89SAndroid Build Coastguard Workercompiler. `N==0` disables FORTIFY, whereas `N==1`, `N==2`, and `N==3` enable
35*8d67ca89SAndroid Build Coastguard Workerincreasingly strict versions of it. In general, FORTIFY doesn't require user
36*8d67ca89SAndroid Build Coastguard Workercode changes; that said, some code patterns
37*8d67ca89SAndroid Build Coastguard Workerare [incompatible with stricter versions of FORTIFY checking]. This is largely
38*8d67ca89SAndroid Build Coastguard Workerbecause FORTIFY has significant flexibility in what it considers to be an
39*8d67ca89SAndroid Build Coastguard Worker"out-of-bounds" access.
40*8d67ca89SAndroid Build Coastguard Worker
41*8d67ca89SAndroid Build Coastguard WorkerFORTIFY implementations use a mix of compiler diagnostics and runtime checks to
42*8d67ca89SAndroid Build Coastguard Workerflag and/or mitigate the impacts of the misuses mentioned above.
43*8d67ca89SAndroid Build Coastguard Worker
44*8d67ca89SAndroid Build Coastguard WorkerFurther, given FORTIFY's design, the effectiveness of FORTIFY is a function of
45*8d67ca89SAndroid Build Coastguard Worker-- among other things -- the optimization level you're compiling your code at.
46*8d67ca89SAndroid Build Coastguard WorkerMany FORTIFY implementations are implicitly disabled when building with `-O0`,
47*8d67ca89SAndroid Build Coastguard Workersince FORTIFY's design for both Clang and GCC relies on optimizations in order
48*8d67ca89SAndroid Build Coastguard Workerto provide useful run-time checks. For the purpose of this document, all
49*8d67ca89SAndroid Build Coastguard Workeranalysis of FORTIFY functions and commentary on builtins assume that code is
50*8d67ca89SAndroid Build Coastguard Workerbeing built with some optimization level > `-O0`.
51*8d67ca89SAndroid Build Coastguard Worker
52*8d67ca89SAndroid Build Coastguard Worker### A note on GCC
53*8d67ca89SAndroid Build Coastguard Worker
54*8d67ca89SAndroid Build Coastguard WorkerThis document talks specifically about Bionic's FORTIFY implementation targeted
55*8d67ca89SAndroid Build Coastguard Workerat Clang. While GCC also provides a set of language extensions necessary to
56*8d67ca89SAndroid Build Coastguard Workerimplement FORTIFY, these tools are different from what Clang offers. This
57*8d67ca89SAndroid Build Coastguard Workerdivergence is an artifact of Clang and GCC's differing architecture as
58*8d67ca89SAndroid Build Coastguard Workercompilers.
59*8d67ca89SAndroid Build Coastguard Worker
60*8d67ca89SAndroid Build Coastguard WorkerTextually, quite a bit can be shared between a FORTIFY implementation for GCC
61*8d67ca89SAndroid Build Coastguard Workerand one for Clang (e.g., see [ChromeOS' Glibc patch]), but this kind of sharing
62*8d67ca89SAndroid Build Coastguard Workerrequires things like macros that expand to unbalanced braces depending on your
63*8d67ca89SAndroid Build Coastguard Workercompiler:
64*8d67ca89SAndroid Build Coastguard Worker
65*8d67ca89SAndroid Build Coastguard Worker```c
66*8d67ca89SAndroid Build Coastguard Worker/*
67*8d67ca89SAndroid Build Coastguard Worker * Highly simplified; if you're interested in FORTIFY's actual implementation,
68*8d67ca89SAndroid Build Coastguard Worker * please see the patch linked above.
69*8d67ca89SAndroid Build Coastguard Worker */
70*8d67ca89SAndroid Build Coastguard Worker#ifdef __clang__
71*8d67ca89SAndroid Build Coastguard Worker# define FORTIFY_PRECONDITIONS
72*8d67ca89SAndroid Build Coastguard Worker# define FORTIFY_FUNCTION_END
73*8d67ca89SAndroid Build Coastguard Worker#else
74*8d67ca89SAndroid Build Coastguard Worker# define FORTIFY_PRECONDITIONS {
75*8d67ca89SAndroid Build Coastguard Worker# define FORTIFY_FUNCTION_END }
76*8d67ca89SAndroid Build Coastguard Worker#endif
77*8d67ca89SAndroid Build Coastguard Worker
78*8d67ca89SAndroid Build Coastguard Worker/*
79*8d67ca89SAndroid Build Coastguard Worker * FORTIFY_WARNING_ONLY_IF_SIZE_OF_BUF_LESS_THAN is not defined, due to its
80*8d67ca89SAndroid Build Coastguard Worker * complexity and irrelevance. It turns into a compile-time warning if the
81*8d67ca89SAndroid Build Coastguard Worker * compiler can determine `*buf` has fewer than `size` bytes available.
82*8d67ca89SAndroid Build Coastguard Worker */
83*8d67ca89SAndroid Build Coastguard Worker
84*8d67ca89SAndroid Build Coastguard Workerchar *getcwd(char *buf, size_t size)
85*8d67ca89SAndroid Build Coastguard WorkerFORTIFY_PRECONDITIONS
86*8d67ca89SAndroid Build Coastguard Worker  FORTIFY_WARNING_ONLY_IF_SIZE_OF_BUF_LESS_THAN(buf, size, "`buf` is too smol.")
87*8d67ca89SAndroid Build Coastguard Worker{
88*8d67ca89SAndroid Build Coastguard Worker  // Actual shared function implementation goes here.
89*8d67ca89SAndroid Build Coastguard Worker}
90*8d67ca89SAndroid Build Coastguard WorkerFORTIFY_FUNCTION_END
91*8d67ca89SAndroid Build Coastguard Worker```
92*8d67ca89SAndroid Build Coastguard Worker
93*8d67ca89SAndroid Build Coastguard WorkerAll talk of GCC-focused implementations and how to merge Clang and GCC
94*8d67ca89SAndroid Build Coastguard Workerimplementations is out-of-scope for this doc, however.
95*8d67ca89SAndroid Build Coastguard Worker
96*8d67ca89SAndroid Build Coastguard Worker## The Life of a Clang FORTIFY Function
97*8d67ca89SAndroid Build Coastguard Worker
98*8d67ca89SAndroid Build Coastguard WorkerAs referenced in the Background section, FORTIFY performs many different checks
99*8d67ca89SAndroid Build Coastguard Workerfor many functions. This section intends to go through real-world examples of
100*8d67ca89SAndroid Build Coastguard WorkerFORTIFY functions in Bionic, breaking down how each part of these functions
101*8d67ca89SAndroid Build Coastguard Workerwork, and how the pieces fit together to provide FORTIFY-like functionality.
102*8d67ca89SAndroid Build Coastguard Worker
103*8d67ca89SAndroid Build Coastguard WorkerWhile FORTIFY implementations may differ between stdlibs, they broadly follow
104*8d67ca89SAndroid Build Coastguard Workerthe same patterns when implementing their checks for Clang, and they try to
105*8d67ca89SAndroid Build Coastguard Workermake similar promises with respect to FORTIFY compiling to be zero-overhead in
106*8d67ca89SAndroid Build Coastguard Workersome cases, etc. Moreover, while this document specifically examines Bionic,
107*8d67ca89SAndroid Build Coastguard Workermany stdlibs will operate _very similarly_ to Bionic in their Clang FORTIFY
108*8d67ca89SAndroid Build Coastguard Workerimplementations.
109*8d67ca89SAndroid Build Coastguard Worker
110*8d67ca89SAndroid Build Coastguard Worker**In general, when reading the below, be prepared for exceptions, subtlety, and
111*8d67ca89SAndroid Build Coastguard Workercorner cases. The individual function breakdowns below try to not offer
112*8d67ca89SAndroid Build Coastguard Workerredundant information. Each one focuses on different aspects of FORTIFY.**
113*8d67ca89SAndroid Build Coastguard Worker
114*8d67ca89SAndroid Build Coastguard Worker### Terminology
115*8d67ca89SAndroid Build Coastguard Worker
116*8d67ca89SAndroid Build Coastguard WorkerBecause FORTIFY should be mostly transparent to developers, there are inherent
117*8d67ca89SAndroid Build Coastguard Workernaming collisions here: `memcpy(x, y, z)` turns into fundamentally different
118*8d67ca89SAndroid Build Coastguard Workergenerated code depending on the value of `_FORTIFY_SOURCE`. Further, said
119*8d67ca89SAndroid Build Coastguard Worker`memcpy` call with `_FORTIFY_SOURCE` enabled needs to be able to refer to the
120*8d67ca89SAndroid Build Coastguard Worker`memcpy` that would have been called, had `_FORTIFY_SOURCE` been disabled.
121*8d67ca89SAndroid Build Coastguard WorkerHence, the following convention is followed in the subsections below for all
122*8d67ca89SAndroid Build Coastguard Workerprose (namely, multiline code blocks are exempted from this):
123*8d67ca89SAndroid Build Coastguard Worker
124*8d67ca89SAndroid Build Coastguard Worker- Standard library function names preceded by `__builtin_` refer to the use of
125*8d67ca89SAndroid Build Coastguard Worker  the function with `_FORTIFY_SOURCE` disabled.
126*8d67ca89SAndroid Build Coastguard Worker- Standard library function names without a prefix refer to the use of the
127*8d67ca89SAndroid Build Coastguard Worker  function with `_FORTIFY_SOURCE` enabled.
128*8d67ca89SAndroid Build Coastguard Worker
129*8d67ca89SAndroid Build Coastguard WorkerThis convention also applies in `clang`. `__builtin_memcpy` will always call
130*8d67ca89SAndroid Build Coastguard Worker`memcpy` as though `_FORTIFY_SOURCE` were disabled.
131*8d67ca89SAndroid Build Coastguard Worker
132*8d67ca89SAndroid Build Coastguard Worker## Breakdown of `mempcpy`
133*8d67ca89SAndroid Build Coastguard Worker
134*8d67ca89SAndroid Build Coastguard WorkerThe [FORTIFY'ed version of `mempcpy`] is a full, featureful example of a
135*8d67ca89SAndroid Build Coastguard WorkerFORTIFY'ed function from Bionic. From the user's perspective, it supports a few
136*8d67ca89SAndroid Build Coastguard Workerthings:
137*8d67ca89SAndroid Build Coastguard Worker- Producing a compile-time error if the number of bytes to copy trivially
138*8d67ca89SAndroid Build Coastguard Worker  exceeds the number of bytes available at the destination pointer.
139*8d67ca89SAndroid Build Coastguard Worker- If the `mempcpy` has the potential to write to more bytes than what is
140*8d67ca89SAndroid Build Coastguard Worker  available at the destination, a run-time check is inserted to crash the
141*8d67ca89SAndroid Build Coastguard Worker  program if more bytes are written than what is allowed.
142*8d67ca89SAndroid Build Coastguard Worker- Compiling away to be zero overhead when none of the buffer sizes can be
143*8d67ca89SAndroid Build Coastguard Worker  determined at compile-time[^1].
144*8d67ca89SAndroid Build Coastguard Worker
145*8d67ca89SAndroid Build Coastguard WorkerThe declaration in Bionic's headers for `__builtin_mempcpy` is:
146*8d67ca89SAndroid Build Coastguard Worker```c
147*8d67ca89SAndroid Build Coastguard Workervoid* mempcpy(void* __dst, const void* __src, size_t __n) __INTRODUCED_IN(23);
148*8d67ca89SAndroid Build Coastguard Worker```
149*8d67ca89SAndroid Build Coastguard Worker
150*8d67ca89SAndroid Build Coastguard WorkerWhich is annotated with nothing special, so it will be ignored.
151*8d67ca89SAndroid Build Coastguard Worker
152*8d67ca89SAndroid Build Coastguard WorkerThe [source for `mempcpy`] in Bionic's headers for is:
153*8d67ca89SAndroid Build Coastguard Worker```c
154*8d67ca89SAndroid Build Coastguard Worker__BIONIC_FORTIFY_INLINE
155*8d67ca89SAndroid Build Coastguard Workervoid* mempcpy(void* const dst __pass_object_size0, const void* src, size_t copy_amount)
156*8d67ca89SAndroid Build Coastguard Worker        __overloadable
157*8d67ca89SAndroid Build Coastguard Worker        __clang_error_if(__bos_unevaluated_lt(__bos0(dst), copy_amount),
158*8d67ca89SAndroid Build Coastguard Worker                         "'mempcpy' called with size bigger than buffer") {
159*8d67ca89SAndroid Build Coastguard Worker#if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
160*8d67ca89SAndroid Build Coastguard Worker    size_t bos_dst = __bos0(dst);
161*8d67ca89SAndroid Build Coastguard Worker    if (!__bos_trivially_ge(bos_dst, copy_amount)) {
162*8d67ca89SAndroid Build Coastguard Worker        return __builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);
163*8d67ca89SAndroid Build Coastguard Worker    }
164*8d67ca89SAndroid Build Coastguard Worker#endif
165*8d67ca89SAndroid Build Coastguard Worker    return __builtin_mempcpy(dst, src, copy_amount);
166*8d67ca89SAndroid Build Coastguard Worker}
167*8d67ca89SAndroid Build Coastguard Worker```
168*8d67ca89SAndroid Build Coastguard Worker
169*8d67ca89SAndroid Build Coastguard WorkerExpanding some of the important macros here, this function expands to roughly:
170*8d67ca89SAndroid Build Coastguard Worker```c
171*8d67ca89SAndroid Build Coastguard Workerstatic
172*8d67ca89SAndroid Build Coastguard Worker__inline__
173*8d67ca89SAndroid Build Coastguard Worker__attribute__((no_stack_protector))
174*8d67ca89SAndroid Build Coastguard Worker__attribute__((always_inline))
175*8d67ca89SAndroid Build Coastguard Workervoid* mempcpy(
176*8d67ca89SAndroid Build Coastguard Worker        void* const dst __attribute__((pass_object_size(0))),
177*8d67ca89SAndroid Build Coastguard Worker        const void* src,
178*8d67ca89SAndroid Build Coastguard Worker        size_t copy_amount)
179*8d67ca89SAndroid Build Coastguard Worker        __attribute__((overloadable))
180*8d67ca89SAndroid Build Coastguard Worker        __attribute__((diagnose_if(
181*8d67ca89SAndroid Build Coastguard Worker            __builtin_object_size(dst, 0) != -1 && __builtin_object_size(dst, 0) <= copy_amount),
182*8d67ca89SAndroid Build Coastguard Worker            "'mempcpy' called with size bigger than buffer"))) {
183*8d67ca89SAndroid Build Coastguard Worker#if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
184*8d67ca89SAndroid Build Coastguard Worker    size_t bos_dst = __builtin_object_size(dst, 0);
185*8d67ca89SAndroid Build Coastguard Worker    if (!(__bos_trivially_ge(bos_dst, copy_amount))) {
186*8d67ca89SAndroid Build Coastguard Worker        return __builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);
187*8d67ca89SAndroid Build Coastguard Worker    }
188*8d67ca89SAndroid Build Coastguard Worker#endif
189*8d67ca89SAndroid Build Coastguard Worker    return __builtin_mempcpy(dst, src, copy_amount);
190*8d67ca89SAndroid Build Coastguard Worker}
191*8d67ca89SAndroid Build Coastguard Worker```
192*8d67ca89SAndroid Build Coastguard Worker
193*8d67ca89SAndroid Build Coastguard WorkerSo let's walk through this step by step, to see how FORTIFY does what it says on
194*8d67ca89SAndroid Build Coastguard Workerthe tin here.
195*8d67ca89SAndroid Build Coastguard Worker
196*8d67ca89SAndroid Build Coastguard Worker[^1]: "Zero overhead" in a way [similar to C++11's `std::unique_ptr`]: this will
197*8d67ca89SAndroid Build Coastguard Workerturn into a direct call `__builtin_mempcpy` (or an optimized form thereof) with
198*8d67ca89SAndroid Build Coastguard Workerno other surrounding checks at runtime. However, the additional complexity may
199*8d67ca89SAndroid Build Coastguard Workerhinder optimizations that are performed before the optimizer can prove that the
200*8d67ca89SAndroid Build Coastguard Worker`if (...) { ... }` can be optimized out. Depending on how late this happens,
201*8d67ca89SAndroid Build Coastguard Workerthe additional complexity may skew inlining costs, hide opportunities for e.g.,
202*8d67ca89SAndroid Build Coastguard Worker`memcpy` coalescing, etc etc.
203*8d67ca89SAndroid Build Coastguard Worker
204*8d67ca89SAndroid Build Coastguard Worker### How does Clang select `mempcpy`?
205*8d67ca89SAndroid Build Coastguard Worker
206*8d67ca89SAndroid Build Coastguard WorkerFirst, it's critical to notice that `mempcpy` is marked `overloadable`. This
207*8d67ca89SAndroid Build Coastguard Workerfunction is a `static inline __attribute__((always_inline))` overload of
208*8d67ca89SAndroid Build Coastguard Worker`__builtin_mempcpy`:
209*8d67ca89SAndroid Build Coastguard Worker- `__attribute__((overloadable))` allows us to perform overloading in C.
210*8d67ca89SAndroid Build Coastguard Worker- `__attribute__((overloadable))` mangles all calls to functions marked with
211*8d67ca89SAndroid Build Coastguard Worker  `__attribute__((overloadable))`.
212*8d67ca89SAndroid Build Coastguard Worker- `__attribute__((overloadable))` allows exactly one function signature with a
213*8d67ca89SAndroid Build Coastguard Worker  given name to not be marked with `__attribute__((overloadable))`. Calls to
214*8d67ca89SAndroid Build Coastguard Worker  this overload will not be mangled.
215*8d67ca89SAndroid Build Coastguard Worker
216*8d67ca89SAndroid Build Coastguard WorkerSecond, one might note that this `mempcpy` implementation has the same C-level
217*8d67ca89SAndroid Build Coastguard Workersignature as `__builtin_mempcpy`. `pass_object_size` is a Clang attribute that
218*8d67ca89SAndroid Build Coastguard Workeris generally needed by FORTIFY, but it carries the side-effect that functions
219*8d67ca89SAndroid Build Coastguard Workermay be overloaded simply on the presence (or lack of presence) of
220*8d67ca89SAndroid Build Coastguard Worker`pass_object_size` attributes. Given two overloads of a function that only
221*8d67ca89SAndroid Build Coastguard Workerdiffer on the presence of `pass_object_size` attributes, the candidate with
222*8d67ca89SAndroid Build Coastguard Worker`pass_object_size` attributes is preferred.
223*8d67ca89SAndroid Build Coastguard Worker
224*8d67ca89SAndroid Build Coastguard WorkerFinally, the prior paragraph gets thrown out if one tries to take the address of
225*8d67ca89SAndroid Build Coastguard Worker`mempcpy`. It is impossible to take the address of a function with one or more
226*8d67ca89SAndroid Build Coastguard Workerparameters that are annotated with `pass_object_size`. Hence,
227*8d67ca89SAndroid Build Coastguard Worker`&__builtin_mempcpy == &mempcpy`. Further, because this is an issue of overload
228*8d67ca89SAndroid Build Coastguard Workerresolution, `(&mempcpy)(x, y, z);` is functionally identical to
229*8d67ca89SAndroid Build Coastguard Worker`__builtin_mempcpy(x, y, z);`.
230*8d67ca89SAndroid Build Coastguard Worker
231*8d67ca89SAndroid Build Coastguard WorkerAll of this accomplishes the following:
232*8d67ca89SAndroid Build Coastguard Worker- Direct calls to `mempcpy` should call the FORTIFY-protected `mempcpy`.
233*8d67ca89SAndroid Build Coastguard Worker- Indirect calls to `&mempcpy` should call `__builtin_mempcpy`.
234*8d67ca89SAndroid Build Coastguard Worker
235*8d67ca89SAndroid Build Coastguard Worker### How does Clang offer compile-time diagnostics?
236*8d67ca89SAndroid Build Coastguard Worker
237*8d67ca89SAndroid Build Coastguard WorkerOnce one is convinced that the FORTIFY-enabled overload of `mempcpy` will be
238*8d67ca89SAndroid Build Coastguard Workerselected for direct calls, Clang's `diagnose_if` and `__builtin_object_size` do
239*8d67ca89SAndroid Build Coastguard Workerall of the work from there.
240*8d67ca89SAndroid Build Coastguard Worker
241*8d67ca89SAndroid Build Coastguard WorkerSubtleties here primarily fall out of the discussion in the above section about
242*8d67ca89SAndroid Build Coastguard Worker`&__builtin_mempcpy == &mempcpy`:
243*8d67ca89SAndroid Build Coastguard Worker```c
244*8d67ca89SAndroid Build Coastguard Worker#define _FORTIFY_SOURCE 2
245*8d67ca89SAndroid Build Coastguard Worker#include <string.h>
246*8d67ca89SAndroid Build Coastguard Workervoid example_code() {
247*8d67ca89SAndroid Build Coastguard Worker  char buf[4]; // ...Assume sizeof(char) == 1.
248*8d67ca89SAndroid Build Coastguard Worker  const char input_buf[] = "Hello, World";
249*8d67ca89SAndroid Build Coastguard Worker  mempcpy(buf, input_buf, 4); // Valid, no diagnostic issued.
250*8d67ca89SAndroid Build Coastguard Worker
251*8d67ca89SAndroid Build Coastguard Worker  mempcpy(buf, input_buf, 5); // Emits a compile-time error since sizeof(buf) < 5.
252*8d67ca89SAndroid Build Coastguard Worker  __builtin_mempcpy(buf, input_buf, 5); // No compile-time error.
253*8d67ca89SAndroid Build Coastguard Worker  (&mempcpy)(buf, input_buf, 5); // No compile-time error, since __builtin_mempcpy is selected.
254*8d67ca89SAndroid Build Coastguard Worker}
255*8d67ca89SAndroid Build Coastguard Worker```
256*8d67ca89SAndroid Build Coastguard Worker
257*8d67ca89SAndroid Build Coastguard WorkerOtherwise, the rest of this subsection is dedicated to preliminary discussion
258*8d67ca89SAndroid Build Coastguard Workerabout `__builtin_object_size`.
259*8d67ca89SAndroid Build Coastguard Worker
260*8d67ca89SAndroid Build Coastguard WorkerClang's frontend can do one of two things with `__builtin_object_size(p, n)`:
261*8d67ca89SAndroid Build Coastguard Worker- Evaluate it as a constant.
262*8d67ca89SAndroid Build Coastguard Worker  - This can either mean declaring that the number of bytes at `p` is definitely
263*8d67ca89SAndroid Build Coastguard Worker    impossible to know, so the default value is used, or the number of bytes at
264*8d67ca89SAndroid Build Coastguard Worker    `p` can be known without optimizations.
265*8d67ca89SAndroid Build Coastguard Worker- Declare that the expression cannot form a constant, and lower it to
266*8d67ca89SAndroid Build Coastguard Worker  `@llvm.objectsize`, which is discussed in depth later.
267*8d67ca89SAndroid Build Coastguard Worker
268*8d67ca89SAndroid Build Coastguard WorkerIn the examples above, since `diagnose_if` is evaluated with context from the
269*8d67ca89SAndroid Build Coastguard Workercaller, Clang should be able to trivially determine that `buf` refers to a
270*8d67ca89SAndroid Build Coastguard Worker`char` array with 4 elements.
271*8d67ca89SAndroid Build Coastguard Worker
272*8d67ca89SAndroid Build Coastguard WorkerThe primary consequence of the above is that diagnostics can only be emitted if
273*8d67ca89SAndroid Build Coastguard Workerno optimizations are required to detect a broken code pattern. To be specific,
274*8d67ca89SAndroid Build Coastguard Workerclang's constexpr evaluator must be able to determine the logical object that
275*8d67ca89SAndroid Build Coastguard Workerany given pointer points to in order to fold `__builtin_object_size` to a
276*8d67ca89SAndroid Build Coastguard Workerconstant, non-default answer:
277*8d67ca89SAndroid Build Coastguard Worker
278*8d67ca89SAndroid Build Coastguard Worker```c
279*8d67ca89SAndroid Build Coastguard Worker#define _FORTIFY_SOURCE 2
280*8d67ca89SAndroid Build Coastguard Worker#include <string.h>
281*8d67ca89SAndroid Build Coastguard Workervoid example_code() {
282*8d67ca89SAndroid Build Coastguard Worker  char buf[4]; // ...Assume sizeof(char) == 1.
283*8d67ca89SAndroid Build Coastguard Worker  const char input_buf[] = "Hello, World";
284*8d67ca89SAndroid Build Coastguard Worker  mempcpy(buf, input_buf, 4); // Valid, no diagnostic issued.
285*8d67ca89SAndroid Build Coastguard Worker  mempcpy(buf, input_buf, 5); // Emits a compile-time error since sizeof(buf) < 5.
286*8d67ca89SAndroid Build Coastguard Worker  char *buf_ptr = buf;
287*8d67ca89SAndroid Build Coastguard Worker  mempcpy(buf_ptr, input_buf, 5); // No compile-time error; `buf_ptr`'s target can't be determined.
288*8d67ca89SAndroid Build Coastguard Worker}
289*8d67ca89SAndroid Build Coastguard Worker```
290*8d67ca89SAndroid Build Coastguard Worker
291*8d67ca89SAndroid Build Coastguard Worker### How does Clang insert run-time checks?
292*8d67ca89SAndroid Build Coastguard Worker
293*8d67ca89SAndroid Build Coastguard WorkerThis section expands on the following statement: FORTIFY has zero runtime cost
294*8d67ca89SAndroid Build Coastguard Workerin instances where there is no chance of catching a bug at run-time. Otherwise,
295*8d67ca89SAndroid Build Coastguard Workerit introduces a tiny additional run-time cost to ensure that functions aren't
296*8d67ca89SAndroid Build Coastguard Workermisused.
297*8d67ca89SAndroid Build Coastguard Worker
298*8d67ca89SAndroid Build Coastguard WorkerIn prior sections, the following was established:
299*8d67ca89SAndroid Build Coastguard Worker- `overloadable` and `pass_object_size` prompt Clang to always select this
300*8d67ca89SAndroid Build Coastguard Worker  overload of `mempcpy` over `__builtin_mempcpy` for direct calls.
301*8d67ca89SAndroid Build Coastguard Worker- If a call to `mempcpy` was trivially broken, Clang would produce a
302*8d67ca89SAndroid Build Coastguard Worker  compile-time error, rather than producing a binary.
303*8d67ca89SAndroid Build Coastguard Worker
304*8d67ca89SAndroid Build Coastguard WorkerHence, the case we're interested in here is one where Clang's frontend selected
305*8d67ca89SAndroid Build Coastguard Workera FORTIFY'ed function's implementation for a function call, but was unable to
306*8d67ca89SAndroid Build Coastguard Workerfind anything seriously wrong with said function call. Since the frontend is
307*8d67ca89SAndroid Build Coastguard Workerpowerless to detect bugs at this point, our focus shifts to the mechanisms that
308*8d67ca89SAndroid Build Coastguard WorkerLLVM uses to support FORTIFY.
309*8d67ca89SAndroid Build Coastguard Worker
310*8d67ca89SAndroid Build Coastguard WorkerGoing back to Bionic's `mempcpy` implementation, we have the following (ignoring
311*8d67ca89SAndroid Build Coastguard Workerdiagnose_if and assuming run-time checks are enabled):
312*8d67ca89SAndroid Build Coastguard Worker```c
313*8d67ca89SAndroid Build Coastguard Workerstatic
314*8d67ca89SAndroid Build Coastguard Worker__inline__
315*8d67ca89SAndroid Build Coastguard Worker__attribute__((no_stack_protector))
316*8d67ca89SAndroid Build Coastguard Worker__attribute__((always_inline))
317*8d67ca89SAndroid Build Coastguard Workervoid* mempcpy(
318*8d67ca89SAndroid Build Coastguard Worker        void* const dst __attribute__((pass_object_size(0))),
319*8d67ca89SAndroid Build Coastguard Worker        const void* src,
320*8d67ca89SAndroid Build Coastguard Worker        size_t copy_amount)
321*8d67ca89SAndroid Build Coastguard Worker        __attribute__((overloadable)) {
322*8d67ca89SAndroid Build Coastguard Worker    size_t bos_dst = __builtin_object_size(dst, 0);
323*8d67ca89SAndroid Build Coastguard Worker    if (bos_dst != -1 &&
324*8d67ca89SAndroid Build Coastguard Worker        !(__builtin_constant_p(copy_amount) && bos_dst >= copy_amount)) {
325*8d67ca89SAndroid Build Coastguard Worker        return __builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);
326*8d67ca89SAndroid Build Coastguard Worker    }
327*8d67ca89SAndroid Build Coastguard Worker    return __builtin_mempcpy(dst, src, copy_amount);
328*8d67ca89SAndroid Build Coastguard Worker}
329*8d67ca89SAndroid Build Coastguard Worker```
330*8d67ca89SAndroid Build Coastguard Worker
331*8d67ca89SAndroid Build Coastguard WorkerIn other words, we have a `static`, `always_inline` function which:
332*8d67ca89SAndroid Build Coastguard Worker- If `__builtin_object_size(dst, 0)` cannot be determined (in which case, it
333*8d67ca89SAndroid Build Coastguard Worker  returns -1), calls `__builtin_mempcpy`.
334*8d67ca89SAndroid Build Coastguard Worker- Otherwise, if `copy_amount` can be folded to a constant, and if
335*8d67ca89SAndroid Build Coastguard Worker  `__builtin_object_size(dst, 0) >= copy_amount`, calls `__builtin_mempcpy`.
336*8d67ca89SAndroid Build Coastguard Worker- Otherwise, calls `__builtin___mempcpy_chk`.
337*8d67ca89SAndroid Build Coastguard Worker
338*8d67ca89SAndroid Build Coastguard Worker
339*8d67ca89SAndroid Build Coastguard WorkerHow can this be "zero overhead"? Let's focus on the following part of the
340*8d67ca89SAndroid Build Coastguard Workerfunction:
341*8d67ca89SAndroid Build Coastguard Worker
342*8d67ca89SAndroid Build Coastguard Worker```c
343*8d67ca89SAndroid Build Coastguard Worker    size_t bos_dst = __builtin_object_size(dst, 0);
344*8d67ca89SAndroid Build Coastguard Worker    if (bos_dst != -1 &&
345*8d67ca89SAndroid Build Coastguard Worker        !(__builtin_constant_p(copy_amount) && bos_dst >= copy_amount)) {
346*8d67ca89SAndroid Build Coastguard Worker```
347*8d67ca89SAndroid Build Coastguard Worker
348*8d67ca89SAndroid Build Coastguard WorkerIf Clang's frontend cannot determine a value for `__builtin_object_size`, Clang
349*8d67ca89SAndroid Build Coastguard Workerlowers it to LLVM's `@llvm.objectsize` intrinsic. The `@llvm.objectsize`
350*8d67ca89SAndroid Build Coastguard Workerinvocation corresponding to `__builtin_object_size(p, 0)` is guaranteed to
351*8d67ca89SAndroid Build Coastguard Workeralways fold to a constant value by the time LLVM emits machine code.
352*8d67ca89SAndroid Build Coastguard Worker
353*8d67ca89SAndroid Build Coastguard WorkerHence, `bos_dst` is guaranteed to be a constant; if it's -1, the above branch
354*8d67ca89SAndroid Build Coastguard Workercan be eliminated entirely, since it folds to `if (false && ...)`. Further, the
355*8d67ca89SAndroid Build Coastguard WorkerRHS of the `&&` in this branch has us call `__builtin_mempcpy` if `copy_amount`
356*8d67ca89SAndroid Build Coastguard Workeris a known value less than `bos_dst` (yet another constant value). Therefore,
357*8d67ca89SAndroid Build Coastguard Workerthe entire condition is always knowable when LLVM is done with LLVM IR-level
358*8d67ca89SAndroid Build Coastguard Workeroptimizations, so no condition is ever emitted to machine code in practice.
359*8d67ca89SAndroid Build Coastguard Worker
360*8d67ca89SAndroid Build Coastguard Worker#### Why is "zero overhead" in quotes? Why is `unique_ptr` relevant?
361*8d67ca89SAndroid Build Coastguard Worker
362*8d67ca89SAndroid Build Coastguard Worker`__builtin_object_size` and `__builtin_constant_p` are forced to be constants
363*8d67ca89SAndroid Build Coastguard Workerafter most optimizations take place. Until LLVM replaces both of these with
364*8d67ca89SAndroid Build Coastguard Workerconstants and optimizes them out, we have additional branches and function calls
365*8d67ca89SAndroid Build Coastguard Workerin our IR. This can have negative effects, such as distorting inlining costs and
366*8d67ca89SAndroid Build Coastguard Workerinhibiting optimizations that are conservative around branches in control-flow.
367*8d67ca89SAndroid Build Coastguard Worker
368*8d67ca89SAndroid Build Coastguard WorkerSo FORTIFY is free in these cases _in isolation of any of the code around it_.
369*8d67ca89SAndroid Build Coastguard WorkerDue to its implementation, it may impact the optimizations that occur on code
370*8d67ca89SAndroid Build Coastguard Workeraround the literal call to the FORTIFY-hardened libc function.
371*8d67ca89SAndroid Build Coastguard Worker
372*8d67ca89SAndroid Build Coastguard Worker`unique_ptr` was just the first thing that came to the author's mind for "the
373*8d67ca89SAndroid Build Coastguard Workertype should be zero cost with any level of optimization enabled, but edge-cases
374*8d67ca89SAndroid Build Coastguard Workermight make it only-mostly-free to use."
375*8d67ca89SAndroid Build Coastguard Worker
376*8d67ca89SAndroid Build Coastguard Worker### How is checking actually performed?
377*8d67ca89SAndroid Build Coastguard Worker
378*8d67ca89SAndroid Build Coastguard WorkerIn cases where checking can be performed (e.g., where we call
379*8d67ca89SAndroid Build Coastguard Worker`__builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);`), Bionic provides [an
380*8d67ca89SAndroid Build Coastguard Workerimplementation for `__mempcpy_chk`]. This is:
381*8d67ca89SAndroid Build Coastguard Worker
382*8d67ca89SAndroid Build Coastguard Worker```c
383*8d67ca89SAndroid Build Coastguard Workerextern "C" void* __mempcpy_chk(void* dst, const void* src, size_t count, size_t dst_len) {
384*8d67ca89SAndroid Build Coastguard Worker  __check_count("mempcpy", "count", count);
385*8d67ca89SAndroid Build Coastguard Worker  __check_buffer_access("mempcpy", "write into", count, dst_len);
386*8d67ca89SAndroid Build Coastguard Worker  return mempcpy(dst, src, count);
387*8d67ca89SAndroid Build Coastguard Worker}
388*8d67ca89SAndroid Build Coastguard Worker```
389*8d67ca89SAndroid Build Coastguard WorkerThis function itself boils down to a few small branches which abort the program
390*8d67ca89SAndroid Build Coastguard Workerif they fail, and a direct call to `__builtin_mempcpy`.
391*8d67ca89SAndroid Build Coastguard Worker
392*8d67ca89SAndroid Build Coastguard Worker### Wrapping up
393*8d67ca89SAndroid Build Coastguard Worker
394*8d67ca89SAndroid Build Coastguard WorkerIn the above breakdown, it was shown how Clang and Bionic work together to:
395*8d67ca89SAndroid Build Coastguard Worker- represent FORTIFY-hardened overloads of functions,
396*8d67ca89SAndroid Build Coastguard Worker- report misuses of stdlib functions at compile-time, and
397*8d67ca89SAndroid Build Coastguard Worker- insert run-time checks for uses of functions that might be incorrect, but only
398*8d67ca89SAndroid Build Coastguard Worker  if we have the potential of proving the incorrectness of these.
399*8d67ca89SAndroid Build Coastguard Worker
400*8d67ca89SAndroid Build Coastguard Worker## Breakdown of open
401*8d67ca89SAndroid Build Coastguard Worker
402*8d67ca89SAndroid Build Coastguard WorkerIn Bionic, the [FORTIFY'ed implementation of `open`] is quite large. Much like
403*8d67ca89SAndroid Build Coastguard Worker`mempcpy`, the `__builtin_open` declaration is simple:
404*8d67ca89SAndroid Build Coastguard Worker
405*8d67ca89SAndroid Build Coastguard Worker```c
406*8d67ca89SAndroid Build Coastguard Workerint open(const char* __path, int __flags, ...);
407*8d67ca89SAndroid Build Coastguard Worker```
408*8d67ca89SAndroid Build Coastguard Worker
409*8d67ca89SAndroid Build Coastguard WorkerWith some macros expanded, the FORTIFY-hardened header implementation is:
410*8d67ca89SAndroid Build Coastguard Worker```c
411*8d67ca89SAndroid Build Coastguard Workerint __open_2(const char*, int);
412*8d67ca89SAndroid Build Coastguard Workerint __open_real(const char*, int, ...) __asm__(open);
413*8d67ca89SAndroid Build Coastguard Worker
414*8d67ca89SAndroid Build Coastguard Worker#define __open_modes_useful(flags) (((flags) & O_CREAT) || ((flags) & O_TMPFILE) == O_TMPFILE)
415*8d67ca89SAndroid Build Coastguard Worker
416*8d67ca89SAndroid Build Coastguard Workerstatic
417*8d67ca89SAndroid Build Coastguard Workerint open(const char* pathname, int flags, mode_t modes, ...) __overloadable
418*8d67ca89SAndroid Build Coastguard Worker        __attribute__((diagnose_if(1, "error", "too many arguments")));
419*8d67ca89SAndroid Build Coastguard Worker
420*8d67ca89SAndroid Build Coastguard Workerstatic
421*8d67ca89SAndroid Build Coastguard Worker__inline__
422*8d67ca89SAndroid Build Coastguard Worker__attribute__((no_stack_protector))
423*8d67ca89SAndroid Build Coastguard Worker__attribute__((always_inline))
424*8d67ca89SAndroid Build Coastguard Workerint open(const char* const __attribute__((pass_object_size(1))) pathname, int flags)
425*8d67ca89SAndroid Build Coastguard Worker        __attribute__((overloadable))
426*8d67ca89SAndroid Build Coastguard Worker        __attribute__((diagnose_if(
427*8d67ca89SAndroid Build Coastguard Worker            __open_modes_useful(flags),
428*8d67ca89SAndroid Build Coastguard Worker            "error",
429*8d67ca89SAndroid Build Coastguard Worker            "'open' called with O_CREAT or O_TMPFILE, but missing mode"))) {
430*8d67ca89SAndroid Build Coastguard Worker#if __ANDROID_API__ >= 17 && __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
431*8d67ca89SAndroid Build Coastguard Worker    return __open_2(pathname, flags);
432*8d67ca89SAndroid Build Coastguard Worker#else
433*8d67ca89SAndroid Build Coastguard Worker    return __open_real(pathname, flags);
434*8d67ca89SAndroid Build Coastguard Worker#endif
435*8d67ca89SAndroid Build Coastguard Worker}
436*8d67ca89SAndroid Build Coastguard Workerstatic
437*8d67ca89SAndroid Build Coastguard Worker__inline__
438*8d67ca89SAndroid Build Coastguard Worker__attribute__((no_stack_protector))
439*8d67ca89SAndroid Build Coastguard Worker__attribute__((always_inline))
440*8d67ca89SAndroid Build Coastguard Workerint open(const char* const __attribute__((pass_object_size(1))) pathname, int flags, mode_t modes)
441*8d67ca89SAndroid Build Coastguard Worker        __attribute__((overloadable))
442*8d67ca89SAndroid Build Coastguard Worker        __clang_warning_if(!__open_modes_useful(flags) && modes,
443*8d67ca89SAndroid Build Coastguard Worker                           "'open' has superfluous mode bits; missing O_CREAT?") {
444*8d67ca89SAndroid Build Coastguard Worker    return __open_real(pathname, flags, modes);
445*8d67ca89SAndroid Build Coastguard Worker}
446*8d67ca89SAndroid Build Coastguard Worker```
447*8d67ca89SAndroid Build Coastguard Worker
448*8d67ca89SAndroid Build Coastguard WorkerWhich may be a lot to take in.
449*8d67ca89SAndroid Build Coastguard Worker
450*8d67ca89SAndroid Build Coastguard WorkerBefore diving too deeply, please note that the remainder of these subsections
451*8d67ca89SAndroid Build Coastguard Workerassume that the programmer didn't make any egregious typos. Moreover, there's no
452*8d67ca89SAndroid Build Coastguard Workerreal way that Bionic tries to prevent calls to `open` like
453*8d67ca89SAndroid Build Coastguard Worker`open("foo", 0, "how do you convert a const char[N] to mode_t?");`. The only
454*8d67ca89SAndroid Build Coastguard Workerreal C-compatible solution the author can think of is "stamp out many overloads
455*8d67ca89SAndroid Build Coastguard Workerto catch sort-of-common instances of this very uncommon typo." This isn't great.
456*8d67ca89SAndroid Build Coastguard Worker
457*8d67ca89SAndroid Build Coastguard WorkerMore directly, no effort is made below to recognize calls that, due to
458*8d67ca89SAndroid Build Coastguard Workerincompatible argument types, cannot go to any `open` implementation other than
459*8d67ca89SAndroid Build Coastguard Worker`__builtin_open`, since it's recognized right here. :)
460*8d67ca89SAndroid Build Coastguard Worker
461*8d67ca89SAndroid Build Coastguard Worker### Implementation breakdown
462*8d67ca89SAndroid Build Coastguard Worker
463*8d67ca89SAndroid Build Coastguard WorkerThis `open` implementation does a few things:
464*8d67ca89SAndroid Build Coastguard Worker- Turns calls to `open` with too many arguments into a compile-time error.
465*8d67ca89SAndroid Build Coastguard Worker- Diagnoses calls to `open` with missing modes at compile-time and run-time
466*8d67ca89SAndroid Build Coastguard Worker  (both cases turn into errors).
467*8d67ca89SAndroid Build Coastguard Worker- Emits warnings on calls to `open` with useless mode bits, unless the mode bits
468*8d67ca89SAndroid Build Coastguard Worker  are all 0.
469*8d67ca89SAndroid Build Coastguard Worker
470*8d67ca89SAndroid Build Coastguard WorkerOne common bit of code not explained below is the `__open_real` declaration above:
471*8d67ca89SAndroid Build Coastguard Worker```c
472*8d67ca89SAndroid Build Coastguard Workerint __open_real(const char*, int, ...) __asm__(open);
473*8d67ca89SAndroid Build Coastguard Worker```
474*8d67ca89SAndroid Build Coastguard Worker
475*8d67ca89SAndroid Build Coastguard WorkerThis exists as a way for us to call `__builtin_open` without needing clang to
476*8d67ca89SAndroid Build Coastguard Workerhave a pre-defined `__builtin_open` function.
477*8d67ca89SAndroid Build Coastguard Worker
478*8d67ca89SAndroid Build Coastguard Worker#### Compile-time error on too many arguments
479*8d67ca89SAndroid Build Coastguard Worker
480*8d67ca89SAndroid Build Coastguard Worker```c
481*8d67ca89SAndroid Build Coastguard Workerstatic
482*8d67ca89SAndroid Build Coastguard Workerint open(const char* pathname, int flags, mode_t modes, ...) __overloadable
483*8d67ca89SAndroid Build Coastguard Worker        __attribute__((diagnose_if(1, "error", "too many arguments")));
484*8d67ca89SAndroid Build Coastguard Worker```
485*8d67ca89SAndroid Build Coastguard Worker
486*8d67ca89SAndroid Build Coastguard WorkerWhich matches most calls to open that supply too many arguments, since
487*8d67ca89SAndroid Build Coastguard Worker`int(const char *, int, ...)` matches less strongly than
488*8d67ca89SAndroid Build Coastguard Worker`int(const char *, int, mode_t, ...)` for calls where the 3rd arg can be
489*8d67ca89SAndroid Build Coastguard Workerconverted to `mode_t` without too much effort. Because of the `diagnose_if`
490*8d67ca89SAndroid Build Coastguard Workerattribute, all of these calls turn into compile-time errors.
491*8d67ca89SAndroid Build Coastguard Worker
492*8d67ca89SAndroid Build Coastguard Worker#### Compile-time or run-time error on missing arguments
493*8d67ca89SAndroid Build Coastguard WorkerThe following overload handles all two-argument calls to `open`.
494*8d67ca89SAndroid Build Coastguard Worker```c
495*8d67ca89SAndroid Build Coastguard Workerstatic
496*8d67ca89SAndroid Build Coastguard Worker__inline__
497*8d67ca89SAndroid Build Coastguard Worker__attribute__((no_stack_protector))
498*8d67ca89SAndroid Build Coastguard Worker__attribute__((always_inline))
499*8d67ca89SAndroid Build Coastguard Workerint open(const char* const __attribute__((pass_object_size(1))) pathname, int flags)
500*8d67ca89SAndroid Build Coastguard Worker        __attribute__((overloadable))
501*8d67ca89SAndroid Build Coastguard Worker        __attribute__((diagnose_if(
502*8d67ca89SAndroid Build Coastguard Worker            __open_modes_useful(flags),
503*8d67ca89SAndroid Build Coastguard Worker            "error",
504*8d67ca89SAndroid Build Coastguard Worker            "'open' called with O_CREAT or O_TMPFILE, but missing mode"))) {
505*8d67ca89SAndroid Build Coastguard Worker#if __ANDROID_API__ >= 17 && __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
506*8d67ca89SAndroid Build Coastguard Worker    return __open_2(pathname, flags);
507*8d67ca89SAndroid Build Coastguard Worker#else
508*8d67ca89SAndroid Build Coastguard Worker    return __open_real(pathname, flags);
509*8d67ca89SAndroid Build Coastguard Worker#endif
510*8d67ca89SAndroid Build Coastguard Worker}
511*8d67ca89SAndroid Build Coastguard Worker```
512*8d67ca89SAndroid Build Coastguard Worker
513*8d67ca89SAndroid Build Coastguard WorkerLike `mempcpy`, `diagnose_if` handles emitting a compile-time error if the call
514*8d67ca89SAndroid Build Coastguard Workerto `open` is broken in a way that's visible to Clang's frontend. This
515*8d67ca89SAndroid Build Coastguard Workeressentially boils down to "`open` is being called with a `flags` value that
516*8d67ca89SAndroid Build Coastguard Workerrequires mode bits to be set."
517*8d67ca89SAndroid Build Coastguard Worker
518*8d67ca89SAndroid Build Coastguard WorkerIf that fails to catch a bug, we [unconditionally call `__open_2`], which
519*8d67ca89SAndroid Build Coastguard Workerperforms a run-time check:
520*8d67ca89SAndroid Build Coastguard Worker```c
521*8d67ca89SAndroid Build Coastguard Workerint __open_2(const char* pathname, int flags) {
522*8d67ca89SAndroid Build Coastguard Worker  if (needs_mode(flags)) __fortify_fatal("open: called with O_CREAT/O_TMPFILE but no mode");
523*8d67ca89SAndroid Build Coastguard Worker  return FDTRACK_CREATE_NAME("open", __openat(AT_FDCWD, pathname, force_O_LARGEFILE(flags), 0));
524*8d67ca89SAndroid Build Coastguard Worker}
525*8d67ca89SAndroid Build Coastguard Worker```
526*8d67ca89SAndroid Build Coastguard Worker
527*8d67ca89SAndroid Build Coastguard Worker#### Compile-time warning if modes are pointless
528*8d67ca89SAndroid Build Coastguard Worker
529*8d67ca89SAndroid Build Coastguard WorkerFinally, we have the following `open` call:
530*8d67ca89SAndroid Build Coastguard Worker```c
531*8d67ca89SAndroid Build Coastguard Workerstatic
532*8d67ca89SAndroid Build Coastguard Worker__inline__
533*8d67ca89SAndroid Build Coastguard Worker__attribute__((no_stack_protector))
534*8d67ca89SAndroid Build Coastguard Worker__attribute__((always_inline))
535*8d67ca89SAndroid Build Coastguard Workerint open(const char* const __attribute__((pass_object_size(1))) pathname, int flags, mode_t modes)
536*8d67ca89SAndroid Build Coastguard Worker        __attribute__((overloadable))
537*8d67ca89SAndroid Build Coastguard Worker        __clang_warning_if(!__open_modes_useful(flags) && modes,
538*8d67ca89SAndroid Build Coastguard Worker                           "'open' has superfluous mode bits; missing O_CREAT?") {
539*8d67ca89SAndroid Build Coastguard Worker    return __open_real(pathname, flags, modes);
540*8d67ca89SAndroid Build Coastguard Worker}
541*8d67ca89SAndroid Build Coastguard Worker```
542*8d67ca89SAndroid Build Coastguard Worker
543*8d67ca89SAndroid Build Coastguard WorkerThis simply issues a warning if Clang's frontend can determine that `flags`
544*8d67ca89SAndroid Build Coastguard Workerisn't necessary. Due to conventions in existing code, a `modes` value of `0` is
545*8d67ca89SAndroid Build Coastguard Workernot diagnosed.
546*8d67ca89SAndroid Build Coastguard Worker
547*8d67ca89SAndroid Build Coastguard Worker#### What about `&open`?
548*8d67ca89SAndroid Build Coastguard WorkerOne yet-unaddressed aspect of the above is how `&open` works. This is thankfully
549*8d67ca89SAndroid Build Coastguard Workera short answer:
550*8d67ca89SAndroid Build Coastguard Worker- It happens that `open` takes a parameter of type `const char*`.
551*8d67ca89SAndroid Build Coastguard Worker- It happens that `pass_object_size` -- an attribute only applicable to
552*8d67ca89SAndroid Build Coastguard Worker  parameters of type `T*` --  makes it impossible to take the address of a
553*8d67ca89SAndroid Build Coastguard Worker  function.
554*8d67ca89SAndroid Build Coastguard Worker
555*8d67ca89SAndroid Build Coastguard WorkerSince clang doesn't support a "this function should never have its address
556*8d67ca89SAndroid Build Coastguard Workertaken," attribute, Bionic uses the next best thing: `pass_object_size`. :)
557*8d67ca89SAndroid Build Coastguard Worker
558*8d67ca89SAndroid Build Coastguard Worker## Breakdown of poll
559*8d67ca89SAndroid Build Coastguard Worker
560*8d67ca89SAndroid Build Coastguard Worker(Preemptively: at the time of writing, Clang has no literal `__builtin_poll`
561*8d67ca89SAndroid Build Coastguard Workerbuiltin. `__builtin_poll` is referenced below to remain consistent with the
562*8d67ca89SAndroid Build Coastguard Workerconvention established in the Terminology section.)
563*8d67ca89SAndroid Build Coastguard Worker
564*8d67ca89SAndroid Build Coastguard WorkerBionic's `poll` implementation is closest to `mempcpy` above, though it has a
565*8d67ca89SAndroid Build Coastguard Workerfew interesting aspects worth examining.
566*8d67ca89SAndroid Build Coastguard Worker
567*8d67ca89SAndroid Build Coastguard WorkerThe [full header implementation of `poll`] is, with some macros expanded:
568*8d67ca89SAndroid Build Coastguard Worker```c
569*8d67ca89SAndroid Build Coastguard Worker#define __bos_fd_count_trivially_safe(bos_val, fds, fd_count) \
570*8d67ca89SAndroid Build Coastguard Worker  ((bos_val) == -1) || \
571*8d67ca89SAndroid Build Coastguard Worker    (__builtin_constant_p(fd_count) && \
572*8d67ca89SAndroid Build Coastguard Worker    (bos_val) >= sizeof(*fds) * (fd_count)))
573*8d67ca89SAndroid Build Coastguard Worker
574*8d67ca89SAndroid Build Coastguard Workerstatic
575*8d67ca89SAndroid Build Coastguard Worker__inline__
576*8d67ca89SAndroid Build Coastguard Worker__attribute__((no_stack_protector))
577*8d67ca89SAndroid Build Coastguard Worker__attribute__((always_inline))
578*8d67ca89SAndroid Build Coastguard Workerint poll(struct pollfd* const fds __attribute__((pass_object_size(1))), nfds_t fd_count, int timeout)
579*8d67ca89SAndroid Build Coastguard Worker    __attribute__((overloadable))
580*8d67ca89SAndroid Build Coastguard Worker    __attriubte__((diagnose_if(
581*8d67ca89SAndroid Build Coastguard Worker       __builtin_object_size(fds, 1) != -1 && __builtin_object_size(fds, 1) < sizeof(*fds) * fd_count,
582*8d67ca89SAndroid Build Coastguard Worker        "error",
583*8d67ca89SAndroid Build Coastguard Worker        "in call to 'poll', fd_count is larger than the given buffer"))) {
584*8d67ca89SAndroid Build Coastguard Worker  size_t bos_fds = __builtin_object_size(fds, 1);
585*8d67ca89SAndroid Build Coastguard Worker  if (!__bos_fd_count_trivially_safe(bos_fds, fds, fd_count)) {
586*8d67ca89SAndroid Build Coastguard Worker    return __poll_chk(fds, fd_count, timeout, bos_fds);
587*8d67ca89SAndroid Build Coastguard Worker  }
588*8d67ca89SAndroid Build Coastguard Worker  return (&poll)(fds, fd_count, timeout);
589*8d67ca89SAndroid Build Coastguard Worker}
590*8d67ca89SAndroid Build Coastguard Worker```
591*8d67ca89SAndroid Build Coastguard Worker
592*8d67ca89SAndroid Build Coastguard WorkerTo get the commonality with `mempcpy` and `open` out of the way:
593*8d67ca89SAndroid Build Coastguard Worker- This function is an overload with `__builtin_poll`.
594*8d67ca89SAndroid Build Coastguard Worker- The signature is the same, modulo the presence of a `pass_object_size`
595*8d67ca89SAndroid Build Coastguard Worker  attribute. Hence, for direct calls, overload resolution will always prefer it
596*8d67ca89SAndroid Build Coastguard Worker  over `__builtin_poll`. Taking the address of `poll` is forbidden, so all
597*8d67ca89SAndroid Build Coastguard Worker  references to `&poll` actually reference `__builtin_poll`.
598*8d67ca89SAndroid Build Coastguard Worker- When `fds` is too small to hold `fd_count` `pollfd`s, Clang will emit a
599*8d67ca89SAndroid Build Coastguard Worker  compile-time error if possible using `diagnose_if`.
600*8d67ca89SAndroid Build Coastguard Worker- If this can't be observed until run-time, `__poll_chk` verifies this.
601*8d67ca89SAndroid Build Coastguard Worker- When `fds` is a constant according to `__builtin_constant_p`, this always
602*8d67ca89SAndroid Build Coastguard Worker  compiles into `__poll_chk` for always-broken calls to `poll`, or
603*8d67ca89SAndroid Build Coastguard Worker  `__builtin_poll` for always-safe calls to `poll`.
604*8d67ca89SAndroid Build Coastguard Worker
605*8d67ca89SAndroid Build Coastguard WorkerThe critical bits to highlight here are on this line:
606*8d67ca89SAndroid Build Coastguard Worker```c
607*8d67ca89SAndroid Build Coastguard Workerint poll(struct pollfd* const fds __attribute__((pass_object_size(1))), nfds_t fd_count, int timeout)
608*8d67ca89SAndroid Build Coastguard Worker```
609*8d67ca89SAndroid Build Coastguard Worker
610*8d67ca89SAndroid Build Coastguard WorkerAnd this line:
611*8d67ca89SAndroid Build Coastguard Worker```c
612*8d67ca89SAndroid Build Coastguard Worker  return (&poll)(fds, fd_count, timeout);
613*8d67ca89SAndroid Build Coastguard Worker```
614*8d67ca89SAndroid Build Coastguard Worker
615*8d67ca89SAndroid Build Coastguard WorkerStarting with the simplest, we call `__builtin_poll` with `(&poll)(...);`. As
616*8d67ca89SAndroid Build Coastguard Workerreferenced above, taking the address of an overloaded function where all but one
617*8d67ca89SAndroid Build Coastguard Workeroverload has a `pass_object_size` attribute on one or more parameters always
618*8d67ca89SAndroid Build Coastguard Workerresolves to the function without any `pass_object_size` attributes.
619*8d67ca89SAndroid Build Coastguard Worker
620*8d67ca89SAndroid Build Coastguard WorkerThe other line deserves a section. The subtlety of it is almost entirely in the
621*8d67ca89SAndroid Build Coastguard Workeruse of `pass_object_size(1)` instead of `pass_object_size(0)`. on the `fds`
622*8d67ca89SAndroid Build Coastguard Workerparameter, and the corresponding use of `__builtin_object_size(fds, 1);` in the
623*8d67ca89SAndroid Build Coastguard Workerbody of `poll`.
624*8d67ca89SAndroid Build Coastguard Worker
625*8d67ca89SAndroid Build Coastguard Worker### Subtleties of __builtin_object_size(p, N)
626*8d67ca89SAndroid Build Coastguard Worker
627*8d67ca89SAndroid Build Coastguard WorkerEarlier in this document, it was said that a full description of each
628*8d67ca89SAndroid Build Coastguard Workerattribute/builtin necessary to power FORTIFY was out of scope. This is... only
629*8d67ca89SAndroid Build Coastguard Workersomewhat the case when we talk about `__builtin_object_size` and
630*8d67ca89SAndroid Build Coastguard Worker`pass_object_size`, especially when their second argument is `1`.
631*8d67ca89SAndroid Build Coastguard Worker
632*8d67ca89SAndroid Build Coastguard Worker#### tl;dr
633*8d67ca89SAndroid Build Coastguard Worker`__builtin_object_size(p, N)` and `pass_object_size(N)`, where `(N & 1) == 1`,
634*8d67ca89SAndroid Build Coastguard Workercan only be accurately determined by Clang. LLVM's `@llvm.objectsize` intrinsic
635*8d67ca89SAndroid Build Coastguard Workerignores the value of `N & 1`, since handling `(N & 1) == 1` accurately requires
636*8d67ca89SAndroid Build Coastguard Workerdata that's currently entirely inaccessible to LLVM, and that is difficult to
637*8d67ca89SAndroid Build Coastguard Workerpreserve through LLVM's optimization passes.
638*8d67ca89SAndroid Build Coastguard Worker
639*8d67ca89SAndroid Build Coastguard Worker`pass_object_size`'s "lifting" of the evaluation of
640*8d67ca89SAndroid Build Coastguard Worker`__builtin_object_size(p, N)` to the caller is critical, since it allows Clang
641*8d67ca89SAndroid Build Coastguard Workerfull visibility into the expression passed to e.g., `poll(&foo->bar, baz, qux)`.
642*8d67ca89SAndroid Build Coastguard WorkerIt's not a perfect solution, but it allows `N == 1` to be fully accurate in at
643*8d67ca89SAndroid Build Coastguard Workerleast some cases.
644*8d67ca89SAndroid Build Coastguard Worker
645*8d67ca89SAndroid Build Coastguard Worker#### Background
646*8d67ca89SAndroid Build Coastguard WorkerClang's implementation of `__builtin_object_size` aims to be compatible with
647*8d67ca89SAndroid Build Coastguard WorkerGCC's, which has [a decent bit of documentation]. Put simply,
648*8d67ca89SAndroid Build Coastguard Worker`__builtin_object_size(p, N)` is intended to evaluate at compile-time how many
649*8d67ca89SAndroid Build Coastguard Workerbytes can be accessed after `p` in a well-defined way. Straightforward examples
650*8d67ca89SAndroid Build Coastguard Workerof this are:
651*8d67ca89SAndroid Build Coastguard Worker```c
652*8d67ca89SAndroid Build Coastguard Workerchar buf[8];
653*8d67ca89SAndroid Build Coastguard Workerassert(__builtin_object_size(buf, N) == 8);
654*8d67ca89SAndroid Build Coastguard Workerassert(__builtin_object_size(buf + 1, N) == 7);
655*8d67ca89SAndroid Build Coastguard Worker```
656*8d67ca89SAndroid Build Coastguard Worker
657*8d67ca89SAndroid Build Coastguard WorkerThis should hold for all values of N that are valid to pass to
658*8d67ca89SAndroid Build Coastguard Worker`__builtin_object_size`. The `N` value of `__builtin_object_size` is a mask of
659*8d67ca89SAndroid Build Coastguard Workersettings.
660*8d67ca89SAndroid Build Coastguard Worker
661*8d67ca89SAndroid Build Coastguard Worker##### (N & 2) == ?
662*8d67ca89SAndroid Build Coastguard Worker
663*8d67ca89SAndroid Build Coastguard WorkerThis is mostly for completeness sake; in Bionic's FORTIFY implementation, N is
664*8d67ca89SAndroid Build Coastguard Workeralways either 0 or 1.
665*8d67ca89SAndroid Build Coastguard Worker
666*8d67ca89SAndroid Build Coastguard WorkerIf there are multiple possible values of `p` in a call to
667*8d67ca89SAndroid Build Coastguard Worker`__builtin_object_size(p, N)`, the second bit in `N` determines the behavior of
668*8d67ca89SAndroid Build Coastguard Workerthe compiler. If `(N & 2) == 0`, `__builtin_object_size` should return the
669*8d67ca89SAndroid Build Coastguard Workergreatest possible size for each possible value of `p`. Otherwise, it should
670*8d67ca89SAndroid Build Coastguard Workerreturn the least possible value. For example:
671*8d67ca89SAndroid Build Coastguard Worker
672*8d67ca89SAndroid Build Coastguard Worker```c
673*8d67ca89SAndroid Build Coastguard Workerchar smol_buf[7];
674*8d67ca89SAndroid Build Coastguard Workerchar buf[8];
675*8d67ca89SAndroid Build Coastguard Workerchar *p = rand() ? smol_buf : buf;
676*8d67ca89SAndroid Build Coastguard Workerassert(__builtin_object_size(p, 0) == 8);
677*8d67ca89SAndroid Build Coastguard Workerassert(__builtin_object_size(p, 2) == 7);
678*8d67ca89SAndroid Build Coastguard Worker```
679*8d67ca89SAndroid Build Coastguard Worker
680*8d67ca89SAndroid Build Coastguard Worker##### (N & 1) == 0
681*8d67ca89SAndroid Build Coastguard Worker
682*8d67ca89SAndroid Build Coastguard Worker`__builtin_object_size(p, 0)` is more or less as simple as the example in the
683*8d67ca89SAndroid Build Coastguard WorkerBackground section directly above. When Clang attempts to evaluate
684*8d67ca89SAndroid Build Coastguard Worker`__builtin_object_size(p, 0);` and when LLVM tries to determine the result of a
685*8d67ca89SAndroid Build Coastguard Workercorresponding `@llvm.objectsize` call to, they search for the storage underlying
686*8d67ca89SAndroid Build Coastguard Workerthe pointer in question. If that can be determined, Clang or LLVM can provide an
687*8d67ca89SAndroid Build Coastguard Workeranswer; otherwise, they cannot.
688*8d67ca89SAndroid Build Coastguard Worker
689*8d67ca89SAndroid Build Coastguard Worker##### (N & 1) == 1, and the true magic of pass_object_size
690*8d67ca89SAndroid Build Coastguard Worker
691*8d67ca89SAndroid Build Coastguard Worker`__builtin_object_size(p, 1)` has a less uniform implementation between LLVM and
692*8d67ca89SAndroid Build Coastguard WorkerClang. According to GCC's documentation, "If the least significant bit [of
693*8d67ca89SAndroid Build Coastguard Worker__builtin_object_size's second argument] is clear, objects are whole variables,
694*8d67ca89SAndroid Build Coastguard Workerif it is set, a closest surrounding subobject is considered the object a pointer
695*8d67ca89SAndroid Build Coastguard Workerpoints to."
696*8d67ca89SAndroid Build Coastguard Worker
697*8d67ca89SAndroid Build Coastguard WorkerThe "closest surrounding subobject," means that `(N & 1) == 1` depends on type
698*8d67ca89SAndroid Build Coastguard Workerinformation in order to operate in many cases. Consider the following examples:
699*8d67ca89SAndroid Build Coastguard Worker```c
700*8d67ca89SAndroid Build Coastguard Workerstruct Foo {
701*8d67ca89SAndroid Build Coastguard Worker  int a;
702*8d67ca89SAndroid Build Coastguard Worker  int b;
703*8d67ca89SAndroid Build Coastguard Worker};
704*8d67ca89SAndroid Build Coastguard Worker
705*8d67ca89SAndroid Build Coastguard Workerstruct Foo foo;
706*8d67ca89SAndroid Build Coastguard Workerassert(__builtin_object_size(&foo, 0) == sizeof(foo));
707*8d67ca89SAndroid Build Coastguard Workerassert(__builtin_object_size(&foo, 1) == sizeof(foo));
708*8d67ca89SAndroid Build Coastguard Workerassert(__builtin_object_size(&foo->a, 0) == sizeof(foo));
709*8d67ca89SAndroid Build Coastguard Workerassert(__builtin_object_size(&foo->a, 1) == sizeof(int));
710*8d67ca89SAndroid Build Coastguard Worker
711*8d67ca89SAndroid Build Coastguard Workerstruct Foo foos[2];
712*8d67ca89SAndroid Build Coastguard Workerassert(__builtin_object_size(&foos[0], 0) == 2 * sizeof(foo));
713*8d67ca89SAndroid Build Coastguard Workerassert(__builtin_object_size(&foos[0], 1) == sizeof(foo));
714*8d67ca89SAndroid Build Coastguard Workerassert(__builtin_object_size(&foos[0]->a, 0) == 2 * sizeof(foo));
715*8d67ca89SAndroid Build Coastguard Workerassert(__builtin_object_size(&foos[0]->a, 1) == sizeof(int));
716*8d67ca89SAndroid Build Coastguard Worker```
717*8d67ca89SAndroid Build Coastguard Worker
718*8d67ca89SAndroid Build Coastguard Worker...And perhaps somewhat surprisingly:
719*8d67ca89SAndroid Build Coastguard Worker```c
720*8d67ca89SAndroid Build Coastguard Workervoid example(struct Foo *foo) {
721*8d67ca89SAndroid Build Coastguard Worker  // (As a reminder, `-1` is "I don't know" when `(N & 2) == 0`.)
722*8d67ca89SAndroid Build Coastguard Worker  assert(__builtin_object_size(foo, 0) == -1);
723*8d67ca89SAndroid Build Coastguard Worker  assert(__builtin_object_size(foo, 1) == -1);
724*8d67ca89SAndroid Build Coastguard Worker  assert(__builtin_object_size(foo->a, 0) == -1);
725*8d67ca89SAndroid Build Coastguard Worker  assert(__builtin_object_size(foo->a, 1) == sizeof(int));
726*8d67ca89SAndroid Build Coastguard Worker}
727*8d67ca89SAndroid Build Coastguard Worker```
728*8d67ca89SAndroid Build Coastguard Worker
729*8d67ca89SAndroid Build Coastguard WorkerIn Clang, [this type-aware requirement poses problems for us]: Clang's frontend
730*8d67ca89SAndroid Build Coastguard Workerknows everything we could possibly want about the types of variables, but
731*8d67ca89SAndroid Build Coastguard Workeroptimizations are only performed by LLVM. LLVM has no reliable source for C or
732*8d67ca89SAndroid Build Coastguard WorkerC++ data types, so calls to `__builtin_object_size(p, N)` that cannot be
733*8d67ca89SAndroid Build Coastguard Workerresolved by clang are lowered to the equivalent of
734*8d67ca89SAndroid Build Coastguard Worker`__builtin_object_size(p, N & ~1)` in LLVM IR.
735*8d67ca89SAndroid Build Coastguard Worker
736*8d67ca89SAndroid Build Coastguard WorkerMoreover, Clang's frontend is the best-equipped part of the compiler to
737*8d67ca89SAndroid Build Coastguard Workeraccurately determine the answer for `__builtin_object_size(p, N)`, given we know
738*8d67ca89SAndroid Build Coastguard Workerwhat `p` is. LLVM is the best-equipped part of the compiler to determine the
739*8d67ca89SAndroid Build Coastguard Workervalue of `p`. This ordering issue is unfortunate.
740*8d67ca89SAndroid Build Coastguard Worker
741*8d67ca89SAndroid Build Coastguard WorkerThis is where `pass_object_size(N)` comes in. To summarize [the docs for
742*8d67ca89SAndroid Build Coastguard Worker`pass_object_size`], it evaluates `__builtin_object_size(p, N)` within the
743*8d67ca89SAndroid Build Coastguard Workercontext of the caller of the function annotated with `pass_object_size`, and
744*8d67ca89SAndroid Build Coastguard Workerpasses the value of that into the callee as an invisible parameter. All calls to
745*8d67ca89SAndroid Build Coastguard Worker`__builtin_object_size(parameter, N)` are substituted with references to this
746*8d67ca89SAndroid Build Coastguard Workerinvisible parameter.
747*8d67ca89SAndroid Build Coastguard Worker
748*8d67ca89SAndroid Build Coastguard WorkerPutting this plainly, Clang's frontend struggles to evaluate the following:
749*8d67ca89SAndroid Build Coastguard Worker```c
750*8d67ca89SAndroid Build Coastguard Workerint foo(void *p) {
751*8d67ca89SAndroid Build Coastguard Worker  return __builtin_object_size(p, 1);
752*8d67ca89SAndroid Build Coastguard Worker}
753*8d67ca89SAndroid Build Coastguard Worker
754*8d67ca89SAndroid Build Coastguard Workervoid bar() {
755*8d67ca89SAndroid Build Coastguard Worker  struct { int i, j } k;
756*8d67ca89SAndroid Build Coastguard Worker  // The frontend can't figure this interprocedural objectsize out, so it gets lowered to
757*8d67ca89SAndroid Build Coastguard Worker  // LLVM, which determines that the answer here is sizeof(k).
758*8d67ca89SAndroid Build Coastguard Worker  int baz = foo(&k.i);
759*8d67ca89SAndroid Build Coastguard Worker}
760*8d67ca89SAndroid Build Coastguard Worker```
761*8d67ca89SAndroid Build Coastguard Worker
762*8d67ca89SAndroid Build Coastguard WorkerHowever, with the magic of `pass_object_size`, we get one level of inlining to
763*8d67ca89SAndroid Build Coastguard Workerlook through:
764*8d67ca89SAndroid Build Coastguard Worker```c
765*8d67ca89SAndroid Build Coastguard Workerint foo(void *const __attribute__((pass_object_size(1))) p) {
766*8d67ca89SAndroid Build Coastguard Worker  return __builtin_object_size(p, 1);
767*8d67ca89SAndroid Build Coastguard Worker}
768*8d67ca89SAndroid Build Coastguard Worker
769*8d67ca89SAndroid Build Coastguard Workervoid bar() {
770*8d67ca89SAndroid Build Coastguard Worker  struct { int i, j } k;
771*8d67ca89SAndroid Build Coastguard Worker  // Due to pass_object_size, this is equivalent to:
772*8d67ca89SAndroid Build Coastguard Worker  // int baz = foo(&k.i, __builtin_object_size(&k.i, 1));
773*8d67ca89SAndroid Build Coastguard Worker  // ...and `int foo(void *)` is actually equivalent to:
774*8d67ca89SAndroid Build Coastguard Worker  // int foo(void *const, size_t size) {
775*8d67ca89SAndroid Build Coastguard Worker  //   return size;
776*8d67ca89SAndroid Build Coastguard Worker  // }
777*8d67ca89SAndroid Build Coastguard Worker  int baz = foo(&k.i);
778*8d67ca89SAndroid Build Coastguard Worker}
779*8d67ca89SAndroid Build Coastguard Worker```
780*8d67ca89SAndroid Build Coastguard Worker
781*8d67ca89SAndroid Build Coastguard WorkerSo we can obtain an accurate result in this case.
782*8d67ca89SAndroid Build Coastguard Worker
783*8d67ca89SAndroid Build Coastguard Worker##### What about pass_object_size(0)?
784*8d67ca89SAndroid Build Coastguard WorkerIt's sort of tangential, but if you find yourself wondering about the utility of
785*8d67ca89SAndroid Build Coastguard Worker`pass_object_size(0)` ... it's somewhat split. `pass_object_size(0)` in Bionic's
786*8d67ca89SAndroid Build Coastguard WorkerFORTIFY exists mostly for visual consistency, simplicity, and as a useful way to
787*8d67ca89SAndroid Build Coastguard Workerhave e.g., `&mempcpy` == `&__builtin_mempcpy`.
788*8d67ca89SAndroid Build Coastguard Worker
789*8d67ca89SAndroid Build Coastguard WorkerOutside of these fringe benefits, all of the functions with
790*8d67ca89SAndroid Build Coastguard Worker`pass_object_size(0)` on parameters are marked with `always_inline`, so
791*8d67ca89SAndroid Build Coastguard Worker"lifting" the `__builtin_object_size` call isn't ultimately very helpful. In
792*8d67ca89SAndroid Build Coastguard Workertheory, users can always have something like:
793*8d67ca89SAndroid Build Coastguard Worker
794*8d67ca89SAndroid Build Coastguard Worker```c
795*8d67ca89SAndroid Build Coastguard Worker// In some_header.h
796*8d67ca89SAndroid Build Coastguard Worker// This function does cool and interesting things with the `__builtin_object_size` of its parameter,
797*8d67ca89SAndroid Build Coastguard Worker// and is able to work with that as though the function were defined inline.
798*8d67ca89SAndroid Build Coastguard Workervoid out_of_line_function(void *__attribute__((pass_object_size(0))));
799*8d67ca89SAndroid Build Coastguard Worker```
800*8d67ca89SAndroid Build Coastguard Worker
801*8d67ca89SAndroid Build Coastguard WorkerThough the author isn't aware of uses like this in practice, beyond a few folks
802*8d67ca89SAndroid Build Coastguard Workeron LLVM's mailing list seeming interested in trying it someday.
803*8d67ca89SAndroid Build Coastguard Worker
804*8d67ca89SAndroid Build Coastguard Worker#### Wrapping up
805*8d67ca89SAndroid Build Coastguard WorkerIn the (long) section above, two things were covered:
806*8d67ca89SAndroid Build Coastguard Worker- The use of `(&poll)(...);` is a convenient shorthand for calling
807*8d67ca89SAndroid Build Coastguard Worker  `__builtin_poll`.
808*8d67ca89SAndroid Build Coastguard Worker- `__builtin_object_size(p, N)` with `(N & 1) == 1` is not easy for Clang to
809*8d67ca89SAndroid Build Coastguard Worker  answer accurately, since it relies on type info only available in the
810*8d67ca89SAndroid Build Coastguard Worker  frontend, and it sometimes relies on optimizations only available in the
811*8d67ca89SAndroid Build Coastguard Worker  middle-end. `pass_object_size` helps mitigate this.
812*8d67ca89SAndroid Build Coastguard Worker
813*8d67ca89SAndroid Build Coastguard Worker## Miscellaneous Notes
814*8d67ca89SAndroid Build Coastguard WorkerThe above should be a roughly comprehensive view of how FORTIFY works in the
815*8d67ca89SAndroid Build Coastguard Workerreal world. The main thing it fails to mention is the use of [the `diagnose_as_builtin` attribute] in Clang.
816*8d67ca89SAndroid Build Coastguard Worker
817*8d67ca89SAndroid Build Coastguard WorkerAs time has moved on, Clang has increasingly gained support for emitting
818*8d67ca89SAndroid Build Coastguard Workerwarnings that were previously emitted by FORTIFY machinery.
819*8d67ca89SAndroid Build Coastguard Worker`diagnose_as_builtin` allows us to remove the `diagnose_if`s from some of the
820*8d67ca89SAndroid Build Coastguard Worker`static inline` overloads of stdlib functions above, so Clang may diagnose them
821*8d67ca89SAndroid Build Coastguard Workerinstead.
822*8d67ca89SAndroid Build Coastguard Worker
823*8d67ca89SAndroid Build Coastguard WorkerClang's built-in diagnostics are often better than `diagnose_if` diagnostics,
824*8d67ca89SAndroid Build Coastguard Workersince Clang can format its diagnostics to include e.g., information about the
825*8d67ca89SAndroid Build Coastguard Workersizes of buffers in a suspect call to a function. `diagnose_if` can only have
826*8d67ca89SAndroid Build Coastguard Workerthe compiler output constant strings.
827*8d67ca89SAndroid Build Coastguard Worker
828*8d67ca89SAndroid Build Coastguard Worker[ChromeOS' Glibc patch]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/90fa9b27731db10a6010c7f7c25b24028145b091/sys-libs/glibc/files/local/glibc-2.33/0007-glibc-add-clang-style-FORTIFY.patch
829*8d67ca89SAndroid Build Coastguard Worker[FORTIFY'ed implementation of `open`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/include/bits/fortify/fcntl.h#41
830*8d67ca89SAndroid Build Coastguard Worker[FORTIFY'ed version of `mempcpy`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/include/bits/fortify/string.h#45
831*8d67ca89SAndroid Build Coastguard Worker[a decent bit of documentation]: https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
832*8d67ca89SAndroid Build Coastguard Worker[an implementation for `__mempcpy_chk`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/bionic/fortify.cpp#501
833*8d67ca89SAndroid Build Coastguard Worker[full header implementation of `poll`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/include/bits/fortify/poll.h#43
834*8d67ca89SAndroid Build Coastguard Worker[incompatible with stricter versions of FORTIFY checking]: https://godbolt.org/z/fGfEYxfnf
835*8d67ca89SAndroid Build Coastguard Worker[similar to C++11's `std::unique_ptr`]: https://stackoverflow.com/questions/58339165/why-can-a-t-be-passed-in-register-but-a-unique-ptrt-cannot
836*8d67ca89SAndroid Build Coastguard Worker[source for `mempcpy`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/include/string.h#55
837*8d67ca89SAndroid Build Coastguard Worker[the `diagnose_as_builtin` attribute]: https://releases.llvm.org/14.0.0/tools/clang/docs/AttributeReference.html#diagnose-as-builtin
838*8d67ca89SAndroid Build Coastguard Worker[the docs for `pass_object_size`]: https://releases.llvm.org/14.0.0/tools/clang/docs/AttributeReference.html#pass-object-size-pass-dynamic-object-size
839*8d67ca89SAndroid Build Coastguard Worker[this type-aware requirement poses problems for us]: https://github.com/llvm/llvm-project/issues/55742
840*8d67ca89SAndroid Build Coastguard Worker[unconditionally call `__open_2`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/bionic/open.cpp#70
841