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

Add support for Arm64 including all changes in PR #1302 (@swine, @surajjs95, @t-msn, and others) #1439

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

puranjaymohan
Copy link
Contributor

@puranjaymohan puranjaymohan commented Feb 7, 2025

This is a rebase of #1302 with some more changes and some already merged patches removed.
It is supposed to work with the sframe based reliable stack unwinder posted upstream:

[PATCH 0/8] unwind, arm64: add sframe unwinder for kernel

NOTE:

  • The sframe sections are skipped for now in the livepatch module because the above series doesn't support modules yet. I am trying to make that work both from the kernel side and also in Kpatch and will add a patch later.

Building and testing a livepatch on a 6.12 arm64 kernel for the following basic patch:

[ec2-user@ip-172-31-32-86 ~]$ cat CVE-1234-5678.patch
From 9c372fa658da9ac55e3acb7c3e4f3035f9241c1d Mon Sep 17 00:00:00 2001
From: Puranjay Mohan <pjy@amazon.com>
Date: Tue, 14 Jan 2025 09:40:34 +0000
Subject: [PATCH] fs: proc: cmdline: livepatch test

This patch will be turned into a livepatch.

Signed-off-by: Puranjay Mohan <pjy@amazon.com>
---
 fs/proc/cmdline.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/fs/proc/cmdline.c b/fs/proc/cmdline.c
index a6f76121955f..90bef8411dbf 100644
--- a/fs/proc/cmdline.c
+++ b/fs/proc/cmdline.c
@@ -7,8 +7,7 @@

 static int cmdline_proc_show(struct seq_file *m, void *v)
 {
-       seq_puts(m, saved_command_line);
-       seq_putc(m, '\n');
+       seq_printf(m, "%s\n", "this has been live patched");
        return 0;
 }

--
2.47.1
[ec2-user@ip-172-31-32-86 ~]$ uname -r
6.12.11-6.47.al2023pjy.aarch64

[ec2-user@ip-172-31-32-86 ~]$ ./kpatch/kpatch-build/kpatch-build -v /usr/lib/debug/lib/modules/6.12.11-6.47.al2023pjy.aarch64/vmlinux -r kernel-6.12.11-6.47.al2023pjy.src.rpm CVE-1234-5678.patch
Using cache at /home/ec2-user/.kpatch/src
Testing patch file(s)
Reading special section data
Building original source
Building patched source
Extracting new and modified ELF sections
cmdline.o: changed function: cmdline_proc_show
Patched objects: vmlinux
Building patch module: livepatch-CVE-1234-5678.ko
SUCCESS
[ec2-user@ip-172-31-32-86 ~]$

Load and Unload test

[root@ip-172-31-32-86 ec2-user]# kpatch load livepatch-CVE-1234-5678.ko
loading patch module: livepatch-CVE-1234-5678.ko
waiting (up to 15 seconds) for patch transition to complete...
transition complete (2 seconds)
[root@ip-172-31-32-86 ec2-user]# dmesg
[69888.542598] livepatch: enabling patch 'livepatch_CVE_1234_5678'
[69888.544388] livepatch: 'livepatch_CVE_1234_5678': starting patching transition
[69890.128882] livepatch: 'livepatch_CVE_1234_5678': patching complete
[root@ip-172-31-32-86 ec2-user]#

[root@ip-172-31-32-86 ec2-user]# cat /proc/cmdline
this has been live patched

[root@ip-172-31-32-86 ec2-user]# kpatch unload livepatch-CVE-1234-5678.ko
disabling patch module: livepatch_CVE_1234_5678
waiting (up to 15 seconds) for patch transition to complete...
transition complete (1 seconds)
unloading patch module: livepatch_CVE_1234_5678
[root@ip-172-31-32-86 ec2-user]# dmesg
[69888.542598] livepatch: enabling patch 'livepatch_CVE_1234_5678'
[69888.544388] livepatch: 'livepatch_CVE_1234_5678': starting patching transition
[69890.128882] livepatch: 'livepatch_CVE_1234_5678': patching complete
[69906.212505] livepatch: 'livepatch_CVE_1234_5678': starting unpatching transition
[69907.128716] livepatch: 'livepatch_CVE_1234_5678': unpatching complete

[root@ip-172-31-32-86 ec2-user]# cat /proc/cmdline
BOOT_IMAGE=(hd0,gpt1)/boot/vmlinuz-6.12.11-6.47.al2023pjy.aarch64 root=UUID=da8e1b79-5f9e-4471-89e7-958620dff70a ro console=tty0 console=ttyS0,115200n8 nvme_core.io_timeout=4294967295 rd.emergency=poweroff rd.shell=0 selinux=1 security=selinux quiet numa_cma=1:64M

Unit tests pass with the objects at: https://github.com/mihails-strasuns/kpatch-unit-test-objs/tree/arm64

CC=gcc10 ARCHES=aarch64 make -j64 unit
make -C kpatch-build
make[1]: Entering directory '/local/home/pjy/code/Kpatch/kpatch-build'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/local/home/pjy/code/Kpatch/kpatch-build'
make -C test/unit
make[1]: Entering directory '/local/home/pjy/code/Kpatch/test/unit'
make -C objs/aarch64
make[2]: Entering directory '/local/home/pjy/code/Kpatch/test/unit/objs/aarch64'
BUILD bug-table-section
BUILD cmdline-string
BUILD data-new
BUILD data-read-mostly
BUILD fixup-section
BUILD gcc-isra
BUILD gcc-static-local-var-2
BUILD gcc-static-local-var-3
BUILD gcc-static-local-var-4
BUILD gcc-static-local-var-5
BUILD gcc-static-local-var-6
BUILD mapping
BUILD meminfo-init-FAIL
BUILD meminfo-string
BUILD new-function
BUILD parainstructions-section
BUILD smp-locks-section
BUILD special-static
BUILD syscall
BUILD tracepoints-section
TEST bug-table-section
TEST cmdline-string
TEST data-new
TEST fixup-section
TEST gcc-isra
TEST gcc-static-local-var-2
TEST gcc-static-local-var-3
TEST gcc-static-local-var-4
TEST gcc-static-local-var-5
TEST gcc-static-local-var-6
TEST meminfo-init
TEST meminfo-string
TEST new-function
TEST parainstructions-section
TEST smp-locks-section
BUILD ASSERT_RTNL-detect
TEST special-static
TEST mapping
TEST tracepoints-section
TEST syscall
TEST data-read-mostly
TEST ASSERT_RTNL-detect
make[2]: Leaving directory '/local/home/pjy/code/Kpatch/test/unit/objs/aarch64'
make[1]: Leaving directory '/local/home/pjy/code/Kpatch/test/unit'
Integration tests
[root@ip-172-31-32-86 kpatch]# KPATCH_BUILD_OPTS=-R make -j64 integration-slow
make -C kpatch-build
make -C kpatch
make -C kmod
make[1]: Entering directory '/home/ec2-user/kpatch/kpatch-build'
make[1]: Entering directory '/home/ec2-user/kpatch/kmod'
make[1]: Entering directory '/home/ec2-user/kpatch/kpatch'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/home/ec2-user/kpatch/kpatch'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/home/ec2-user/kpatch/kmod'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/home/ec2-user/kpatch/kpatch-build'
make -C test/integration slow
make[1]: Entering directory '/home/ec2-user/kpatch/test/integration'
rm -f *.ko *.log COMBINED.patch
./kpatch-test --kpatch-build-opts="-R" -d "amzn"-"2023"
build: data-new
build: gcc-static-local-var-6
build: macro-callbacks
build: module
build: new-function
build: new-globals
build: shadow-newpid
build: special-static
build: symvers-disagreement-FAIL
build: syscall
build: warn-detect-FAIL
combine: skipping amzn-2023/symvers-disagreement-FAIL.patch
combine: skipping amzn-2023/warn-detect-FAIL.patch
build: combined module
load test: data-new
load test: gcc-static-local-var-6 (no test prog)
load test: macro-callbacks (no test prog)
load test: module
load test: new-function (no test prog)
load test: new-globals (no test prog)
load test: shadow-newpid
load test: special-static (no test prog)
load test: syscall
load test: combined module
custom test: multiple
SUCCESS
make[1]: Leaving directory '/home/ec2-user/kpatch/test/integration'
[root@ip-172-31-32-86 kpatch]# echo $?
0

puranjaymohan and others added 7 commits February 7, 2025 10:33
Signed-off-by: Puranjay Mohan <pjy@amazon.com>
The "has_function_profiling" support field in the symbol struct is used to show
that a function symbol is able to be patched. This is necessary to check that
functions which need to be patched are able to be.

On arm64 this means the presence of 2 NOP instructions at function entry
which are patched by ftrace to call the ftrace handling code. These 2 NOPs
are inserted by the compiler and the location of them is recorded in a
section called "__patchable_function_entries". Check whether a symbol has a
corresponding entry in the "__patchable_function_entries" section and if so
mark it as "has_func_profiling".

Signed-off-by: Suraj Jitindar Singh <surajjs@amazon.com>
[Modify to use __patchable_function_entries support added upstream]
Signed-off-by: Puranjay Mohan <pjy@amazon.com>
…rch64

Add aarch64 support to kpatch_create_ftrace_callsite_sections(). Check
for the 2 required NOP instructions on function entry, which may be
preceded by a BTI C instruction depending on whether the
function is a leaf function. This determines the offset of the
patch site.

Signed-off-by: Pete Swain <swine@google.com>
Signed-off-by: Puranjay Mohan <pjy@amazon.com>
Add the final support required for aarch64 and enable building on that arch.

Signed-off-by: Suraj Jitindar Singh <surajjs@amazon.com>
[kpatch_line_macro_change_only() fixes]
Signed-off-by: Puranjay Mohan <pjy@amazon.com>
On arm64 when CONFIG_DEBUG_BUGVERBOSE is enabled debugging information about
bug sections is stored in the ".rodata.str" section of the object file. If this
isn't included then linking fails as labels in this section are referenced
by relocations in the bug table.

Include this section to enable building patches which contain this bug debug
information.

Signed-off-by: Suraj Jitindar Singh <surajjs@amazon.com>
It seems mapping symbols in aarch64 elf has section size of 0.
So, exclude it in section symbol replacing code just like
kpatch_correlate_symbols().
This fixes the data-read-mostly unit test on aarch64.

Signed-off-by: Misono Tomohiro <misono.tomohiro@jp.fujitsu.com>
Signed-off-by: Puranjay Mohan <pjy@amazon.com>
Copy from kernel source tree.

Signed-off-by: Misono Tomohiro <misono.tomohiro@jp.fujitsu.com>
@puranjaymohan puranjaymohan changed the title Add support Arm64 including all changes in PR #1302 (@swine, @surajjs95, @t-msn, and others) Add support for Arm64 including all changes in PR #1302 (@swine, @surajjs95, @t-msn, and others) Feb 7, 2025
dylanbhatch and others added 2 commits February 7, 2025 12:09
For arm64 this option uses -fpatchable-function-entry=M,2, so 2 NOPs
are placed before the function entry point (in order to store a pointer
to ftrace_ops). When calculating function padding, check for the
presence of the two NOPs, and adjust the padding size by 8 if they are
found.

This was merged in the upstream kernel in v6.8 with:

      baaf553d3bc3 ("arm64: Implement HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS")

With this into the equation, the entry of a function can look like one
of:

1. Without DYNAMIC_FTRACE_WITH_CALL_OPS and CONFIG_ARM64_BTI_KERNEL
-------------------------------------------------------------------

Disassembly of section .text.cmdline_proc_show:

0000000000000008 <cmdline_proc_show>:
   8:   d503201f        nop
   c:   d503201f        nop

2. Without DYNAMIC_FTRACE_WITH_CALL_OPS and with CONFIG_ARM64_BTI_KERNEL
------------------------------------------------------------------------

Disassembly of section .text.cmdline_proc_show:

0000000000000008 <cmdline_proc_show>:
   0:   d503245f        bti     c
   4:   d503201f        nop
   8:   d503201f        nop

3. With DYNAMIC_FTRACE_WITH_CALL_OPS and without CONFIG_ARM64_BTI_KERNEL
------------------------------------------------------------------------

Disassembly of section .text.cmdline_proc_show:

0000000000000000 <cmdline_proc_show-0x8>:
   0:   d503201f        nop
   4:   d503201f        nop

0000000000000008 <cmdline_proc_show>:
   8:   d503201f        nop
   c:   d503201f        nop

4. With DYNAMIC_FTRACE_WITH_CALL_OPS and with CONFIG_ARM64_BTI_KERNEL
---------------------------------------------------------------------

Disassembly of section .text.cmdline_proc_show:

0000000000000000 <cmdline_proc_show-0x8>:
   0:   d503201f        nop
   4:   d503201f        nop

0000000000000008 <cmdline_proc_show>:
   8:   d503245f        bti     c
   c:   d503201f        nop
  10:   d503201f        nop

make create-diff-object aware of DYNAMIC_FTRACE_WITH_CALL_OPS and its
quirks.

Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
Signed-off-by: Puranjay Mohan <pjy@amazon.com>
The sframe sections can't be normally diffed and need to be created
separately. skip them for now.

Signed-off-by: Puranjay Mohan <pjy@amazon.com>
kpatch_replace_sections_syms() substitutes the object/function symbols
for the section symbol in the relocation sections. But relocations in
.rela.__patchable_function_entries can point to an instruction ouside
the function. This is because with CALL_OPS enabled, two NOPs are added
before the function entry. __patchable_function_entries needs the
address of the first NOP above the function.

We anyway generate __patchable_function_entries again in
kpatch_create_ftrace_callsite_sections() so we can skip mangling these
relocations

Signed-off-by: Puranjay Mohan <pjy@amazon.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants