Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shadow call stack should be supported on aarch64-unknown-none #121972

Open
Darksonn opened this issue Mar 4, 2024 · 1 comment
Open

Shadow call stack should be supported on aarch64-unknown-none #121972

Darksonn opened this issue Mar 4, 2024 · 1 comment
Assignees
Labels
A-sanitizers Area: Sanitizers for correctness and code quality. C-bug Category: This is a bug. O-AArch64 Armv8-A or later processors in AArch64 mode T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Darksonn
Copy link
Contributor

Darksonn commented Mar 4, 2024

Passing the -Zsanitizer=shadow-call-stack flag to rustc when compiling for the aarch64-unknown-none target results in the following error:

error: shadow-call-stack sanitizer is not supported for this target

However, as long as the x18 register is reserved during codegen (see #121970), there shouldn't be any problem with enabling the shadow call stack sanitizer on aarch64-unknown-none. It is already supported on several other aarch64 targets (see #121966).

The Linux Kernel uses the aarch64-unknown-none target when compiling Rust code for aarch64. This flag is needed so that we can enable CONFIG_SHADOW_CALL_STACK when using Rust in the kernel.

For more information on this sanitizer, please see the relevant chapter in the unstable book.

Related to this thread on LKML.

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Mar 4, 2024
@jieyouxu jieyouxu added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. O-AArch64 Armv8-A or later processors in AArch64 mode A-target-feature Area: Enabling/disabling target features like AVX, Neon, etc. A-sanitizers Area: Sanitizers for correctness and code quality. C-bug Category: This is a bug. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. A-target-feature Area: Enabling/disabling target features like AVX, Neon, etc. labels Mar 4, 2024
Darksonn added a commit to Darksonn/linux that referenced this issue Mar 4, 2024
Add flags to support the shadow call stack sanitizer, both in the
dynamic and non-dynamic modes.

Right now, the compiler will emit the warning "unknown feature specified
for `-Ctarget-feature`: `reserve-x18`". However, the compiler still
passes it to the codegen backend, so the flag will work just fine. Once
rustc starts recognizing the flag (or provides another way to enable the
feature), it will stop emitting this warning. See [1] for the relevant
issue.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. However, I still think
it is reasonable to add the flag now, as it will at least fail the build
when using an invalid configuration, until the Rust compiler is fixed to
list -Zsanitizer=shadow-call-stack as supported for the target. See [2]
for the feature request to add this.

I have tested this change with Rust Binder on an Android device using
CONFIG_DYNAMIC_SCS. Without the -Ctarget-feature=+reserve-x18 flag, the
phone crashes immediately on boot, and with the flag, the phone appears
to work normally.

Link: rust-lang/rust#121970 [1]
Link: rust-lang/rust#121972 [2]
Signed-off-by: Alice Ryhl <[email protected]>
Darksonn added a commit to Darksonn/linux that referenced this issue Mar 4, 2024
Add flags to support the shadow call stack sanitizer, both in the
dynamic and non-dynamic modes.

Right now, the compiler will emit the warning "unknown feature specified
for `-Ctarget-feature`: `reserve-x18`". However, the compiler still
passes it to the codegen backend, so the flag will work just fine. Once
rustc starts recognizing the flag (or provides another way to enable the
feature), it will stop emitting this warning. See [1] for the relevant
issue.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. However, I still think
it is reasonable to add the flag now, as it will at least fail the build
when using an invalid configuration, until the Rust compiler is fixed to
list -Zsanitizer=shadow-call-stack as supported for the target. See [2]
for the feature request to add this.

I have tested this change with Rust Binder on an Android device using
CONFIG_DYNAMIC_SCS. Without the -Ctarget-feature=+reserve-x18 flag, the
phone crashes immediately on boot, and with the flag, the phone appears
to work normally.

Link: rust-lang/rust#121970 [1]
Link: rust-lang/rust#121972 [2]
Signed-off-by: Alice Ryhl <[email protected]>
Darksonn added a commit to Darksonn/linux that referenced this issue Mar 5, 2024
Add flags to support the shadow call stack sanitizer, both in the
dynamic and non-dynamic modes.

Right now, the compiler will emit the warning "unknown feature specified
for `-Ctarget-feature`: `reserve-x18`". However, the compiler still
passes it to the codegen backend, so the flag will work just fine. Once
rustc starts recognizing the flag (or provides another way to enable the
feature), it will stop emitting this warning. See [1] for the relevant
issue.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. However, I still think
it is reasonable to add the flag now, as it will at least fail the build
when using an invalid configuration, until the Rust compiler is fixed to
list -Zsanitizer=shadow-call-stack as supported for the target. See [2]
for the feature request to add this.

I have tested this change with Rust Binder on an Android device using
CONFIG_DYNAMIC_SCS. Without the -Ctarget-feature=+reserve-x18 flag, the
phone crashes immediately on boot, and with the flag, the phone appears
to work normally.

This contains a TODO to add the -Zuse-sync-unwind=n flag. The flag
defaults to n, so it isn't a problem today, but the flag is unstable, so
the default could change in a future compiler release.

Link: rust-lang/rust#121970 [1]
Link: rust-lang/rust#121972 [2]
Signed-off-by: Alice Ryhl <[email protected]>
Darksonn added a commit to Darksonn/linux that referenced this issue Mar 5, 2024
Add flags to support the shadow call stack sanitizer, both in the
dynamic and non-dynamic modes.

Right now, the compiler will emit the warning "unknown feature specified
for `-Ctarget-feature`: `reserve-x18`". However, the compiler still
passes it to the codegen backend, so the flag will work just fine. Once
rustc starts recognizing the flag (or provides another way to enable the
feature), it will stop emitting this warning. See [1] for the relevant
issue.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. However, I still think
it is reasonable to add the flag now, as it will at least fail the build
when using an invalid configuration, until the Rust compiler is fixed to
list -Zsanitizer=shadow-call-stack as supported for the target. See [2]
for the feature request to add this.

I have tested this change with Rust Binder on an Android device using
CONFIG_DYNAMIC_SCS. Without the -Ctarget-feature=+reserve-x18 flag, the
phone crashes immediately on boot, and with the flag, the phone appears
to work normally.

This contains a TODO to add the -Zuse-sync-unwind=n flag. The flag
defaults to n, so it isn't a problem today, but the flag is unstable, so
the default could change in a future compiler release.

Link: rust-lang/rust#121970 [1]
Link: rust-lang/rust#121972 [2]
Signed-off-by: Alice Ryhl <[email protected]>
Darksonn added a commit to Darksonn/linux that referenced this issue Mar 5, 2024
Add flags to support the shadow call stack sanitizer, both in the
dynamic and non-dynamic modes.

Right now, the compiler will emit the warning "unknown feature specified
for `-Ctarget-feature`: `reserve-x18`". However, the compiler still
passes it to the codegen backend, so the flag will work just fine. Once
rustc starts recognizing the flag (or provides another way to enable the
feature), it will stop emitting this warning. See [1] for the relevant
issue.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. However, I still think
it is reasonable to add the flag now, as it will at least fail the build
when using an invalid configuration, until the Rust compiler is fixed to
list -Zsanitizer=shadow-call-stack as supported for the target. See [2]
for the feature request to add this.

I have tested this change with Rust Binder on an Android device using
CONFIG_DYNAMIC_SCS. Without the -Ctarget-feature=+reserve-x18 flag, the
phone crashes immediately on boot, and with the flag, the phone appears
to work normally.

This contains a TODO to add the -Zuse-sync-unwind=n flag. The flag
defaults to n, so it isn't a problem today, but the flag is unstable, so
the default could change in a future compiler release.

Link: rust-lang/rust#121970 [1]
Link: rust-lang/rust#121972 [2]
Signed-off-by: Alice Ryhl <[email protected]>
Darksonn added a commit to Darksonn/linux that referenced this issue Mar 5, 2024
Add flags to support the shadow call stack sanitizer, both in the
dynamic and non-dynamic modes.

Right now, the compiler will emit the warning "unknown feature specified
for `-Ctarget-feature`: `reserve-x18`". However, the compiler still
passes it to the codegen backend, so the flag will work just fine. Once
rustc starts recognizing the flag (or provides another way to enable the
feature), it will stop emitting this warning. See [1] for the relevant
issue.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. However, I still think
it is reasonable to add the flag now, as it will at least fail the build
when using an invalid configuration, until the Rust compiler is fixed to
list -Zsanitizer=shadow-call-stack as supported for the target. See [2]
for the feature request to add this.

I have tested this change with Rust Binder on an Android device using
CONFIG_DYNAMIC_SCS. Without the -Ctarget-feature=+reserve-x18 flag, the
phone crashes immediately on boot, and with the flag, the phone appears
to work normally.

This contains a TODO to add the -Zuse-sync-unwind=n flag. The flag
defaults to n, so it isn't a problem today, but the flag is unstable, so
the default could change in a future compiler release.

Link: rust-lang/rust#121970 [1]
Link: rust-lang/rust#121972 [2]
Acked-by: Miguel Ojeda <[email protected]>
Tested-by: Valentin Obst <[email protected]>
Reviewed-by: Valentin Obst <[email protected]>
Signed-off-by: Alice Ryhl <[email protected]>
hubot pushed a commit to aosp-mirror/kernel_common that referenced this issue Mar 5, 2024
Add flags to support the shadow call stack sanitizer, both in the
dynamic and non-dynamic modes.

Right now, the compiler will emit the warning "unknown feature specified
for `-Ctarget-feature`: `reserve-x18`". However, the compiler still
passes it to the codegen backend, so the flag will work just fine. Once
rustc starts recognizing the flag (or provides another way to enable the
feature), it will stop emitting this warning. See [1] for the relevant
issue.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. However, I still think
it is reasonable to add the flag now, as it will at least fail the build
when using an invalid configuration, until the Rust compiler is fixed to
list -Zsanitizer=shadow-call-stack as supported for the target. See [2]
for the feature request to add this.

I have tested this change with Rust Binder on an Android device using
CONFIG_DYNAMIC_SCS. Without the -Ctarget-feature=+reserve-x18 flag, the
phone crashes immediately on boot, and with the flag, the phone appears
to work normally.

This contains a TODO to add the -Zuse-sync-unwind=n flag. The flag
defaults to n, so it isn't a problem today, but the flag is unstable, so
the default could change in a future compiler release.

Link: rust-lang/rust#121970 [1]
Link: rust-lang/rust#121972 [2]
Signed-off-by: Alice Ryhl <[email protected]>

Bug: 328033850
Link: https://lore.kernel.org/rust-for-linux/[email protected]/
Change-Id: Ia55287e1ed6da2d5d8d3d6414f2d9a0fc7d23e81
Signed-off-by: Alice Ryhl <[email protected]>
hubot pushed a commit to aosp-mirror/kernel_common that referenced this issue Mar 13, 2024
Add flags to support the shadow call stack sanitizer, both in the
dynamic and non-dynamic modes.

Right now, the compiler will emit the warning "unknown feature specified
for `-Ctarget-feature`: `reserve-x18`". However, the compiler still
passes it to the codegen backend, so the flag will work just fine. Once
rustc starts recognizing the flag (or provides another way to enable the
feature), it will stop emitting this warning. See [1] for the relevant
issue.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. However, I still think
it is reasonable to add the flag now, as it will at least fail the build
when using an invalid configuration, until the Rust compiler is fixed to
list -Zsanitizer=shadow-call-stack as supported for the target. See [2]
for the feature request to add this.

I have tested this change with Rust Binder on an Android device using
CONFIG_DYNAMIC_SCS. Without the -Ctarget-feature=+reserve-x18 flag, the
phone crashes immediately on boot, and with the flag, the phone appears
to work normally.

This contains a TODO to add the -Zuse-sync-unwind=n flag. The flag
defaults to n, so it isn't a problem today, but the flag is unstable, so
the default could change in a future compiler release.

Link: rust-lang/rust#121970 [1]
Link: rust-lang/rust#121972 [2]
Signed-off-by: Alice Ryhl <[email protected]>

Bug: 328033850
Link: https://lore.kernel.org/rust-for-linux/[email protected]/
Change-Id: Ia55287e1ed6da2d5d8d3d6414f2d9a0fc7d23e81
Signed-off-by: Alice Ryhl <[email protected]>
Darksonn added a commit to Darksonn/linux that referenced this issue Jul 4, 2024
As of rustc 1.80.0, the Rust compiler supports the -Zfixed-x18 flag, so
we can now use Rust with the shadow call stack sanitizer.

On older versions of Rust, it is possible to use shadow call stack by
passing -Ctarget-feature=+reserve-x18 instead of -Zfixed-x18. However,
this flag emits a warning, so this patch does not add support for that.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. See [2] for the
feature request to add this. Kconfig is not configured to reject this
configuration because that leads to cyclic Kconfig rules.

Link: rust-lang/rust#121972 [1]
Signed-off-by: Alice Ryhl <[email protected]>
Darksonn added a commit to Darksonn/linux that referenced this issue Jul 4, 2024
As of rustc 1.80.0, the Rust compiler supports the -Zfixed-x18 flag, so
we can now use Rust with the shadow call stack sanitizer.

On older versions of Rust, it is possible to use shadow call stack by
passing -Ctarget-feature=+reserve-x18 instead of -Zfixed-x18. However,
this flag emits a warning, so this patch does not add support for that.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. See [2] for the
feature request to add this. Kconfig is not configured to reject this
configuration because that leads to cyclic Kconfig rules.

Link: rust-lang/rust#121972 [1]
Signed-off-by: Alice Ryhl <[email protected]>
Darksonn added a commit to Darksonn/linux that referenced this issue Jul 4, 2024
As of rustc 1.80.0, the Rust compiler supports the -Zfixed-x18 flag, so
we can now use Rust with the shadow call stack sanitizer.

On older versions of Rust, it is possible to use shadow call stack by
passing -Ctarget-feature=+reserve-x18 instead of -Zfixed-x18. However,
this flag emits a warning, so this patch does not add support for that.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. See [2] for the
feature request to add this. Kconfig is not configured to reject this
configuration because that leads to cyclic Kconfig rules.

Link: rust-lang/rust#121972 [1]
Signed-off-by: Alice Ryhl <[email protected]>
Darksonn added a commit to Darksonn/linux that referenced this issue Jul 19, 2024
To use the shadow call stack sanitizer, you must pass special flags:

* On arm64, you must pass -ffixed-x18 to your C compiler.
* On riscv, you must pass --no-relax-gp to your linker.

These requirements also apply to Rust code. When using Rust on arm64,
you must pass the -Zfixed-x18 flag to rustc, which has the same effect
as the -ffixed-x18 flag does for C code. The -Zfixed-x18 flag requires
rustc version 1.80.0 or greater.

There is no need to pass any flags to rustc on riscv as only the linker
requires additional flags on this platform.

On older versions of Rust, it is still possible to use shadow call stack
by passing -Ctarget-feature=+reserve-x18 instead of -Zfixed-x18.
However, this flag emits a warning during the build, so this patch does
not add support for using it.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. See [1] for the
feature request for this. To avoid this compilation failure, Kconfig is
set up to reject such configurations.

The `depends on` clause is placed on `config RUST` to avoid a situation
where enabling Rust silently turns off the sanitizer. Instead, turning
on the sanitizer results in Rust being disabled. We generally do not
want changes to CONFIG_RUST to result in any mitigations being changed
or turned off.

To avoid a cyclic dependency between RUST and RUSTC_VERSION, the
RUSTC_VERSION symbol is changed to depend on HAVE_RUST instead of RUST.

Link: rust-lang/rust#121972 [1]
Signed-off-by: Alice Ryhl <[email protected]>
@dingxiangfei2009
Copy link
Contributor

@rustbot claim

Darksonn added a commit to Darksonn/linux that referenced this issue Jul 29, 2024
To use the shadow call stack sanitizer, you must pass special flags:

* On arm64, you must pass -ffixed-x18 to your compiler.
* On riscv, you must pass --no-relax-gp to your linker.

These requirements also apply to Rust code. When using Rust on arm64,
you must pass the -Zfixed-x18 flag to rustc, which has the same effect
as the -ffixed-x18 flag does for C code. The -Zfixed-x18 flag requires
rustc version 1.80.0 or greater.

There is no need to pass any flags to rustc on riscv as only the linker
requires additional flags on this platform.

On older versions of Rust, it is still possible to use shadow call stack
by passing -Ctarget-feature=+reserve-x18 instead of -Zfixed-x18.
However, this flag emits a warning during the build, so this patch does
not add support for using it.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. See [1] for the
relevant feature request. To avoid this compilation failure, Kconfig is
set up to reject such configurations.

The `depends on` clause is placed on `config RUST` to avoid a situation
where enabling Rust silently turns off the sanitizer. Instead, turning
on the sanitizer results in Rust being disabled. We generally do not
want changes to CONFIG_RUST to result in any mitigations being changed
or turned off.

Link: rust-lang/rust#121972 [1]
Signed-off-by: Alice Ryhl <[email protected]>
Darksonn added a commit to Darksonn/linux that referenced this issue Jul 29, 2024
To use the shadow call stack sanitizer, you must pass special flags:

* On arm64, you must pass -ffixed-x18 to your compiler.
* On riscv, you must pass --no-relax-gp to your linker.

These requirements also apply to Rust code. When using Rust on arm64,
you must pass the -Zfixed-x18 flag to rustc, which has the same effect
as the -ffixed-x18 flag does for C code. The -Zfixed-x18 flag requires
rustc version 1.80.0 or greater.

There is no need to pass any flags to rustc on riscv as only the linker
requires additional flags on this platform.

On older versions of Rust, it is still possible to use shadow call stack
by passing -Ctarget-feature=+reserve-x18 instead of -Zfixed-x18.
However, this flag emits a warning during the build, so this patch does
not add support for using it.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. See [1] for the
relevant feature request. To avoid this compilation failure, Kconfig is
set up to reject such configurations.

The `depends on` clause is placed on `config RUST` to avoid a situation
where enabling Rust silently turns off the sanitizer. Instead, turning
on the sanitizer results in Rust being disabled. We generally do not
want changes to CONFIG_RUST to result in any mitigations being changed
or turned off.

Link: rust-lang/rust#121972 [1]
Signed-off-by: Alice Ryhl <[email protected]>
Darksonn added a commit to Darksonn/linux that referenced this issue Aug 6, 2024
This patch adds all of the flags that are needed to support the shadow
call stack (SCS) sanitizer with Rust, and updates Kconfig to allow
configurations that work.

The -Zfixed-x18 flag is required to use SCS on arm64, and requires rustc
version 1.80.0 or greater. This restriction is reflected in Kconfig.

When CONFIG_DYNAMIC_SCS is enabled, the build will be configured to
include unwind tables in the build artifacts. Dynamic SCS uses the
unwind tables at boot to find all places that need to be patched. The
-Cforce-unwind-tables=y flag ensures that unwind tables are available
for Rust code.

In non-dynamic mode, the -Zsanitizer=shadow-call-stack flag is what
enables the SCS sanitizer.

At the time of writing, all released rustc versions up to and including
1.81 incorrectly think that the Rust targets aarch64-unknown-none and
riscv64-unknown-none-elf don't support -Zsanitizer=shadow-call-stack, so
the build will fail if you enable shadow call stack in non-dynamic mode.
See [1] for the relevant feature request. To avoid this compilation
failure, Kconfig is set up to reject such configurations.

Note that because these configurations are rejected, this patch only
allows SCS to be used with arm64 and not on riscv. However, once [1] is
implemented, I will submit a follow-up patch that allows configurations
without UNWIND_PATCH_PAC_INTO_SCS on sufficiently new compilers. That
patch will implicitly allow SCS to be enabled on riscv, but this is okay
because unlike arm64, riscv does not need any flags for rustc beyond
-Zsanitizer=shadow-call-stack.

It is possible to avoid the requirement of rustc 1.80.0 by using
-Ctarget-feature=+reserve-x18 instead of -Zfixed-x18. However, this flag
emits a warning during the build, so this patch does not add support for
using it and instead requires 1.80.0 or greater.

The `depends on` clause is placed on `config RUST` to avoid a situation
where enabling Rust silently turns off the sanitizer. Instead, turning
on the sanitizer results in Rust being disabled. We generally do not
want changes to CONFIG_RUST to result in any mitigations being changed
or turned off.

Link: rust-lang/rust#121972 [1]
Signed-off-by: Alice Ryhl <[email protected]>
Darksonn added a commit to Darksonn/linux that referenced this issue Aug 6, 2024
This patch adds all of the flags that are needed to support the shadow
call stack (SCS) sanitizer with Rust, and updates Kconfig to allow
configurations that work.

The -Zfixed-x18 flag is required to use SCS on arm64, and requires rustc
version 1.80.0 or greater. This restriction is reflected in Kconfig.

When CONFIG_DYNAMIC_SCS is enabled, the build will be configured to
include unwind tables in the build artifacts. Dynamic SCS uses the
unwind tables at boot to find all places that need to be patched. The
-Cforce-unwind-tables=y flag ensures that unwind tables are available
for Rust code.

In non-dynamic mode, the -Zsanitizer=shadow-call-stack flag is what
enables the SCS sanitizer.

At the time of writing, all released rustc versions up to and including
1.81 incorrectly think that the Rust targets aarch64-unknown-none and
riscv64-unknown-none-elf don't support -Zsanitizer=shadow-call-stack, so
the build will fail if you enable shadow call stack in non-dynamic mode.
See [1] for the relevant feature request. To avoid this compilation
failure, Kconfig is set up to reject such configurations.

Note that because these configurations are rejected, this patch only
allows SCS to be used with arm64 and not on riscv. However, once [1] is
implemented, I will submit a follow-up patch that allows configurations
without UNWIND_PATCH_PAC_INTO_SCS on sufficiently new compilers. That
patch will implicitly allow SCS to be enabled on riscv, but this is okay
because unlike arm64, riscv does not need any flags for rustc beyond
-Zsanitizer=shadow-call-stack.

It is possible to avoid the requirement of rustc 1.80.0 by using
-Ctarget-feature=+reserve-x18 instead of -Zfixed-x18. However, this flag
emits a warning during the build, so this patch does not add support for
using it and instead requires 1.80.0 or greater.

The `depends on` clause is placed on `config RUST` to avoid a situation
where enabling Rust silently turns off the sanitizer. Instead, turning
on the sanitizer results in Rust being disabled. We generally do not
want changes to CONFIG_RUST to result in any mitigations being changed
or turned off.

Link: rust-lang/rust#121972 [1]
Signed-off-by: Alice Ryhl <[email protected]>
Darksonn added a commit to Darksonn/linux that referenced this issue Aug 6, 2024
This patch adds all of the flags that are needed to support the shadow
call stack (SCS) sanitizer with Rust, and updates Kconfig to allow
configurations that work.

The -Zfixed-x18 flag is required to use SCS on arm64, and requires rustc
version 1.80.0 or greater. This restriction is reflected in Kconfig.

When CONFIG_DYNAMIC_SCS is enabled, the build will be configured to
include unwind tables in the build artifacts. Dynamic SCS uses the
unwind tables at boot to find all places that need to be patched. The
-Cforce-unwind-tables=y flag ensures that unwind tables are available
for Rust code.

In non-dynamic mode, the -Zsanitizer=shadow-call-stack flag is what
enables the SCS sanitizer.

At the time of writing, all released rustc versions up to and including
1.81 incorrectly think that the Rust targets aarch64-unknown-none and
riscv64-unknown-none-elf don't support -Zsanitizer=shadow-call-stack, so
the build will fail if you enable shadow call stack in non-dynamic mode.
See [1] for the relevant feature request. To avoid this compilation
failure, Kconfig is set up to reject such configurations.

Note that because these configurations are rejected, this patch only
allows SCS to be used with arm64 and not on riscv. However, once [1] is
implemented, I will submit a follow-up patch that allows configurations
without UNWIND_PATCH_PAC_INTO_SCS on sufficiently new compilers. That
patch will implicitly allow SCS to be enabled on riscv, but this is okay
because unlike arm64, riscv does not need any flags for rustc beyond
-Zsanitizer=shadow-call-stack.

It is possible to avoid the requirement of rustc 1.80.0 by using
-Ctarget-feature=+reserve-x18 instead of -Zfixed-x18. However, this flag
emits a warning during the build, so this patch does not add support for
using it and instead requires 1.80.0 or greater.

The `depends on` clause is placed on `config RUST` to avoid a situation
where enabling Rust silently turns off the sanitizer. Instead, turning
on the sanitizer results in Rust being disabled. We generally do not
want changes to CONFIG_RUST to result in any mitigations being changed
or turned off.

Link: rust-lang/rust#121972 [1]
Signed-off-by: Alice Ryhl <[email protected]>
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Aug 15, 2024
…-stack-sanitizer, r=tmandry

Unconditionally allow shadow call-stack sanitizer for AArch64

It is possible to do so whenever `-Z fixed-x18` is applied.

cc `@Darksonn` for context

The reasoning is that, as soon as reservation on `x18` is forced through the flag `fixed-x18`, on AArch64 the option to instrument with [Shadow Call Stack sanitizer](https://clang.llvm.org/docs/ShadowCallStack.html) is then applicable regardless of the target configuration.

At the every least, we would like to relax the restriction on specifically `aarch64-unknonw-none`. For this option, we can include a documentation change saying that users of compiled objects need to ensure that they are linked to runtime with Shadow Call Stack instrumentation support.

Related: rust-lang#121972
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Aug 15, 2024
…-stack-sanitizer, r=tmandry

Unconditionally allow shadow call-stack sanitizer for AArch64

It is possible to do so whenever `-Z fixed-x18` is applied.

cc ``@Darksonn`` for context

The reasoning is that, as soon as reservation on `x18` is forced through the flag `fixed-x18`, on AArch64 the option to instrument with [Shadow Call Stack sanitizer](https://clang.llvm.org/docs/ShadowCallStack.html) is then applicable regardless of the target configuration.

At the every least, we would like to relax the restriction on specifically `aarch64-unknonw-none`. For this option, we can include a documentation change saying that users of compiled objects need to ensure that they are linked to runtime with Shadow Call Stack instrumentation support.

Related: rust-lang#121972
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Aug 15, 2024
Rollup merge of rust-lang#128348 - dingxiangfei2009:allow-shadow-call-stack-sanitizer, r=tmandry

Unconditionally allow shadow call-stack sanitizer for AArch64

It is possible to do so whenever `-Z fixed-x18` is applied.

cc ``@Darksonn`` for context

The reasoning is that, as soon as reservation on `x18` is forced through the flag `fixed-x18`, on AArch64 the option to instrument with [Shadow Call Stack sanitizer](https://clang.llvm.org/docs/ShadowCallStack.html) is then applicable regardless of the target configuration.

At the every least, we would like to relax the restriction on specifically `aarch64-unknonw-none`. For this option, we can include a documentation change saying that users of compiled objects need to ensure that they are linked to runtime with Shadow Call Stack instrumentation support.

Related: rust-lang#121972
hubot pushed a commit to aosp-mirror/kernel_common that referenced this issue Aug 21, 2024
Add flags to support the shadow call stack sanitizer, both in the
dynamic and non-dynamic modes.

Right now, the compiler will emit the warning "unknown feature specified
for `-Ctarget-feature`: `reserve-x18`". However, the compiler still
passes it to the codegen backend, so the flag will work just fine. Once
rustc starts recognizing the flag (or provides another way to enable the
feature), it will stop emitting this warning. See [1] for the relevant
issue.

Currently, the compiler thinks that the aarch64-unknown-none target
doesn't support -Zsanitizer=shadow-call-stack, so the build will fail if
you enable shadow call stack in non-dynamic mode. However, I still think
it is reasonable to add the flag now, as it will at least fail the build
when using an invalid configuration, until the Rust compiler is fixed to
list -Zsanitizer=shadow-call-stack as supported for the target. See [2]
for the feature request to add this.

I have tested this change with Rust Binder on an Android device using
CONFIG_DYNAMIC_SCS. Without the -Ctarget-feature=+reserve-x18 flag, the
phone crashes immediately on boot, and with the flag, the phone appears
to work normally.

This contains a TODO to add the -Zuse-sync-unwind=n flag. The flag
defaults to n, so it isn't a problem today, but the flag is unstable, so
the default could change in a future compiler release.

Link: rust-lang/rust#121970 [1]
Link: rust-lang/rust#121972 [2]
Signed-off-by: Alice Ryhl <[email protected]>

Bug: 328033850
Link: https://lore.kernel.org/rust-for-linux/[email protected]/
Change-Id: Ia55287e1ed6da2d5d8d3d6414f2d9a0fc7d23e81
Signed-off-by: Alice Ryhl <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-sanitizers Area: Sanitizers for correctness and code quality. C-bug Category: This is a bug. O-AArch64 Armv8-A or later processors in AArch64 mode T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants