Hello,
this is the third RFC version of Bootpatch-SLR. The previous RFCs were
sent to linux-hardening; this version is also sent to LKML for broader
review. Compared to RFC v2, it uses a new GAS feature instead of a
dedicated assembler inside the compiler plugin. Additionally, it
introduces the Sanemaker validation framework. This version rebases
BPSLR onto Linux 7.2-rc3 and resolves the boot failures that prevented
earlier rebases.

RFC v2:
    https://lists.openwall.net/linux-hardening/2026/06/20/5

Changes since RFC v2:
  - Implemented GAS fieldlabel feature to label immediate instruction
    operand bytes.
  - Removed pinpoint instruction pin assembler. Metadata now links
    directly against fieldlabels emitted by GAS.
  - Implemented Sanemaker validation tool and integrated it into the
    kernel.
  - Rebased Bootpatch-SLR onto Linux 7.2-rc3.
  - Excluded some RCU fields of task_struct from randomization to
    prevent boot crashes on new version.

Bootpatch-SLR enables per-instance structure layout randomization for
distribution kernels. While GCC's RandStruct pass randomizes layouts at
compile-time, every machine running the same kernel image receives the
same layout. Bootpatch-SLR applies comparable randomization during boot.

A full architectural overview and additional resources are available at:

    https://spslr.yjn-systems.com

At this stage, tooling is only available for x86_64. It is based on
Linux 7.2-rc3. Bootpatch-SLR currently randomizes most of the
task_struct. A few fields are exempt from randomization because of
current implementation details (see v2 cover letter).

Bootpatch-SLR requires a custom toolchain based on GCC 16.1.0 and GAS
2.46.1. GCC is extended to provide access to COMPONENT_REFs that are
usually folded inside the parser. The custom GAS provides the new
fieldlabel feature used to annotate encoded instruction patch sites.

An example for the fieldlabel feature is:

    movq $fieldlabel(8, .Lspslr_ipin_42, .Lspslr_ipin_width_42), %0

This causes the custom GAS to put the .Lspslr_ipin_42 label directly
onto the bytes encoding the immediate value 8. It additionally defines
the .Lspslr_ipin_width_42 label to be the size of the immediate field.
The metadata emitted by the Pinpoint plugin directly references these
symbols to specify exact patch-site locations.

The toolchain patches are available at:

    https://github.com/YJN-Systems/Selfpatch-SLR/tree/rfc-v3/toolchain

This RFC patch series is organized as follows:

 * Patch 1 adds the Pinpoint GCC plugin.

 * Patch 2 adds the Selfpatch runtime.

 * Patch 3 adds linker scripts and build integration.

 * Patch 4 applies BPSLR to the task_struct and integrates Sanemaker.

 * Patch 5 adds a simple tasklist sample module for sanity checking.

The current baseline configuration for testing is defconfig plus
CONFIG_SPSLR. Additionally, CONFIG_SAMPLES, CONFIG_SAMPLES_SPSLR, and
CONFIG_SAMPLES_SPSLR_TASKLIST can be enabled to build a simple
sanity-check module. Lastly, CONFIG_SANEMAKER can be set to make the
build compatible with the Sanemaker validation tool.

The Sanemaker sources are available at:

    https://github.com/YJN-Systems/Sanemaker/tree/rfc-v3

Further reading material on it is available at:

    https://spslr.yjn-systems.com/sanemaker.html

Sanemaker is a QEMU TCG plugin that traces every memory access that the
kernel performs. It normalizes accessed addresses to target type fields.
Between one run with BPSLR inactive and one run with the feature
enabled, it verifies that all instructions access the same fields in
both runs. Should an instruction be missed by pinpoint and thus be
insufficiently adjusted to a randomized layout, Sanemaker recognizes
that the instruction accesses the wrong field in the BPSLR-enabled run.
Integrated into CI pipelines, Sanemaker is meant to act as a deployment
barrier. It provides strong evidence that all instructions exercised
during testing behave correctly under BPSLR.

The RCU issue with the latest kernel version was reliably identified
using Sanemaker too. You can find a short blog post detailing the
investigation and results here:

    https://spslr.yjn-systems.com/blog/sanemk_kboot.html

The most immediate next points on my TODO list are:

  - Randomize the list heads. I intend to expand Selfpatch to refresh
    static data that depends on randomized field offsets.

  - Apply randomization to more target types. Optimally, v4 will
    randomize all types marked for randomization under RandStruct.

I immensely appreciate any feedback on any component or concept of this
system.

Thanks,
Jasper

York Jasper Niebuhr (5):
  Pinpoint plugin
  Selfpatch runtime
  SPSLR build integration
  SPSLR and Sanemaker source integration
  Tasklist sample module

 arch/x86/boot/startup/Makefile                |   4 +
 arch/x86/entry/vdso/common/Makefile.include   |   2 +-
 arch/x86/kernel/vmlinux.lds.S                 |  23 +
 include/linux/compiler_types.h                |   8 +
 include/linux/sched.h                         |  58 +-
 include/linux/spslr.h                         |  82 +++
 include/sanemaker/traps.h                     | 135 ++++
 init/Kconfig                                  |  13 +
 init/main.c                                   |  35 +
 kernel/Makefile                               |   2 +
 kernel/fork.c                                 |  10 +-
 kernel/module/main.c                          | 167 +++++
 kernel/spslr/Makefile                         |   7 +
 kernel/spslr/pinpoint.h                       |  76 +++
 kernel/spslr/sanemaker_traps.c                | 117 ++++
 kernel/spslr/spslr.c                          | 555 +++++++++++++++
 kernel/spslr/spslr_env.c                      |  74 ++
 kernel/spslr/spslr_env.h                      |  45 ++
 kernel/spslr/spslr_randomizer.c               | 646 ++++++++++++++++++
 kernel/spslr/spslr_randomizer.h               |  29 +
 samples/Kconfig                               |   3 +
 samples/Makefile                              |   1 +
 samples/spslr/Kconfig                         |  17 +
 samples/spslr/Makefile                        |   1 +
 samples/spslr/tasklist/Makefile               |   1 +
 samples/spslr/tasklist/tasklist.c             |  67 ++
 scripts/Makefile.gcc-plugins                  |   9 +
 scripts/gcc-plugins/Makefile                  |  18 +
 scripts/gcc-plugins/asm_offset_pass.c         |  79 +++
 scripts/gcc-plugins/dpin_registry.c           | 199 ++++++
 scripts/gcc-plugins/dpin_registry.h           |  22 +
 scripts/gcc-plugins/ipin_registry.c           | 367 ++++++++++
 scripts/gcc-plugins/ipin_registry.h           |  57 ++
 scripts/gcc-plugins/layout_hash.c             |  61 ++
 scripts/gcc-plugins/layout_hash.h             |   8 +
 scripts/gcc-plugins/on_finish_decl.c          |   8 +
 scripts/gcc-plugins/on_finish_type.c          |  12 +
 scripts/gcc-plugins/on_finish_unit.c          | 336 +++++++++
 .../gcc-plugins/on_preserve_component_ref.c   |  99 +++
 scripts/gcc-plugins/on_register_attributes.c  |  52 ++
 scripts/gcc-plugins/on_start_unit.c           |  11 +
 scripts/gcc-plugins/passes.h                  |  31 +
 scripts/gcc-plugins/pinpoint.c                | 103 +++
 scripts/gcc-plugins/pinpoint.h                |  75 ++
 .../gcc-plugins/rtl_ipin_survival_scan_pass.c |  37 +
 scripts/gcc-plugins/safe-attribs.h            |   9 +
 scripts/gcc-plugins/safe-diagnostic.h         |  10 +
 scripts/gcc-plugins/safe-gcc-plugin.h         |   6 +
 scripts/gcc-plugins/safe-ggc.h                |   8 +
 scripts/gcc-plugins/safe-gimple.h             |  14 +
 scripts/gcc-plugins/safe-input.h              |   9 +
 scripts/gcc-plugins/safe-langhooks.h          |   8 +
 scripts/gcc-plugins/safe-md5.h                |   8 +
 scripts/gcc-plugins/safe-output.h             |   8 +
 scripts/gcc-plugins/safe-plugin-version.h     |   8 +
 scripts/gcc-plugins/safe-rtl.h                |  17 +
 scripts/gcc-plugins/safe-tree.h               |  10 +
 scripts/gcc-plugins/separate_offset_pass.c    | 327 +++++++++
 scripts/gcc-plugins/serialize.c               | 303 ++++++++
 scripts/gcc-plugins/serialize.h               | 115 ++++
 .../gcc-plugins/target_hash_builtin_pass.c    | 167 +++++
 scripts/gcc-plugins/target_registry.c         | 492 +++++++++++++
 scripts/gcc-plugins/target_registry.h         |  59 ++
 scripts/module.lds.S                          |  25 +
 64 files changed, 5336 insertions(+), 29 deletions(-)
 create mode 100644 include/linux/spslr.h
 create mode 100644 include/sanemaker/traps.h
 create mode 100644 kernel/spslr/Makefile
 create mode 100644 kernel/spslr/pinpoint.h
 create mode 100644 kernel/spslr/sanemaker_traps.c
 create mode 100644 kernel/spslr/spslr.c
 create mode 100644 kernel/spslr/spslr_env.c
 create mode 100644 kernel/spslr/spslr_env.h
 create mode 100644 kernel/spslr/spslr_randomizer.c
 create mode 100644 kernel/spslr/spslr_randomizer.h
 create mode 100644 samples/spslr/Kconfig
 create mode 100644 samples/spslr/Makefile
 create mode 100644 samples/spslr/tasklist/Makefile
 create mode 100644 samples/spslr/tasklist/tasklist.c
 create mode 100644 scripts/gcc-plugins/asm_offset_pass.c
 create mode 100644 scripts/gcc-plugins/dpin_registry.c
 create mode 100644 scripts/gcc-plugins/dpin_registry.h
 create mode 100644 scripts/gcc-plugins/ipin_registry.c
 create mode 100644 scripts/gcc-plugins/ipin_registry.h
 create mode 100644 scripts/gcc-plugins/layout_hash.c
 create mode 100644 scripts/gcc-plugins/layout_hash.h
 create mode 100644 scripts/gcc-plugins/on_finish_decl.c
 create mode 100644 scripts/gcc-plugins/on_finish_type.c
 create mode 100644 scripts/gcc-plugins/on_finish_unit.c
 create mode 100644 scripts/gcc-plugins/on_preserve_component_ref.c
 create mode 100644 scripts/gcc-plugins/on_register_attributes.c
 create mode 100644 scripts/gcc-plugins/on_start_unit.c
 create mode 100644 scripts/gcc-plugins/passes.h
 create mode 100644 scripts/gcc-plugins/pinpoint.c
 create mode 100644 scripts/gcc-plugins/pinpoint.h
 create mode 100644 scripts/gcc-plugins/rtl_ipin_survival_scan_pass.c
 create mode 100644 scripts/gcc-plugins/safe-attribs.h
 create mode 100644 scripts/gcc-plugins/safe-diagnostic.h
 create mode 100644 scripts/gcc-plugins/safe-gcc-plugin.h
 create mode 100644 scripts/gcc-plugins/safe-ggc.h
 create mode 100644 scripts/gcc-plugins/safe-gimple.h
 create mode 100644 scripts/gcc-plugins/safe-input.h
 create mode 100644 scripts/gcc-plugins/safe-langhooks.h
 create mode 100644 scripts/gcc-plugins/safe-md5.h
 create mode 100644 scripts/gcc-plugins/safe-output.h
 create mode 100644 scripts/gcc-plugins/safe-plugin-version.h
 create mode 100644 scripts/gcc-plugins/safe-rtl.h
 create mode 100644 scripts/gcc-plugins/safe-tree.h
 create mode 100644 scripts/gcc-plugins/separate_offset_pass.c
 create mode 100644 scripts/gcc-plugins/serialize.c
 create mode 100644 scripts/gcc-plugins/serialize.h
 create mode 100644 scripts/gcc-plugins/target_hash_builtin_pass.c
 create mode 100644 scripts/gcc-plugins/target_registry.c
 create mode 100644 scripts/gcc-plugins/target_registry.h

-- 
2.43.0


Reply via email to