Skip to content

Commit b61e1f3

Browse files
hcahcaVasily Gorbik
authored andcommitted
s390/kprobes: move insn_page to text segment
Move the in-kernel kprobes insn page to text segment. Rationale: having that page in rw data segment is suboptimal, since as soon as a kprobe is set, this will split the 1:1 kernel mapping for a single page which get new permissions. Note: there is always at least one kprobe present for the kretprobe trampoline; so the mapping will always be split into smaller 4k mappings because of this. Moving the kprobes insn page into text segment makes sure that the page is mapped RO/X in any case, and avoids that the 1:1 mapping is split. The kprobe insn_page is defined as a dummy function which is filled with "br %r14" instructions. Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
1 parent eefc69a commit b61e1f3

4 files changed

Lines changed: 27 additions & 4 deletions

File tree

arch/s390/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ obj-$(CONFIG_COMPAT) += $(compat-obj-y)
5757
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
5858
obj-$(CONFIG_STACKTRACE) += stacktrace.o
5959
obj-$(CONFIG_KPROBES) += kprobes.o
60+
obj-$(CONFIG_KPROBES) += kprobes_insn_page.o
6061
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
6162
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
6263
obj-$(CONFIG_UPROBES) += uprobes.o

arch/s390/kernel/entry.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,6 @@ void set_fs_fixup(void);
8787
unsigned long stack_alloc(void);
8888
void stack_free(unsigned long stack);
8989

90+
extern char kprobes_insn_page[];
91+
9092
#endif /* _ENTRY_H */

arch/s390/kernel/kprobes.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <asm/set_memory.h>
2323
#include <asm/sections.h>
2424
#include <asm/dis.h>
25+
#include "entry.h"
2526

2627
DEFINE_PER_CPU(struct kprobe *, current_kprobe);
2728
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
@@ -31,7 +32,6 @@ struct kretprobe_blackpoint kretprobe_blacklist[] = { };
3132
DEFINE_INSN_CACHE_OPS(s390_insn);
3233

3334
static int insn_page_in_use;
34-
static char insn_page[PAGE_SIZE] __aligned(PAGE_SIZE);
3535

3636
void *alloc_insn_page(void)
3737
{
@@ -53,13 +53,11 @@ static void *alloc_s390_insn_page(void)
5353
{
5454
if (xchg(&insn_page_in_use, 1) == 1)
5555
return NULL;
56-
__set_memory((unsigned long) &insn_page, 1, SET_MEMORY_RO | SET_MEMORY_X);
57-
return &insn_page;
56+
return &kprobes_insn_page;
5857
}
5958

6059
static void free_s390_insn_page(void *page)
6160
{
62-
__set_memory((unsigned long) page, 1, SET_MEMORY_RW | SET_MEMORY_NX);
6361
xchg(&insn_page_in_use, 0);
6462
}
6563

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
3+
#include <linux/linkage.h>
4+
5+
/*
6+
* insn_page is a special 4k aligned dummy function for kprobes.
7+
* It will contain all kprobed instructions that are out-of-line executed.
8+
* The page must be within the kernel image to guarantee that the
9+
* out-of-line instructions are within 2GB distance of their original
10+
* location. Using a dummy function ensures that the insn_page is within
11+
* the text section of the kernel and mapped read-only/executable from
12+
* the beginning on, thus avoiding to split large mappings if the page
13+
* would be in the data section instead.
14+
*/
15+
.section .kprobes.text, "ax"
16+
.align 4096
17+
ENTRY(kprobes_insn_page)
18+
.rept 2048
19+
.word 0x07fe
20+
.endr
21+
ENDPROC(kprobes_insn_page)
22+
.previous

0 commit comments

Comments
 (0)