diff mbox series

[v2,bpf-next,5/7] x86/alternative: introduce text_poke_jit

Message ID 20211215060102.3793196-6-song@kernel.org (mailing list archive)
State Changes Requested
Delegated to: BPF
Headers show
Series bpf_prog_pack allocator | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR pending PR summary
bpf/vmtest-bpf-next pending VM_Test
netdev/tree_selection success Clearly marked for bpf-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 7483 this patch: 7483
netdev/cc_maintainers warning 11 maintainers not CCed: bp@alien8.de kafai@fb.com jpoimboe@redhat.com songliubraving@fb.com john.fastabend@gmail.com hpa@zytor.com dave.hansen@linux.intel.com tglx@linutronix.de mingo@redhat.com kpsingh@kernel.org yhs@fb.com
netdev/build_clang success Errors and warnings before: 761 this patch: 761
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 6570 this patch: 6570
netdev/checkpatch warning CHECK: extern prototypes should be avoided in .h files WARNING: line length of 86 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Song Liu Dec. 15, 2021, 6:01 a.m. UTC
This will be used by BPF jit compiler to dump JITed binary to a RWX huge
page, and thus allow multiple BPF programs sharing the a huge (2MB) page.

Signed-off-by: Song Liu <song@kernel.org>
---
 arch/x86/include/asm/text-patching.h |  1 +
 arch/x86/kernel/alternative.c        | 28 ++++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

Comments

Peter Zijlstra Dec. 15, 2021, 9:06 a.m. UTC | #1
On Tue, Dec 14, 2021 at 10:01:00PM -0800, Song Liu wrote:
> This will be used by BPF jit compiler to dump JITed binary to a RWX huge

RWX *must* not happen, ever. If you still rely on that full NAK.
Peter Zijlstra Dec. 15, 2021, 9:17 a.m. UTC | #2
On Tue, Dec 14, 2021 at 10:01:00PM -0800, Song Liu wrote:
> This will be used by BPF jit compiler to dump JITed binary to a RWX huge

OK, I read the actually allocator you use and the relevant code for this
patch and the above is a typo, you meant: RX. Those pages are most
definitely not writable.


> +void *text_poke_jit(void *addr, const void *opcode, size_t len)
> +{
> +	unsigned long start = (unsigned long)addr;
> +	size_t patched = 0;
> +
> +	if (WARN_ON_ONCE(core_kernel_text(start)))
> +		return NULL;
> +
> +	while (patched < len) {
> +		unsigned long ptr = start + patched;
> +		size_t s;
> +
> +		s = min_t(size_t, PAGE_SIZE * 2 - offset_in_page(ptr), len - patched);

Cute, should work.

> +
> +		__text_poke((void *)ptr, opcode + patched, s);
> +		patched += s;
> +	}
> +	return addr;
> +}
Song Liu Dec. 16, 2021, 7:40 p.m. UTC | #3
> On Dec 15, 2021, at 1:17 AM, Peter Zijlstra <peterz@infradead.org> wrote:
> 
> On Tue, Dec 14, 2021 at 10:01:00PM -0800, Song Liu wrote:
>> This will be used by BPF jit compiler to dump JITed binary to a RWX huge
> 
> OK, I read the actually allocator you use and the relevant code for this
> patch and the above is a typo, you meant: RX. Those pages are most
> definitely not writable.

Yeah, it was a typo. I meant to say ROX. 

Thanks,
Song
> 
> 
>> +void *text_poke_jit(void *addr, const void *opcode, size_t len)
>> +{
>> +	unsigned long start = (unsigned long)addr;
>> +	size_t patched = 0;
>> +
>> +	if (WARN_ON_ONCE(core_kernel_text(start)))
>> +		return NULL;
>> +
>> +	while (patched < len) {
>> +		unsigned long ptr = start + patched;
>> +		size_t s;
>> +
>> +		s = min_t(size_t, PAGE_SIZE * 2 - offset_in_page(ptr), len - patched);
> 
> Cute, should work.
> 
>> +
>> +		__text_poke((void *)ptr, opcode + patched, s);
>> +		patched += s;
>> +	}
>> +	return addr;
>> +}
diff mbox series

Patch

diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h
index b7421780e4e9..991058c9b4b1 100644
--- a/arch/x86/include/asm/text-patching.h
+++ b/arch/x86/include/asm/text-patching.h
@@ -44,6 +44,7 @@  extern void text_poke_early(void *addr, const void *opcode, size_t len);
 extern void *text_poke(void *addr, const void *opcode, size_t len);
 extern void text_poke_sync(void);
 extern void *text_poke_kgdb(void *addr, const void *opcode, size_t len);
+extern void *text_poke_jit(void *addr, const void *opcode, size_t len);
 extern int poke_int3_handler(struct pt_regs *regs);
 extern void text_poke_bp(void *addr, const void *opcode, size_t len, const void *emulate);
 
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 23fb4d51a5da..02c35725cc62 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -1102,6 +1102,34 @@  void *text_poke_kgdb(void *addr, const void *opcode, size_t len)
 	return __text_poke(addr, opcode, len);
 }
 
+/**
+ * text_poke_jit - Update instructions on a live kernel by jit engine
+ * @addr: address to modify
+ * @opcode: source of the copy
+ * @len: length to copy, could be more than 2x PAGE_SIZE
+ *
+ * Only module memory taking jit text (e.g. for bpf) should be patched.
+ */
+void *text_poke_jit(void *addr, const void *opcode, size_t len)
+{
+	unsigned long start = (unsigned long)addr;
+	size_t patched = 0;
+
+	if (WARN_ON_ONCE(core_kernel_text(start)))
+		return NULL;
+
+	while (patched < len) {
+		unsigned long ptr = start + patched;
+		size_t s;
+
+		s = min_t(size_t, PAGE_SIZE * 2 - offset_in_page(ptr), len - patched);
+
+		__text_poke((void *)ptr, opcode + patched, s);
+		patched += s;
+	}
+	return addr;
+}
+
 static void do_sync_core(void *info)
 {
 	sync_core();