Skip to content

Commit 7f2de1c

Browse files
committed
Improve docs. It was totally just me and not Claude rewriting it.
1 parent 2e9022d commit 7f2de1c

File tree

1 file changed

+67
-47
lines changed

1 file changed

+67
-47
lines changed

clang/include/clang/Basic/AttrDocs.td

Lines changed: 67 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3648,67 +3648,87 @@ def CFISaltDocs : Documentation {
36483648
let Heading = "cfi_salt";
36493649
let Label = "langext-cfi_salt";
36503650
let Content = [{
3651-
Use ``__attribute__((cfi_salt("<salt>")))`` on a function declaration, function
3652-
definition, or typedef to help distinguish CFI hashes between functions with
3653-
the same type signature. Take, for example, the Linux kernel, where there are
3654-
hundreds of functions with the same type signature that are indirectly
3655-
callable.
3651+
The ``cfi_salt`` attribute allows you to add a salt value to Control Flow
3652+
Integrity (CFI) type hashes to help distinguish between functions with the
3653+
same type signature. This attribute can be applied to function declarations,
3654+
function definitions, and function pointer typedefs.
36563655

3657-
.. code-block::
3658-
3659-
1662 functions with void (*)(void)
3660-
1179 functions with int (*)(void)
3661-
...
3656+
**Syntax:**
36623657

3663-
Making the CFI value distinct between them allows CFI to be more robust.
3658+
* GNU-style: ``__attribute__((cfi_salt("<salt_string>")))`
3659+
* C++11-style: ``[[clang::cfi_salt("<salt_string>")]]``
36643660

3665-
Example use:
3661+
**Usage:**
36663662

3667-
.. code-block:: c
3663+
The attribute takes a single string literal argument that serves as the salt.
3664+
Functions or function types with different salt values will have different CFI
3665+
hashes, even if they have identical type signatures.
36683666

3669-
// .h file:
3670-
#define __cfi_salt __attribute__((cfi_salt("pepper")))
3667+
**Motivation:**
36713668

3672-
// Convenient typedefs to avoid nested declarator syntax.
3673-
typedef int (*fptr_t)(void); // Non-salted function call.
3674-
typedef int (*fptr_salted_t)(void) __cfi_salt;
3669+
In large codebases like the Linux kernel, there are often hundreds of functions
3670+
with identical type signatures that are called indirectly:
36753671

3676-
struct widget_generator {
3677-
fptr_t init;
3678-
fptr_salted_t exec;
3679-
fptr_t teardown;
3680-
};
3672+
.. code-block::
36813673

3682-
// 1st .c file:
3683-
static int internal_init(void) { /* ... */ }
3684-
static int internal_salted_exec(void) __cfi_salt { /* ... */ }
3685-
static int internal_teardown(void) { /* ... */ }
3674+
1662 functions with void (*)(void)
3675+
1179 functions with int (*)(void)
3676+
...
36863677

3687-
static struct widget_generator _generator = {
3688-
.init = internal_init,
3689-
.exec = internal_salted_exec,
3690-
.teardown = internal_teardown,
3691-
};
3678+
By salting the CFI hashes, you can make CFI more robust by ensuring that
3679+
functions intended for different purposes have distinct CFI identities.
36923680

3693-
struct widget_generator *widget_gen = &_generator;
3681+
**Type Compatibility:**
36943682

3695-
// 2nd .c file:
3696-
int generate_a_widget(void) {
3697-
int ret;
3683+
* Functions with different salt values are considered to have incompatible types
3684+
* Function pointers with different salt values cannot be assigned to each other
3685+
* All declarations of the same function must use the same salt value
36983686

3699-
// Called with non-salted CFI.
3700-
ret = widget_gen->init();
3701-
if (ret)
3702-
return ret;
3687+
**Example:**
37033688

3704-
// Called with salted CFI.
3705-
ret = widget_gen->exec();
3706-
if (ret)
3707-
return ret;
3689+
.. code-block:: c
37083690

3709-
// Called with non-salted CFI.
3710-
return widget_gen->teardown();
3711-
}
3691+
// Header file - define convenience macros
3692+
#define __cfi_salt(s) __attribute__((cfi_salt(s)))
3693+
3694+
// Typedef for regular function pointers
3695+
typedef int (*fptr_t)(void);
3696+
3697+
// Typedef for salted function pointers
3698+
typedef int (*fptr_salted_t)(void) __cfi_salt("pepper");
3699+
3700+
struct widget_ops {
3701+
fptr_t init; // Regular CFI
3702+
fptr_salted_t exec; // Salted CFI
3703+
fptr_t cleanup; // Regular CFI
3704+
};
3705+
3706+
// Function implementations
3707+
static int widget_init(void) { return 0; }
3708+
static int widget_exec(void) __cfi_salt("pepper") { return 1; }
3709+
static int widget_cleanup(void) { return 0; }
3710+
3711+
static struct widget_ops ops = {
3712+
.init = widget_init, // OK - compatible types
3713+
.exec = widget_exec, // OK - both use "pepper" salt
3714+
.cleanup = widget_cleanup // OK - compatible types
3715+
};
3716+
3717+
// Using C++11 attribute syntax
3718+
void secure_callback(void) [[clang::cfi_salt("secure")]];
3719+
3720+
// This would cause a compilation error:
3721+
// fptr_t bad_ptr = widget_exec; // Error: incompatible types
3722+
3723+
**Notes:**
3724+
3725+
* The salt string can contain any characters, including spaces and quotes
3726+
* This attribute only applies to function types; using it on non-function
3727+
types will generate a warning
3728+
* All declarations and definitions of the same function must use identical
3729+
salt values
3730+
* The attribute affects type compatibility during compilation and CFI hash
3731+
generation during code generation
37123732

37133733
}];
37143734
}

0 commit comments

Comments
 (0)