lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <30C972B6393DBAC5+cover.1760463245.git.tanyuan@tinylab.org>
Date: Wed, 15 Oct 2025 14:38:43 +0800
From: Yuan Tan <tanyuan@...ylab.org>
To: arnd@...db.de,
	masahiroy@...nel.org,
	nathan@...nel.org,
	palmer@...belt.com,
	linux-kbuild@...r.kernel.org,
	linux-riscv@...ts.infradead.org
Cc: linux-arch@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	i@...kray.me,
	tanyuan@...ylab.org,
	falcon@...ylab.org,
	ronbogo@...look.com,
	z1652074432@...il.com,
	lx24@....ynu.edu.cn
Subject: [PATCH v2/resend 0/8] dce, riscv: Unused syscall trimming with PUSHSECTION and conditional KEEP()

Hi all,

Sorry for the noise — it looks like my mail provider rewrote the Message-ID
of the cover letter, which broke the thread. I'm resending the cover letter
to make the series appear correctly threaded on lore.

This series aims to introduce syscall trimming support based on dead code
and data elimination (DCE). This can reduce the final image size, which is
particularly useful for embedded devices, while also reducing the attack
surface. It might further benefit specialized scenarios such as unikernels
or LTO builds, and could potentially help shrink the instruction cache
footprint.

Besides that, this series also introduces a new PUSHSECTION macro. This
wrapper allows sections created by .pushsection to have a proper reference
relationship with their callers, so that --gc-sections can safely work
without requiring unconditional KEEP() entries in linker scripts.

Since the new syscalltbl.sh infrastructure has been merged, I think it’s a
good time to push this patchsetTODO? forward.

Patch 1–3 introduce the infrastructure for TRIM_UNUSED_SYSCALLS, mainly
allowing syscalltbl.sh to decide which syscalls to keep according to
USED_SYSCALLS.
Patch 4 enables TRIM_UNUSED_SYSCALLS for the RISC-V architecture. With
syscalltbl.sh now available, this feature should be applicable to all
architectures that support LD_DEAD_CODE_DATA_ELIMINATION and use
syscalltbl.sh, but let’s focus on RISC-V first.
Patch 5–8 address the dependency inversion problem caused by sections
created with .pushsection that are forcibly retained by KEEP() in linker
scripts.

Here is an example to illustrate the problem:

void fun2(void);

void fun1(void) {
	asm volatile (
		".pushsection .text.pushed,\"ax\"\n\t" "call fun2\n\t"
		".popsection\n\t"
	);
}

If fun1() is used, .text.fun1 is kept alive, but .text.pushed has no
reference to .text.fun1, so --gc-sections may incorrectly discard
.text.pushed. To avoid this, the kernel traditionally wraps such sections
with KEEP() in the linker script. However, KEEP() introduces a dependency
inversion: if fun1() and fun2() are unused, .text.fun1, .text.fun2 and
.text.pushed should be removed, but KEEP() forces .text.pushed to stay,
which even keeps .text.fun2. As a result, sections that should be
eliminated are retained unnecessarily.

In Linux, sections such as ex_table, jump_table, bug_table, and alternative
are created by .pushsection and suffer from this issue. They prevent some
syscalls from being trimmed.

Ideally, .text.fun1 and .text.pushed should share the same fate: if fun1()
is not referenced, .text.pushed should be discarded as well. To achieve
this, we can establish a relocation with a directive between the caller and
the section created by .pushsection:

.section .text.fun1,"ax"
.reloc ., BFD_RELOC_NONE, pushedlabel
.pushsection .text.pushed,"ax" pushedlabel:
	call fun2
.popsection

Based on this idea, we introduce the PUSHSECTION macro. This macro emits a
relocation directive and a new label automatically, while remaining fully
compatible with all existing .pushsection parameters. With this macro, all
current uses of .pushsection (and even .section) in the kernel can be
replaced, significantly reducing the number of KEEP() in linker scripts and
enabling --gc-sections to work more effectively.

Without PUSHSECTION, there are 56 syscalls that cannot be trimmed in
defconfig and TRIM_UNUSED_SYSCALLS enabled. With PUSHSECTION, all syscalls
can now be properly trimmed.

We have tested enabling TRIM_UNUSED_SYSCALLS while keeping all syscalls
listed in USED_SYSCALLS and successfully booted Ubuntu on a configuration
based on v6.18-rc1 defconfig. The detailed configuration is provided in
[1]. This confirms that the trimming mechanism functions correctly under a
standard kernel setup.

The vmlinux size with tinyconfig is as follows:

|                                 | syscall remain | vmlinux size   | vmlinux after strip |
| ------------------------------- | -------------- | -------------- | ------------------- |
| enable DCE                      | 188            | 1437008        | 915160              |
| enable DCE and syscall trimming | 3              | 1263528 (-12%) | 800472 (-13%)       |


Changes in v2:
- Rebased on the unified syscalltbl.sh infrastructure for syscall trimming.
USED_SYSCALLS now accepts only syscall names to avoid confusion, whereas v1
also allowed entry point symbols.
- Uses the .reloc directive to establish dependencies.
Compared with previous proposals using SHF_LINK_ORDER or SHF_GROUP, this
approach provides a generic, parameter-compatible macro for all
.pushsection usages without side effects.


Previous versions:
- RFC: https://lore.kernel.org/lkml/cover.1676594211.git.falcon@tinylab.org/
- v1 part 1: https://lore.kernel.org/lkml/cover.1695679700.git.falcon@tinylab.org/
- v1 part 2: https://lore.kernel.org/lkml/cover.1699025537.git.tanyuan@tinylab.org/

Links:
[1] https://pastebin.com/St51bk2K


Yuan Tan (4):
  kconfig: add CONFIG_PUSHSECTION_WITH_RELOC for relocation support
  compiler.h: introduce PUSHSECTION macro to establish proper references
  vmlinux.lds.h: support conditional KEEP() in linker script
  riscv: use PUSHSECTION in ex_table, jump_table, bug_table and
    alternatives

Yuhang Zheng (4):
  init/Kconfig: add CONFIG_TRIM_UNUSED_SYSCALLS and related options
  scripts/syscalltbl.sh: add optional --used-syscalls argument for
    syscall trimming
  scripts/Makefile.asm-headers: pass USED_SYSCALLS to syscalltbl.sh
  riscv: enable HAVE_TRIM_UNUSED_SYSCALLS when toolchain supports DCE

 arch/riscv/Kconfig                          |  1 +
 arch/riscv/include/asm/alternative-macros.h |  8 ++--
 arch/riscv/include/asm/asm-extable.h        | 10 +++--
 arch/riscv/include/asm/bug.h                |  2 +-
 arch/riscv/include/asm/jump_label.h         |  3 +-
 arch/riscv/kernel/vmlinux.lds.S             |  9 +++-
 include/asm-generic/vmlinux.lds.h           | 12 ++++-
 include/linux/compiler.h                    | 43 +++++++++++++++++-
 include/linux/compiler_types.h              |  8 ++--
 init/Kconfig                                | 49 +++++++++++++++++++++
 scripts/Makefile.asm-headers                |  4 ++
 scripts/syscalltbl.sh                       | 19 +++++++-
 12 files changed, 150 insertions(+), 18 deletions(-)


base-commit: 3a8660878839faadb4f1a6dd72c3179c1df56787
prerequisite-patch-id: 7af3175326df94637f04a050dee7356416eb1edd
-- 
2.43.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