Skip to content

Commit 73a2422

Browse files
committed
Fix coding style violations
Improve docs and comments. Add a test for the type printer.
1 parent 66c1f79 commit 73a2422

File tree

15 files changed

+70
-151
lines changed

15 files changed

+70
-151
lines changed

clang/docs/PointerAuthentication.rst

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,52 @@ a number of different tests.
280280
normal interface. This may be true even on targets where pointer
281281
authentication is not enabled by default.
282282

283+
__ptrauth Qualifier
284+
^^^^^^^^^^^^^^^^^^^
285+
286+
``__ptrauth(key, address, discriminator)`` is an extended type
287+
qualifier which causes so-qualified objects to hold pointers signed using the
288+
specified schema rather than the default schema for such types.
289+
290+
In the current implementation in Clang, the qualified type must be a C pointer
291+
type, either to a function or to an object. It currently cannot be an
292+
Objective-C pointer type, a C++ reference type, or a block pointer type; these
293+
restrictions may be lifted in the future.
294+
295+
The qualifier's operands are as follows:
296+
297+
- ``key`` - an expression evaluating to a key value from ``<ptrauth.h>``; must
298+
be a constant expression
299+
300+
- ``address`` - whether to use address diversity (1) or not (0); must be
301+
a constant expression with one of these two values
302+
303+
- ``discriminator`` - a constant discriminator; must be a constant expression
304+
305+
See `Discriminators`_ for more information about discriminators.
306+
307+
Currently the operands must be constant-evaluable even within templates. In the
308+
future this restriction may be lifted to allow value-dependent expressions as
309+
long as they instantiate to a constant expression.
310+
311+
Consistent with the ordinary C/C++ rule for parameters, top-level ``__ptrauth``
312+
qualifiers on a parameter (after parameter type adjustment) are ignored when
313+
deriving the type of the function. The parameter will be passed using the
314+
default ABI for the unqualified pointer type.
315+
316+
If ``x`` is an object of type ``__ptrauth(key, address, discriminator) T``,
317+
then the signing schema of the value stored in ``x`` is a key of ``key`` and
318+
a discriminator determined as follows:
319+
320+
- if ``address`` is 0, then the discriminator is ``discriminator``;
321+
322+
- if ``address`` is 1 and ``discriminator`` is 0, then the discriminator is
323+
``&x``; otherwise
324+
325+
- if ``address`` is 1 and ``discriminator`` is non-zero, then the discriminator
326+
is ``ptrauth_blend_discriminator(&x, discriminator)``; see
327+
`ptrauth_blend_discriminator`_.
328+
283329
``<ptrauth.h>``
284330
~~~~~~~~~~~~~~~
285331

clang/include/clang/AST/Type.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1468,7 +1468,7 @@ class QualType {
14681468
}
14691469

14701470
bool hasAddressDiscriminatedPointerAuth() const {
1471-
if (auto ptrauth = getPointerAuth())
1471+
if (PointerAuthQualifier ptrauth = getPointerAuth())
14721472
return ptrauth.isAddressDiscriminated();
14731473
return false;
14741474
}

clang/include/clang/Basic/AttrDocs.td

Lines changed: 2 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,129 +1778,11 @@ an ability to alter memory into full control of a process.
17781778
The first argument to ``__ptrauth`` is the name of the signing key.
17791779
Valid key names for the target are defined in ``<ptrauth.h>``.
17801780

1781-
On ARM64, there are four keys:
1782-
1783-
- ``ptrauth_key_process_independent_data``
1784-
- ``ptrauth_key_process_dependent_data``
1785-
- ``ptrauth_key_process_independent_code``
1786-
- ``ptrauth_key_process_dependent_code``
1787-
1788-
In general, prefer using a code key for function pointers and a data key
1789-
for object pointers. The ARM64 architecture allows loads and calls to
1790-
execute more efficiently when the pointer is signed with an appropriate
1791-
key. Using code keys only for function pointers also substantially lessens
1792-
the risk of creating a so-called "signing oracle" for function pointers;
1793-
see the general pointer authentication language documentation.
1794-
1795-
Using a process-dependent key provides stronger protection against
1796-
cross-process attacks. However, it also inhibits certain memory
1797-
optimizations when a shared library is loaded into multiple processes.
1798-
Using a process-independent key also allows signed pointers to be passed
1799-
in shared memory. Note that even the process-independent keys may change
1800-
after a reboot, so signed values should never be serialized.
1801-
18021781
The second argument to ``__ptrauth`` is a flag (0 or 1) specifying whether
1803-
the object should use address discrimination. If only one argument is
1804-
given, the flag defaults to 0. Address discrimination provides strong
1805-
protection against attacks which copy signed pointers around in memory.
1806-
An attacker cannot usefully copy an arbitrary signed pointer over an
1807-
address-discriminated object. Nor can a value taken from an
1808-
address-discriminated object be usefully copied over some other signed
1809-
pointer. However, it is more expensive to copy values from one
1810-
address-discriminated object to another, even if the other arguments to
1811-
``__ptrauth`` are the same, and it is not valid to copy them with
1812-
``memcpy``. It is also not valid to map memory containing an
1813-
address-discriminated object into different places in the address
1814-
space, e.g. with ``mmap``.
1782+
the object should use address discrimination.
18151783

18161784
The third argument to ``__ptrauth`` is a small non-negative integer
1817-
which allows additional discrimination between objects. Using a
1818-
unique extra discriminator provides strong protection against attacks
1819-
which work by substituting one signed value for another. For example,
1820-
an attacker cannot usefully overwrite an object with a pointer from an
1821-
object using a different extra discriminator; this protection is similar
1822-
to the protection offered by address discrimination. A unique extra
1823-
discriminator also protects against "slide" attacks where an attacker
1824-
alters a pointer instead of altering the memory that the pointer points to.
1825-
The extra discriminator must be a constant expression. On ARM64,
1826-
its value must be between 0 and 65535. If the argument is not provided,
1827-
the default value is 0. It is generally preferable not to use the value 0,
1828-
especially with the process-independent keys, as this combination is used
1829-
in various places in the standard language ABI.
1830-
1831-
The type qualified by ``__ptrauth`` must be a pointer type. Currently
1832-
only C pointer types are allowed and not block pointers, Objective-C
1833-
object pointers, or C++ references. ``__ptrauth`` is parsed and interpreted
1834-
using the same language rules as qualifiers like ``const`` and ``volatile``.
1835-
For example:
1836-
1837-
.. code-block:: c
1838-
1839-
__ptrauth(...) int *ex0; /* invalid: qualifies 'int', which is not a pointer type */
1840-
int * __ptrauth(...) ex1; /* valid: ex1 has qualified type */
1841-
int * __ptrauth(...) *ex2; /* valid: ex2 is a pointer to a qualified object */
1842-
1843-
typedef int *intp;
1844-
__ptrauth(...) intp ex3; /* valid: ex3 has qualified type */
1845-
intp __ptrauth(...) ex4; /* valid: means the exact same thing as ex3 */
1846-
1847-
If a ``__ptrauth``-qualified l-value of function pointer type is
1848-
used as the function operand of a call expression, the function pointer
1849-
will be authenticated "atomically" with the call, such that an attacker
1850-
will not be able to corrupt the destination of the call even in the
1851-
presence of undefined behavior. (That is, the compiler must not
1852-
leave an un-signed pointer that it will later unconditionally trust
1853-
in a place where it could be feasibly overwritten by an attacker,
1854-
such as the stack or a callee-save register during an intervening call.
1855-
The compiler is not required to protect against improbable attacks
1856-
such as corruption of the register file, as might occur with a
1857-
corrupted kernel. It also need not guard against jumps to an arbitrary
1858-
place in the instruction stream, since such jumps would require an
1859-
attacker to already fully control the PC.)
1860-
1861-
If the ABI specifies that a pointer is always signed --- that is,
1862-
if the pointer is a function pointer and the target uses ABI function
1863-
pointer authentication --- then signing and authenticating it as part
1864-
of a load/store actually means resigning it to/from the standard ABI
1865-
signature schema. Similarly, if both operands of a simple assignment
1866-
operator are ``__ptrauth``-qualified, the pointer copied by the
1867-
assignment is resigned from the right-hand operand's schema to the
1868-
left-hand operand's schema. These resigning operations are also done
1869-
"atomically" in the same sense as above.
1870-
1871-
As a final guarantee, if the right-hand operand of an assignment or
1872-
the expression used to initialize a ``__ptrauth``-qualified object is
1873-
a direct reference to an object or function (e.g. ``&my_var``), the
1874-
signing of that pointer is atomic with the evaluaton of the reference
1875-
in this same sense.
1876-
1877-
Otherwise, there are no guarantees of atomicity, and it is the
1878-
programmer's responsibility to avoid allowing a store into a
1879-
``__ptrauth``-qualified object to create a potential "signing oracle"
1880-
which an attacker could use to sign an arbitrary pointer of their choice.
1881-
Such oracles are particularly problematic when the signing uses a code
1882-
key because the oracle could potentially be used to allow an attacker
1883-
to construct a validly-signed function pointer, v-table entry, or
1884-
return address that points to an arbitrary instruction, allowing them
1885-
to completely take over the PC. Programmers attempting to use
1886-
``__ptrauth`` to protect a data pointer, or to protect function pointers
1887-
on targets that do not use ABI function pointer authentication, should
1888-
aim to maintain a "chain of authentication" from initialization all
1889-
the way to the point at which the pointer is used. If this is infeasible,
1890-
they should consider using ``ptrauth_sign_generic_data`` instead.
1891-
1892-
Types that are written in r-value positions, such as return types,
1893-
parameter types, and cast types, may not be ``__ptrauth``-qualified
1894-
at the outermost level. This may be supported in the future.
1895-
1896-
In C++, the arguments to ``__ptrauth`` may not be instantiation-dependent.
1897-
This may be supported in the future.
1898-
1899-
This feature may be tested for with ``__has_feature(ptrauth_qualifier)``.
1900-
It is enabled whenever the ``ptrauth`` intrinsics are enabled.
1901-
1902-
``<ptrauth.h>`` provides predefined qualifiers for various language
1903-
features that implicitly use pointer authentication.
1785+
which allows additional discrimination between objects.
19041786
}];
19051787
}
19061788

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2823,7 +2823,7 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSp
28232823
mangleVendorQualifier("__unaligned");
28242824

28252825
// __ptrauth. Note that this is parameterized.
2826-
if (auto PtrAuth = Quals.getPointerAuth()) {
2826+
if (PointerAuthQualifier PtrAuth = Quals.getPointerAuth()) {
28272827
mangleVendorQualifier("__ptrauth");
28282828
// For now, since we only allow non-dependent arguments, we can just
28292829
// inline the mangling of those arguments as literals. We treat the

clang/lib/AST/TypePrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2470,7 +2470,7 @@ bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {
24702470
if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
24712471
return false;
24722472

2473-
if (auto PointerAuth = getPointerAuth())
2473+
if (PointerAuthQualifier PointerAuth = getPointerAuth())
24742474
if (!PointerAuth.isEmptyWhenPrinted(Policy))
24752475
return false;
24762476

@@ -2580,7 +2580,7 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
25802580
}
25812581
}
25822582

2583-
if (auto PointerAuth = getPointerAuth()) {
2583+
if (PointerAuthQualifier PointerAuth = getPointerAuth()) {
25842584
if (addSpace)
25852585
OS << ' ';
25862586
addSpace = true;

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,9 +1025,9 @@ llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty,
10251025
Qc.removePointerAuth();
10261026
assert(Qc.empty() && "Unknown type qualifier for debug info");
10271027
auto *FromTy = getOrCreateType(QualType(T, 0), Unit);
1028-
return DBuilder.createPtrAuthQualifiedType(
1029-
FromTy, Key, IsDiscr, ExtraDiscr, /*IsaPointer=*/IsaPointer,
1030-
/*AuthenticatesNullValues=*/AuthenticatesNullValues);
1028+
return DBuilder.createPtrAuthQualifiedType(FromTy, Key, IsDiscr,
1029+
ExtraDiscr, IsaPointer,
1030+
AuthenticatesNullValues);
10311031
} else {
10321032
assert(Qc.empty() && "Unknown type qualifier for debug info");
10331033
return getOrCreateType(QualType(T, 0), Unit);

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
796796
Qualifiers::ObjCLifetime lifetime = lvalue.getObjCLifetime();
797797
if (!lifetime) {
798798
llvm::Value *Value;
799-
if (auto PtrAuth = lvalue.getQuals().getPointerAuth()) {
799+
if (PointerAuthQualifier PtrAuth = lvalue.getQuals().getPointerAuth()) {
800800
Value = EmitPointerAuthQualify(PtrAuth, init, lvalue.getAddress());
801801
lvalue.getQuals().removePointerAuth();
802802
} else {

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,7 +2191,7 @@ RValue CodeGenFunction::EmitLoadOfAnyValue(LValue LV, AggValueSlot Slot,
21912191
/// returning the rvalue.
21922192
RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
21932193
// Load from __ptrauth.
2194-
if (auto PtrAuth = LV.getQuals().getPointerAuth()) {
2194+
if (PointerAuthQualifier PtrAuth = LV.getQuals().getPointerAuth()) {
21952195
LV.getQuals().removePointerAuth();
21962196
auto value = EmitLoadOfLValue(LV, Loc).getScalarVal();
21972197
return RValue::get(EmitPointerAuthUnqualify(PtrAuth, value, LV.getType(),
@@ -2427,7 +2427,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
24272427
}
24282428

24292429
// Handle __ptrauth qualification by re-signing the value.
2430-
if (auto PointerAuth = Dst.getQuals().getPointerAuth()) {
2430+
if (PointerAuthQualifier PointerAuth = Dst.getQuals().getPointerAuth()) {
24312431
Src = RValue::get(EmitPointerAuthQualify(PointerAuth, Src.getScalarVal(),
24322432
Dst.getType(), Dst.getAddress(),
24332433
/*known nonnull*/ false));
@@ -5654,7 +5654,8 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
56545654

56555655
switch (getEvaluationKind(E->getType())) {
56565656
case TEK_Scalar: {
5657-
if (auto PtrAuth = E->getLHS()->getType().getPointerAuth()) {
5657+
if (PointerAuthQualifier PtrAuth =
5658+
E->getLHS()->getType().getPointerAuth()) {
56585659
LValue LV = EmitCheckedLValue(E->getLHS(), TCK_Store);
56595660
LValue CopiedLV = LV;
56605661
CopiedLV.getQuals().removePointerAuth();

clang/lib/CodeGen/CGExprConstant.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2068,7 +2068,7 @@ llvm::Constant *ConstantLValueEmitter::tryEmit() {
20682068
}
20692069

20702070
// Apply pointer-auth signing from the destination type.
2071-
if (auto PointerAuth = DestType.getPointerAuth()) {
2071+
if (PointerAuthQualifier PointerAuth = DestType.getPointerAuth()) {
20722072
if (!result.HasDestPointerAuth) {
20732073
value = Emitter.tryEmitConstantSignedPointer(value, PointerAuth);
20742074
if (!value)
@@ -2119,7 +2119,7 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
21192119
return CGM.GetWeakRefReference(D).getPointer();
21202120

21212121
auto PtrAuthSign = [&](llvm::Constant *C) {
2122-
if (auto PointerAuth = DestType.getPointerAuth()) {
2122+
if (PointerAuthQualifier PointerAuth = DestType.getPointerAuth()) {
21232123
C = applyOffset(C);
21242124
C = Emitter.tryEmitConstantSignedPointer(C, PointerAuth);
21252125
return ConstantLValue(C, /*applied offset*/ true, /*signed*/ true);

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4850,7 +4850,7 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
48504850
Value *RHS;
48514851
LValue LHS;
48524852

4853-
if (auto PtrAuth = E->getLHS()->getType().getPointerAuth()) {
4853+
if (PointerAuthQualifier PtrAuth = E->getLHS()->getType().getPointerAuth()) {
48544854
LValue LV = CGF.EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store);
48554855
LV.getQuals().removePointerAuth();
48564856
llvm::Value *RV =

0 commit comments

Comments
 (0)