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

KCFI: Add KCFI arity indicator support #138368

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

rcvalle
Copy link
Member

@rcvalle rcvalle commented Mar 11, 2025

@rustbot
Copy link
Collaborator

rustbot commented Mar 11, 2025

r? @cjgillot

rustbot has assigned @cjgillot.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added PG-exploit-mitigations Project group: Exploit mitigations S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 11, 2025
@rustbot
Copy link
Collaborator

rustbot commented Mar 11, 2025

Some changes occurred in tests/ui/sanitizer

cc @rust-lang/project-exploit-mitigations, @rcvalle

Some changes occurred in tests/codegen/sanitizer

cc @rust-lang/project-exploit-mitigations, @rcvalle

@rcvalle rcvalle force-pushed the rust-kcfi-arity branch 2 times, most recently from 9df55b1 to 3cf7741 Compare March 11, 2025 19:12
@ojeda
Copy link
Contributor

ojeda commented Mar 11, 2025

Thanks Ramon for the very quick PR!

I think the matching LLVM PR is llvm/llvm-project#121070, not the other one, right?

Also, would it make sense to add a quick check for the instructions generated, so that we are sure LLVM is actually doing something? e.g. one of the ones from https://github.com/llvm/llvm-project/blob/main/llvm/test/CodeGen/X86/kcfi-arity.ll

@rust-log-analyzer

This comment has been minimized.

@rcvalle
Copy link
Member Author

rcvalle commented Mar 11, 2025

I think the matching LLVM PR is llvm/llvm-project#121070, not the other one, right?

Thanks for pointing that out! Sorry, I confused them. Fixed.

Also, would it make sense to add a quick check for the instructions generated, so that we are sure LLVM is actually doing something? e.g. one of the ones from https://github.com/llvm/llvm-project/blob/main/llvm/test/CodeGen/X86/kcfi-arity.ll

