History log of /llvm-project/lldb/test/API/linux/aarch64/gcs/TestAArch64LinuxGCS.py (Results 1 – 7 of 7)
Revision (<<< Hide revision tags) (Show revision tags >>>) Date Author Comments
Revision tags: llvmorg-21-init
# c5840cc6 28-Jan-2025 David Spickett <david.spickett@linaro.org>

[lldb][AArch64] Add register fields for Guarded Control Stack registers (#124295)

The features and locked registers hold the same bits, the latter
is a lock for the former. Tested with core files a

[lldb][AArch64] Add register fields for Guarded Control Stack registers (#124295)

The features and locked registers hold the same bits, the latter
is a lock for the former. Tested with core files and live processes.

I thought about setting a non-zero lock register in the core file,
however:
* We can be pretty sure it's reading correctly because its between
the 2 other GCS registers in the same core file note.
* I can't make the test case modify lock bits because userspace
can't clear them (without using ptrace) and we don't know what the libc
has locked
(probably all feature bits).

show more ...


# 75aa5a35 28-Jan-2025 David Spickett <david.spickett@linaro.org>

[lldb][AArch64] Add Guarded Control Stack support for Linux core files (#124293)

This allows you to read the same registers as you would for a live
process.

As the content of proc/pid/smaps is n

[lldb][AArch64] Add Guarded Control Stack support for Linux core files (#124293)

This allows you to read the same registers as you would for a live
process.

As the content of proc/pid/smaps is not included in the core file, we
don't get the "ss" marker that tell us that it is shadow stack. The GCS
region is still in the list though.

show more ...


# e9e06bea 27-Jan-2025 David Spickett <david.spickett@linaro.org>

[lldb][AArch64][NFC] Move a comment in GCS tests

Got put in the wrong place during a rebase.


# b31e9747 27-Jan-2025 David Spickett <david.spickett@linaro.org>

[lldb][AArch64] Fix expression evaluation with Guarded Control Stacks (#123918)

When the Guarded Control Stack (GCS) is enabled, returns cause the
processor to validate that the address at the loca

[lldb][AArch64] Fix expression evaluation with Guarded Control Stacks (#123918)

When the Guarded Control Stack (GCS) is enabled, returns cause the
processor to validate that the address at the location pointed to by
gcspr_el0 matches the one in the link register.

```
ret (lr=A) << pc

| GCS |
+=====+
| A |
| B | << gcspr_el0

Fault: tried to return to A when you should have returned to B.
```

Therefore when an expression wrapper function tries to return to the
expression return address (usually `_start` if there is a libc), it
would fault.

```
ret (lr=_start) << pc

| GCS |
+============+
| user_func1 |
| user_func2 | << gcspr_el0

Fault: tried to return to _start when you should have returned to user_func2.
```

To fix this we must push that return address to the GCS in
PrepareTrivialCall. This value is then consumed by the final return and
the expression completes as expected.

If for some reason that fails, we will manually restore the value of
gcspr_el0, because it turns out that PrepareTrivialCall
does not restore registers if it fails at all. So for now I am handling
gcspr_el0 specifically, but I have filed
https://github.com/llvm/llvm-project/issues/124269 to address the
general problem.

(the other things PrepareTrivialCall does are exceedingly likely to not
fail, so we have never noticed this)

```
ret (lr=_start) << pc

| GCS |
+============+
| user_func1 |
| user_func2 |
| _start | << gcspr_el0

No fault, we return to _start as normal.
```

The gcspr_el0 register will be restored after expression evaluation so
that the program can continue correctly.

However, due to restrictions in the Linux GCS ABI, we will not restore
the enable bit of gcs_features_enabled. Re-enabling GCS via ptrace is
not supported because it requires memory to be allocated by the kernel.

We could disable GCS if the expression enabled GCS, however this would
use up that state transition that the program might later rely on. And
generally it is cleaner to ignore the enable bit, rather than one state
transition of it.

We will also not restore the GCS entry that was overwritten with the
expression's return address. On the grounds that:
* This entry will never be used by the program. If the program branches,
the entry will be overwritten. If the program returns, gcspr_el0 will
point to the entry before the expression return address and that entry
will instead be validated.
* Any expression that calls functions will overwrite even more entries,
so the user needs to be aware of that anyway if they want to preserve
the contents of the GCS for inspection.
* An expression could leave the program in a state where restoring the
value makes the situation worse. Especially if we ever support this in
bare metal debugging.

I will later document all this on
https://lldb.llvm.org/use/aarch64-linux.html.

Tests have been added for:
* A function call that does not interact with GCS.
* A call that does, and disables it (we do not re-enable it).
* A call that does, and enables it (we do not disable it again).
* Failure to push an entry to the GCS stack.

show more ...


# 02c6002d 24-Jan-2025 David Spickett <david.spickett@linaro.org>

[lldb][AArch64] Add Guarded Control Stack registers (#123720)

The Guarded Control Stack extension implements a shadow stack and the
Linux kernel provides access to 3 registers for it via ptrace.

[lldb][AArch64] Add Guarded Control Stack registers (#123720)

The Guarded Control Stack extension implements a shadow stack and the
Linux kernel provides access to 3 registers for it via ptrace.

struct user_gcs {
__u64 features_enabled;
__u64 features_locked;
__u64 gcspr_el0;
};

This commit adds support for reading those from a live process.

The first 2 are pseudo registers based on the real control register and
the 3rd is a real register. This is the stack pointer for the guarded
stack.

I have added a "gcs_" prefix to the "features" registers so that they
have a clear name when shown individually. Also this means they will tab
complete from "gcs", and be next to gcspr_el0 in any sorted lists of
registers.

Guarded Control Stack Registers:
gcs_features_enabled = 0x0000000000000000
gcs_features_locked = 0x0000000000000000
gcspr_el0 = 0x0000000000000000

Testing is more of the usual, where possible I'm writing a register then
doing something in the program to confirm the value was actually sent to
ptrace.

show more ...


# 5658bc4a 21-Jan-2025 David Spickett <david.spickett@linaro.org>

[lldb][Linux] Add Control Protection Fault signal (#122917)

This will be sent by Arm's Guarded Control Stack extension when an
invalid return is executed.

The signal does have an address we coul

[lldb][Linux] Add Control Protection Fault signal (#122917)

This will be sent by Arm's Guarded Control Stack extension when an
invalid return is executed.

The signal does have an address we could show, but it's the PC at which
the fault occured. The debugger has plenty of ways to show you that
already, so I've left it out.

```
(lldb) c
Process 460 resuming
Process 460 stopped
* thread #1, name = 'test', stop reason = signal SIGSEGV: control protection fault
frame #0: 0x0000000000400784 test`main at main.c:57:1
54 afunc();
55 printf("return from main\n");
56 return 0;
-> 57 }
(lldb) dis
<...>
-> 0x400784 <+100>: ret
```

The new test case generates the signal by corrupting the link register
then attempting to return. This will work whether we manually enable GCS
or the C library does it for us.

(in the former case you could just return from main and it would fault)

show more ...


# b1751faa 14-Jan-2025 David Spickett <david.spickett@linaro.org>

[lldb][Linux] Mark memory regions used for shadow stacks (#117861)

This is intended for use with Arm's Guarded Control Stack extension
(GCS). Which reuses some existing shadow stack support in Linu

[lldb][Linux] Mark memory regions used for shadow stacks (#117861)

This is intended for use with Arm's Guarded Control Stack extension
(GCS). Which reuses some existing shadow stack support in Linux. It
should also work with the x86 equivalent.

A "ss" flag is added to the "VmFlags" line of shadow stack memory
regions in `/proc/<pid>/smaps`. To keep the naming generic I've called
it shadow stack instead of guarded control stack.

Also the wording is "shadow stack: yes" because the shadow stack region
is just where it's stored. It's enabled for the whole process or it
isn't. As opposed to memory tagging which can be enabled per region, so
"memory tagging: enabled" fits better for that.

I've added a test case that is also intended to be the start of a set of
tests for GCS. This should help me avoid duplicating the inline assembly
needed.

Note that no special compiler support is needed for the test. However,
for the intial enabling of GCS (assuming the libc isn't doing it) we do
need to use an inline assembly version of prctl.

This is because as soon as you enable GCS, all returns are checked
against the GCS. If the GCS is empty, the program will fault. In other
words, you can never return from the function that enabled GCS, unless
you push values onto it (which is possible but not needed here).

So you cannot use the libc's prctl wrapper for this reason. You can use
that wrapper for anything else, as we do to check if GCS is enabled.

show more ...