From: Suraj Jitindar Singh <surajjs@amazon.com>
To: <linux-arm-kernel@lists.infradead.org>
Cc: <linux-kernel@vger.kernel.org>, <live-patching@vger.kernel.org>,
<catalin.marinas@arm.com>, <will@kernel.org>,
<mark.rutland@arm.com>, <broonie@kernel.org>,
<madvenka@linux.microsoft.com>, <duwe@lst.de>,
<sjitindarsingh@gmail.com>, <benh@kernel.crashing.org>,
Suraj Jitindar Singh <surajjs@amazon.com>
Subject: [RFC PATCH 1/1] arm64: implement live patching
Date: Fri, 4 Jun 2021 16:59:30 -0700 [thread overview]
Message-ID: <20210604235930.603-1-surajjs@amazon.com> (raw)
It's my understanding that the two pieces of work required to enable live
patching on arm are in flight upstream;
- Reliable stack traces as implemented by Madhavan T. Venkataraman [1]
- Objtool as implemented by Julien Thierry [2]
This is the remaining part required to enable live patching on arm.
Based on work by Torsten Duwe [3]
Allocate a task flag used to represent the patch pending state for the
task. Also implement generic functions klp_arch_set_pc() &
klp_get_ftrace_location().
In klp_arch_set_pc() it is sufficient to set regs->pc as in
ftrace_common_return() the return address is loaded from the stack.
ldr x9, [sp, #S_PC]
<snip>
ret x9
In klp_get_ftrace_location() it is necessary to advance the address by
AARCH64_INSN_SIZE (4) to point to the BL in the callsite as 2 nops were
placed at the start of the function, one to be patched to save the LR and
another to be patched to branch to the ftrace call, and
klp_get_ftrace_location() is expected to return the address of the BL. It
may also be necessary to advance the address by another AARCH64_INSN_SIZE
if CONFIG_ARM64_BTI_KERNEL is enabled due to the instruction placed at the
branch target to satisfy BTI,
Signed-off-by: Suraj Jitindar Singh <surajjs@amazon.com>
[1] https://lkml.org/lkml/2021/5/26/1212
[2] https://lkml.org/lkml/2021/3/3/1135
[3] https://lkml.org/lkml/2018/10/26/536
---
arch/arm64/Kconfig | 3 ++
arch/arm64/include/asm/livepatch.h | 42 ++++++++++++++++++++++++++++
arch/arm64/include/asm/thread_info.h | 4 ++-
arch/arm64/kernel/signal.c | 4 +++
4 files changed, 52 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/include/asm/livepatch.h
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b098dabed8c2..c4636990c01d 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -187,6 +187,7 @@ config ARM64
select HAVE_GCC_PLUGINS
select HAVE_HW_BREAKPOINT if PERF_EVENTS
select HAVE_IRQ_TIME_ACCOUNTING
+ select HAVE_LIVEPATCH
select HAVE_NMI
select HAVE_PATA_PLATFORM
select HAVE_PERF_EVENTS
@@ -1946,3 +1947,5 @@ source "arch/arm64/kvm/Kconfig"
if CRYPTO
source "arch/arm64/crypto/Kconfig"
endif
+
+source "kernel/livepatch/Kconfig"
diff --git a/arch/arm64/include/asm/livepatch.h b/arch/arm64/include/asm/livepatch.h
new file mode 100644
index 000000000000..72d7cd86f158
--- /dev/null
+++ b/arch/arm64/include/asm/livepatch.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * livepatch.h - arm64-specific Kernel Live Patching Core
+ */
+#ifndef _ASM_ARM64_LIVEPATCH_H
+#define _ASM_ARM64_LIVEPATCH_H
+
+#include <linux/ftrace.h>
+
+static inline void klp_arch_set_pc(struct ftrace_regs *fregs, unsigned long ip)
+{
+ struct pt_regs *regs = ftrace_get_regs(fregs);
+
+ regs->pc = ip;
+}
+
+/*
+ * klp_get_ftrace_location is expected to return the address of the BL to the
+ * relevant ftrace handler in the callsite. The location of this can vary based
+ * on several compilation options.
+ * CONFIG_DYNAMIC_FTRACE_WITH_REGS
+ * - Inserts 2 nops on function entry the second of which is the BL
+ * referenced above. (See ftrace_init_nop() for the callsite sequence)
+ * (this is required by livepatch and must be selected)
+ * CONFIG_ARM64_BTI_KERNEL:
+ * - Inserts a hint #0x22 on function entry if the function is called
+ * indirectly (to satisfy BTI requirements), which is inserted before
+ * the two nops from above.
+ */
+#define klp_get_ftrace_location klp_get_ftrace_location
+static inline unsigned long klp_get_ftrace_location(unsigned long faddr)
+{
+ unsigned long addr = faddr + AARCH64_INSN_SIZE;
+
+#if IS_ENABLED(CONFIG_ARM64_BTI_KERNEL)
+ addr = ftrace_location_range(addr, addr + AARCH64_INSN_SIZE);
+#endif
+
+ return addr;
+}
+
+#endif /* _ASM_ARM64_LIVEPATCH_H */
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 6623c99f0984..cca936d53a40 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -67,6 +67,7 @@ int arch_dup_task_struct(struct task_struct *dst,
#define TIF_UPROBE 4 /* uprobe breakpoint or singlestep */
#define TIF_MTE_ASYNC_FAULT 5 /* MTE Asynchronous Tag Check Fault */
#define TIF_NOTIFY_SIGNAL 6 /* signal notifications exist */
+#define TIF_PATCH_PENDING 7 /* pending live patching update */
#define TIF_SYSCALL_TRACE 8 /* syscall trace active */
#define TIF_SYSCALL_AUDIT 9 /* syscall auditing */
#define TIF_SYSCALL_TRACEPOINT 10 /* syscall tracepoint for ftrace */
@@ -97,11 +98,12 @@ int arch_dup_task_struct(struct task_struct *dst,
#define _TIF_SVE (1 << TIF_SVE)
#define _TIF_MTE_ASYNC_FAULT (1 << TIF_MTE_ASYNC_FAULT)
#define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
+#define _TIF_PATCH_PENDING (1 << TIF_PATCH_PENDING)
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
_TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
_TIF_UPROBE | _TIF_MTE_ASYNC_FAULT | \
- _TIF_NOTIFY_SIGNAL)
+ _TIF_NOTIFY_SIGNAL | _TIF_PATCH_PENDING)
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
_TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 6237486ff6bb..d1eedb0589a7 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -18,6 +18,7 @@
#include <linux/sizes.h>
#include <linux/string.h>
#include <linux/tracehook.h>
+#include <linux/livepatch.h>
#include <linux/ratelimit.h>
#include <linux/syscalls.h>
@@ -932,6 +933,9 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
(void __user *)NULL, current);
}
+ if (thread_flags & _TIF_PATCH_PENDING)
+ klp_update_patch_state(current);
+
if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
do_signal(regs);
--
2.17.1
WARNING: multiple messages have this Message-ID (diff)
From: Suraj Jitindar Singh <surajjs@amazon.com>
To: <linux-arm-kernel@lists.infradead.org>
Cc: <linux-kernel@vger.kernel.org>, <live-patching@vger.kernel.org>,
<catalin.marinas@arm.com>, <will@kernel.org>,
<mark.rutland@arm.com>, <broonie@kernel.org>,
<madvenka@linux.microsoft.com>, <duwe@lst.de>,
<sjitindarsingh@gmail.com>, <benh@kernel.crashing.org>,
Suraj Jitindar Singh <surajjs@amazon.com>
Subject: [RFC PATCH 1/1] arm64: implement live patching
Date: Fri, 4 Jun 2021 16:59:30 -0700 [thread overview]
Message-ID: <20210604235930.603-1-surajjs@amazon.com> (raw)
It's my understanding that the two pieces of work required to enable live
patching on arm are in flight upstream;
- Reliable stack traces as implemented by Madhavan T. Venkataraman [1]
- Objtool as implemented by Julien Thierry [2]
This is the remaining part required to enable live patching on arm.
Based on work by Torsten Duwe [3]
Allocate a task flag used to represent the patch pending state for the
task. Also implement generic functions klp_arch_set_pc() &
klp_get_ftrace_location().
In klp_arch_set_pc() it is sufficient to set regs->pc as in
ftrace_common_return() the return address is loaded from the stack.
ldr x9, [sp, #S_PC]
<snip>
ret x9
In klp_get_ftrace_location() it is necessary to advance the address by
AARCH64_INSN_SIZE (4) to point to the BL in the callsite as 2 nops were
placed at the start of the function, one to be patched to save the LR and
another to be patched to branch to the ftrace call, and
klp_get_ftrace_location() is expected to return the address of the BL. It
may also be necessary to advance the address by another AARCH64_INSN_SIZE
if CONFIG_ARM64_BTI_KERNEL is enabled due to the instruction placed at the
branch target to satisfy BTI,
Signed-off-by: Suraj Jitindar Singh <surajjs@amazon.com>
[1] https://lkml.org/lkml/2021/5/26/1212
[2] https://lkml.org/lkml/2021/3/3/1135
[3] https://lkml.org/lkml/2018/10/26/536
---
arch/arm64/Kconfig | 3 ++
arch/arm64/include/asm/livepatch.h | 42 ++++++++++++++++++++++++++++
arch/arm64/include/asm/thread_info.h | 4 ++-
arch/arm64/kernel/signal.c | 4 +++
4 files changed, 52 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/include/asm/livepatch.h
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b098dabed8c2..c4636990c01d 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -187,6 +187,7 @@ config ARM64
select HAVE_GCC_PLUGINS
select HAVE_HW_BREAKPOINT if PERF_EVENTS
select HAVE_IRQ_TIME_ACCOUNTING
+ select HAVE_LIVEPATCH
select HAVE_NMI
select HAVE_PATA_PLATFORM
select HAVE_PERF_EVENTS
@@ -1946,3 +1947,5 @@ source "arch/arm64/kvm/Kconfig"
if CRYPTO
source "arch/arm64/crypto/Kconfig"
endif
+
+source "kernel/livepatch/Kconfig"
diff --git a/arch/arm64/include/asm/livepatch.h b/arch/arm64/include/asm/livepatch.h
new file mode 100644
index 000000000000..72d7cd86f158
--- /dev/null
+++ b/arch/arm64/include/asm/livepatch.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * livepatch.h - arm64-specific Kernel Live Patching Core
+ */
+#ifndef _ASM_ARM64_LIVEPATCH_H
+#define _ASM_ARM64_LIVEPATCH_H
+
+#include <linux/ftrace.h>
+
+static inline void klp_arch_set_pc(struct ftrace_regs *fregs, unsigned long ip)
+{
+ struct pt_regs *regs = ftrace_get_regs(fregs);
+
+ regs->pc = ip;
+}
+
+/*
+ * klp_get_ftrace_location is expected to return the address of the BL to the
+ * relevant ftrace handler in the callsite. The location of this can vary based
+ * on several compilation options.
+ * CONFIG_DYNAMIC_FTRACE_WITH_REGS
+ * - Inserts 2 nops on function entry the second of which is the BL
+ * referenced above. (See ftrace_init_nop() for the callsite sequence)
+ * (this is required by livepatch and must be selected)
+ * CONFIG_ARM64_BTI_KERNEL:
+ * - Inserts a hint #0x22 on function entry if the function is called
+ * indirectly (to satisfy BTI requirements), which is inserted before
+ * the two nops from above.
+ */
+#define klp_get_ftrace_location klp_get_ftrace_location
+static inline unsigned long klp_get_ftrace_location(unsigned long faddr)
+{
+ unsigned long addr = faddr + AARCH64_INSN_SIZE;
+
+#if IS_ENABLED(CONFIG_ARM64_BTI_KERNEL)
+ addr = ftrace_location_range(addr, addr + AARCH64_INSN_SIZE);
+#endif
+
+ return addr;
+}
+
+#endif /* _ASM_ARM64_LIVEPATCH_H */
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 6623c99f0984..cca936d53a40 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -67,6 +67,7 @@ int arch_dup_task_struct(struct task_struct *dst,
#define TIF_UPROBE 4 /* uprobe breakpoint or singlestep */
#define TIF_MTE_ASYNC_FAULT 5 /* MTE Asynchronous Tag Check Fault */
#define TIF_NOTIFY_SIGNAL 6 /* signal notifications exist */
+#define TIF_PATCH_PENDING 7 /* pending live patching update */
#define TIF_SYSCALL_TRACE 8 /* syscall trace active */
#define TIF_SYSCALL_AUDIT 9 /* syscall auditing */
#define TIF_SYSCALL_TRACEPOINT 10 /* syscall tracepoint for ftrace */
@@ -97,11 +98,12 @@ int arch_dup_task_struct(struct task_struct *dst,
#define _TIF_SVE (1 << TIF_SVE)
#define _TIF_MTE_ASYNC_FAULT (1 << TIF_MTE_ASYNC_FAULT)
#define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
+#define _TIF_PATCH_PENDING (1 << TIF_PATCH_PENDING)
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
_TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
_TIF_UPROBE | _TIF_MTE_ASYNC_FAULT | \
- _TIF_NOTIFY_SIGNAL)
+ _TIF_NOTIFY_SIGNAL | _TIF_PATCH_PENDING)
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
_TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 6237486ff6bb..d1eedb0589a7 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -18,6 +18,7 @@
#include <linux/sizes.h>
#include <linux/string.h>
#include <linux/tracehook.h>
+#include <linux/livepatch.h>
#include <linux/ratelimit.h>
#include <linux/syscalls.h>
@@ -932,6 +933,9 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
(void __user *)NULL, current);
}
+ if (thread_flags & _TIF_PATCH_PENDING)
+ klp_update_patch_state(current);
+
if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
do_signal(regs);
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next reply other threads:[~2021-06-05 0:00 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-04 23:59 Suraj Jitindar Singh [this message]
2021-06-04 23:59 ` [RFC PATCH 1/1] arm64: implement live patching Suraj Jitindar Singh
2021-06-07 10:20 ` Mark Rutland
2021-06-07 10:20 ` Mark Rutland
2021-06-07 13:08 ` Joe Lawrence
2021-06-07 13:08 ` Joe Lawrence
2021-06-09 0:32 ` Suraj Jitindar Singh
2021-06-09 0:32 ` Suraj Jitindar Singh
2021-06-09 23:57 ` Suraj Jitindar Singh
2021-06-09 23:57 ` Suraj Jitindar Singh
2021-06-07 17:01 ` Mark Brown
2021-06-07 17:01 ` Mark Brown
2021-06-09 0:12 ` Suraj Jitindar Singh
2021-06-09 0:12 ` Suraj Jitindar Singh
2021-06-17 9:29 ` nobuta.keiya
2021-06-17 9:29 ` nobuta.keiya
2021-06-17 18:32 ` Madhavan T. Venkataraman
2021-06-17 18:32 ` Madhavan T. Venkataraman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210604235930.603-1-surajjs@amazon.com \
--to=surajjs@amazon.com \
--cc=benh@kernel.crashing.org \
--cc=broonie@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=duwe@lst.de \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=live-patching@vger.kernel.org \
--cc=madvenka@linux.microsoft.com \
--cc=mark.rutland@arm.com \
--cc=sjitindarsingh@gmail.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.