For module flags, we usually add tests up to to verifying that flags are added only because the side effects of adding them are not implemented in the Rust compiler (so we don't need to keep track of changes and update tests when changes are made in LLVM). Would that be okay for you?

@maurer
Copy link
Contributor

maurer commented Mar 11, 2025

Do we want to add a check when this flag is set that the LLVM is new enough? I think LLVM will silently ignore unknown module tags, so as is, this could result in someone setting -Zsanitizer-kcfi-arity with a rustc that can't actually produce the new-style tags, and being confused by tags that are incompatible with a clang that has that features enabled.

@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-llvm-18 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
#19 exporting to docker image format
#19 sending tarball 19.8s done
#19 DONE 32.7s
##[endgroup]
Setting extra environment values for docker:  --env ENABLE_GCC_CODEGEN=1 --env GCC_EXEC_PREFIX=/usr/lib/gcc/
[CI_JOB_NAME=x86_64-gnu-llvm-18]
[CI_JOB_NAME=x86_64-gnu-llvm-18]
debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured.
---
sccache: Listening on address 127.0.0.1:4226
##[group]Configure the build
configure: processing command line
configure: 
configure: build.configure-args := ['--build=x86_64-unknown-linux-gnu', '--llvm-root=/usr/lib/llvm-18', '--enable-llvm-link-shared', '--set', 'rust.randomize-layout=true', '--set', 'rust.thin-lto-import-instr-limit=10', '--enable-verbose-configure', '--enable-sccache', '--disable-manage-submodules', '--enable-locked-deps', '--enable-cargo-native-static', '--set', 'rust.codegen-units-std=1', '--set', 'dist.compression-profile=balanced', '--dist-compression-formats=xz', '--set', 'rust.lld=false', '--disable-dist-src', '--release-channel=nightly', '--enable-debug-assertions', '--enable-overflow-checks', '--enable-llvm-assertions', '--set', 'rust.verify-llvm-ir', '--set', 'rust.codegen-backends=llvm,cranelift,gcc', '--set', 'llvm.static-libstdcpp', '--enable-new-symbol-mangling']
configure: build.build          := x86_64-unknown-linux-gnu
configure: target.x86_64-unknown-linux-gnu.llvm-config := /usr/lib/llvm-18/bin/llvm-config
configure: llvm.link-shared     := True
configure: rust.randomize-layout := True
configure: rust.thin-lto-import-instr-limit := 10
---
  Number of decisions:   4447
  longest path:          1159 (code:    152)
  longest backtrack:       66 (code:    428)
Shared 86733 out of 152951 states by creating 14756 new states, saving 71977
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/expmed.cc: In function ‘rtx_def* extract_bit_field_1(rtx, poly_uint64, poly_uint64, int, rtx, machine_mode, machine_mode, bool, bool, rtx_def**)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/expmed.cc:1864:45: warning: ‘*(unsigned int*)((char*)&imode + offsetof(scalar_int_mode, scalar_int_mode::m_mode))’ may be used uninitialized [-Wmaybe-uninitialized]
 1864 |       rtx sub = extract_bit_field_as_subreg (mode1, op0, imode,
      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
 1865 |                                              bitsize, bitnum);
      |                                              ~~~~~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/expmed.cc:1824:19: note: ‘*(unsigned int*)((char*)&imode + offsetof(scalar_int_mode, scalar_int_mode::m_mode))’ was declared here
 1824 |   scalar_int_mode imode;
      |                   ^~~~~
At global scope:
cc1plus: note: unrecognized command-line option ‘-Wno-everything’ may have been intended to silence earlier diagnostics
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/gimple-range-gori.cc: In member function ‘void range_def_chain::dump(FILE*, basic_block, const char*)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/gimple-range-gori.cc:319:19: warning: format not a string literal and no format arguments [-Wformat-security]
---
      |                         ^
At global scope:
cc1plus: note: unrecognized command-line option ‘-Wno-everything’ may have been intended to silence earlier diagnostics
In file included from /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/libgccjit.cc:30:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.h: In member function ‘virtual bool gcc::jit::recording::type::is_same_type_as(gcc::jit::recording::type*)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.h:640:20: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
  640 |     if ((is_int () && other->is_int () || is_float() && other->is_float())
      |          ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/libgccjit.cc: In function ‘gcc_jit_type* gcc_jit_context_new_array_type(gcc_jit_context*, gcc_jit_location*, gcc_jit_type*, long unsigned int)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/libgccjit.cc:807:37: warning: comparison of unsigned expression in ‘>= 0’ is always true [-Wtype-limits]
  807 |   RETURN_NULL_IF_FAIL (num_elements >= 0, ctxt, NULL, "negative size");
---
At global scope:
cc1plus: note: unrecognized command-line option ‘-Wno-everything’ may have been intended to silence earlier diagnostics
In file included from /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-playback.h:31,
                 from /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/dummy-frontend.cc:25:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.h: In member function ‘virtual bool gcc::jit::recording::type::is_same_type_as(gcc::jit::recording::type*)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.h:640:20: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
  640 |     if ((is_int () && other->is_int () || is_float() && other->is_float())
      |          ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
At global scope:
cc1plus: note: unrecognized command-line option ‘-Wno-everything’ may have been intended to silence earlier diagnostics
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/../libgcc/libgcov-util.c: In function ‘gcov_info* gcov_read_profile_dir(const char*, int)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/../libgcc/libgcov-util.c:456:9: warning: ignoring return value of ‘int chdir(const char*)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  456 |   chdir (pwd);
      |   ~~~~~~^~~~~
At global scope:
cc1plus: note: unrecognized command-line option ‘-Wno-everything’ may have been intended to silence earlier diagnostics
In file included from /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-playback.h:31,
                 from /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-playback.cc:49:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.h: In member function ‘virtual bool gcc::jit::recording::type::is_same_type_as(gcc::jit::recording::type*)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.h:640:20: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
  640 |     if ((is_int () && other->is_int () || is_float() && other->is_float())
      |          ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
At global scope:
cc1plus: note: unrecognized command-line option ‘-Wno-everything’ may have been intended to silence earlier diagnostics
In file included from /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-playback.h:31,
                 from /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-builtins.cc:24:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.h: In member function ‘virtual bool gcc::jit::recording::type::is_same_type_as(gcc::jit::recording::type*)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.h:640:20: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
  640 |     if ((is_int () && other->is_int () || is_float() && other->is_float())
      |          ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/omp-builtins.def: At global scope:
./options.h:6899:37: warning: narrowing conversion of ‘global_options.gcc_options::x_flag_openacc’ from ‘int’ to ‘bool’ [-Wnarrowing]
 6899 | #define flag_openacc global_options.x_flag_openacc
      |                      ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-builtins.cc:58:23: note: in definition of macro ‘DEF_BUILTIN’
   58 |   {NAME, CLASS, TYPE, BOTH_P, FALLBACK_P, ATTRS, IMPLICIT},
      |                       ^~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/builtins.def:223:16: note: in expansion of macro ‘flag_openacc’
  223 |                flag_openacc, true, true, ATTRS, false, true)
      |                ^~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/omp-builtins.def:55:1: note: in expansion of macro ‘DEF_GOACC_BUILTIN_COMPILER’
   55 | DEF_GOACC_BUILTIN_COMPILER (BUILT_IN_ACC_ON_DEVICE, "acc_on_device",
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~
./options.h:6911:36: warning: narrowing conversion of ‘global_options.gcc_options::x_flag_openmp’ from ‘int’ to ‘bool’ [-Wnarrowing]
 6911 | #define flag_openmp global_options.x_flag_openmp
      |                     ~~~~~~~~~~~~~~~^~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-builtins.cc:58:23: note: in definition of macro ‘DEF_BUILTIN’
   58 |   {NAME, CLASS, TYPE, BOTH_P, FALLBACK_P, ATTRS, IMPLICIT},
      |                       ^~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/builtins.def:238:16: note: in expansion of macro ‘flag_openmp’
  238 |                flag_openmp, true, true, ATTRS, false, flag_openmp)
      |                ^~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/omp-builtins.def:72:1: note: in expansion of macro ‘DEF_GOMP_BUILTIN_COMPILER’
   72 | DEF_GOMP_BUILTIN_COMPILER (BUILT_IN_OMP_IS_INITIAL_DEVICE,
      | ^~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: note: unrecognized command-line option ‘-Wno-everything’ may have been intended to silence earlier diagnostics
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/gcc.cc: In function ‘long unsigned int get_random_number()’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/gcc.cc:10688:12: warning: ignoring return value of ‘ssize_t read(int, void*, size_t)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
10688 |       read (fd, &ret, sizeof (HOST_WIDE_INT));
---
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/gcc.cc:7930:9: warning: ignoring return value of ‘ssize_t write(int, const void*, size_t)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
 7930 |   write (fd, "\n\n", 2);
      |   ~~~~~~^~~~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/gcc.cc: In member function ‘void driver::final_actions() const’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/gcc.cc:9307:13: warning: ignoring return value of ‘int truncate(const char*, __off_t)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
 9307 |     truncate(totruncate_file, 0);
      |     ~~~~~~~~^~~~~~~~~~~~~~~~~~~~
At global scope:
cc1plus: note: unrecognized command-line option ‘-Wno-everything’ may have been intended to silence earlier diagnostics
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/gengtype-lex.l: In function ‘int yylex(const char**)’:
gengtype-lex.cc:357:15: warning: this statement may fall through [-Wimplicit-fallthrough=]
---
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/lto/lto-common.cc: In function ‘void lto_resolution_read(splay_tree, FILE*, lto_file*)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/lto/lto-common.cc:2091:10: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
 2091 |   fscanf (resolution, " ");   /* Read white space.  */
      |   ~~~~~~~^~~~~~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/lto/lto-common.cc:2093:9: warning: ignoring return value of ‘size_t fread(void*, size_t, size_t, FILE*)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
 2093 |   fread (obj_name, sizeof (char), name_len, resolution);
      |   ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/lto/lto-common.cc:2113:10: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
 2113 |   fscanf (resolution, "%u", &num_symbols);
      |   ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
At global scope:
cc1plus: note: unrecognized command-line option ‘-Wno-everything’ may have been intended to silence earlier diagnostics
In file included from /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.cc:32:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.h: In member function ‘virtual bool gcc::jit::recording::type::is_same_type_as(gcc::jit::recording::type*)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.h:640:20: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
  640 |     if ((is_int () && other->is_int () || is_float() && other->is_float())
      |          ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.cc: In member function ‘virtual void gcc::jit::recording::memento_of_set_personality_function::replay_into(gcc::jit::replayer*)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.cc:7595:72: warning: unused parameter ‘r’ [-Wunused-parameter]
 7595 | recording::memento_of_set_personality_function::replay_into (replayer *r)
---
Applying io_quotes_use            to linux/blkzoned.h
Applying io_quotes_use            to linux/ipmi.h
Applying io_quotes_use            to linux/psp-dbc.h
Applying io_quotes_use            to linux/bt-bmc.h
Applying io_quotes_use            to linux/tps6594_pfsm.h
Applying io_quotes_use            to linux/cxl_mem.h
Applying io_quotes_use            to linux/wmi.h
Applying io_quotes_use            to linux/auto_fs.h
Applying io_quotes_use            to linux/mmtimer.h
Applying io_quotes_use            to linux/f2fs.h
Applying io_quotes_use            to linux/vhost.h
---
Applying machine_name             to x86_64-linux-gnu/bits/unistd_ext.h
Applying io_quotes_use            to x86_64-linux-gnu/asm/mtrr.h
Applying io_quotes_use            to x86_64-linux-gnu/asm/amd_hsmp.h
Applying machine_name             to openssl/e_os2.h
Applying io_quotes_use            to drm/xe_drm.h
Applying io_quotes_use            to drm/radeon_drm.h
Applying io_quotes_use            to drm/panfrost_drm.h
Applying io_quotes_use            to drm/etnaviv_drm.h
Applying io_quotes_use            to drm/lima_drm.h
Applying io_quotes_use            to drm/qaic_accel.h
Applying io_quotes_use            to drm/vc4_drm.h
Applying io_quotes_use            to drm/i915_drm.h
Applying io_quotes_use            to drm/omap_drm.h
Applying io_quotes_use            to drm/pvr_drm.h
Applying io_quotes_use            to drm/amdgpu_drm.h
Applying io_quotes_use            to drm/vgem_drm.h
Applying io_quotes_use            to drm/msm_drm.h
Applying io_quotes_use            to drm/v3d_drm.h
Applying io_quotes_use            to drm/exynos_drm.h
Applying io_quotes_use            to drm/nouveau_drm.h
Applying io_quotes_use            to drm/drm.h
Applying io_quotes_use            to drm/habanalabs_accel.h
Applying io_quotes_use            to drm/tegra_drm.h
Applying io_quotes_use            to rdma/rdma_user_ioctl.h
cc1: note: self-tests are not enabled in this build
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/c++tools/server.cc: In function ‘void server(bool, int, module_resolver*)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/c++tools/server.cc:620:10: warning: ignoring return value of ‘int pipe(int*)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
---
  Downloaded boml v0.3.1
   Compiling boml v0.3.1
   Compiling y v0.1.0 (/checkout/compiler/rustc_codegen_gcc/build_system)
    Finished `release` profile [optimized] target(s) in 4.10s
     Running `/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-codegen/x86_64-unknown-linux-gnu/release/y test --use-backend gcc --gcc-path /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/install/lib --out-dir /checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/cg_gcc --release --mini-tests --std-tests`
`--gcc-path` was provided, ignoring config file. Using `/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/install/lib` as path for libgccjit
[BUILD] mini_core
[BUILD] example
[AOT] mini_core_hello_world
/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/cg_gcc/mini_core_hello_world
abc

@ojeda
Copy link
Contributor

ojeda commented Mar 11, 2025

For module flags, we usually add tests up to to verifying that flags are added only because the side effects of adding them are not implemented in the Rust compiler (so we don't need to keep track of changes and update tests when changes are made in LLVM). Would that be okay for you?

Up to the Rust compiler team, of course -- I am not sure what their policy is.

In any case, to be clear, I only meant it as a smoke test, rather than testing everything that LLVM does. In other words, just to be sure that LLVM actually did something with the module flag, rather than replicating every test in LLVM.

From a quick test, it seems LLVM (well, at least llc in Compiler Explorer) does not say anything if there is a typo in the module flag in the IR.

So what I thought is to check e.g. that we get, say, a mov edx, ... with the flag instead of a mov eax, ... without the flag.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PG-exploit-mitigations Project group: Exploit mitigations S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants