2019-05-19 20:08:55 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2012-05-22 10:50:07 +08:00
|
|
|
#define pr_fmt(fmt) "SMP alternatives: " fmt
|
|
|
|
|
2006-03-23 18:59:32 +08:00
|
|
|
#include <linux/module.h>
|
2006-10-18 13:47:25 +08:00
|
|
|
#include <linux/sched.h>
|
2020-05-12 20:19:09 +08:00
|
|
|
#include <linux/perf_event.h>
|
2008-05-13 03:21:01 +08:00
|
|
|
#include <linux/mutex.h>
|
2006-03-23 18:59:32 +08:00
|
|
|
#include <linux/list.h>
|
2009-08-19 15:40:48 +08:00
|
|
|
#include <linux/stringify.h>
|
2020-08-07 14:22:28 +08:00
|
|
|
#include <linux/highmem.h>
|
2007-07-22 17:12:31 +08:00
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <linux/vmalloc.h>
|
2009-03-06 23:37:22 +08:00
|
|
|
#include <linux/memory.h>
|
2010-02-25 21:34:38 +08:00
|
|
|
#include <linux/stop_machine.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 16:04:11 +08:00
|
|
|
#include <linux/slab.h>
|
2013-07-12 17:21:48 +08:00
|
|
|
#include <linux/kdebug.h>
|
2019-02-13 00:12:15 +08:00
|
|
|
#include <linux/kprobes.h>
|
2019-04-26 08:11:27 +08:00
|
|
|
#include <linux/mmu_context.h>
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
#include <linux/bsearch.h>
|
2020-07-27 12:31:30 +08:00
|
|
|
#include <linux/sync_core.h>
|
2016-04-27 03:23:24 +08:00
|
|
|
#include <asm/text-patching.h>
|
2006-03-23 18:59:32 +08:00
|
|
|
#include <asm/alternative.h>
|
|
|
|
#include <asm/sections.h>
|
2007-07-22 17:12:32 +08:00
|
|
|
#include <asm/mce.h>
|
|
|
|
#include <asm/nmi.h>
|
2008-03-06 21:48:49 +08:00
|
|
|
#include <asm/cacheflush.h>
|
2009-03-06 23:37:54 +08:00
|
|
|
#include <asm/tlbflush.h>
|
2020-01-24 02:41:13 +08:00
|
|
|
#include <asm/insn.h>
|
2008-03-06 21:48:49 +08:00
|
|
|
#include <asm/io.h>
|
2009-03-06 23:37:54 +08:00
|
|
|
#include <asm/fixmap.h>
|
2021-03-11 22:23:13 +08:00
|
|
|
#include <asm/paravirt.h>
|
2021-10-26 20:01:42 +08:00
|
|
|
#include <asm/asm-prototypes.h>
|
2006-03-23 18:59:32 +08:00
|
|
|
|
2015-04-30 15:09:26 +08:00
|
|
|
int __read_mostly alternatives_patched;
|
|
|
|
|
|
|
|
EXPORT_SYMBOL_GPL(alternatives_patched);
|
|
|
|
|
2007-08-11 04:31:03 +08:00
|
|
|
#define MAX_PATCH_LEN (255-1)
|
|
|
|
|
2023-02-09 01:10:51 +08:00
|
|
|
#define DA_ALL (~0)
|
|
|
|
#define DA_ALT 0x01
|
|
|
|
#define DA_RET 0x02
|
|
|
|
#define DA_RETPOLINE 0x04
|
|
|
|
#define DA_ENDBR 0x08
|
|
|
|
#define DA_SMP 0x10
|
|
|
|
|
|
|
|
static unsigned int __initdata_or_module debug_alternative;
|
2007-05-03 01:27:13 +08:00
|
|
|
|
2006-06-26 19:56:16 +08:00
|
|
|
static int __init debug_alt(char *str)
|
|
|
|
{
|
2023-02-09 01:10:51 +08:00
|
|
|
if (str && *str == '=')
|
|
|
|
str++;
|
|
|
|
|
|
|
|
if (!str || kstrtouint(str, 0, &debug_alternative))
|
|
|
|
debug_alternative = DA_ALL;
|
|
|
|
|
2006-06-26 19:56:16 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
__setup("debug-alternative", debug_alt);
|
|
|
|
|
2007-07-21 23:10:25 +08:00
|
|
|
static int noreplace_smp;
|
|
|
|
|
2007-05-03 01:27:13 +08:00
|
|
|
static int __init setup_noreplace_smp(char *str)
|
|
|
|
{
|
|
|
|
noreplace_smp = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
__setup("noreplace-smp", setup_noreplace_smp);
|
|
|
|
|
2023-02-09 01:10:51 +08:00
|
|
|
#define DPRINTK(type, fmt, args...) \
|
2014-12-31 03:27:09 +08:00
|
|
|
do { \
|
2023-02-09 01:10:51 +08:00
|
|
|
if (debug_alternative & DA_##type) \
|
2020-06-16 01:49:46 +08:00
|
|
|
printk(KERN_DEBUG pr_fmt(fmt) "\n", ##args); \
|
2012-05-22 10:50:07 +08:00
|
|
|
} while (0)
|
2006-06-26 19:56:16 +08:00
|
|
|
|
2023-02-09 01:10:51 +08:00
|
|
|
#define DUMP_BYTES(type, buf, len, fmt, args...) \
|
x86/alternatives: Make JMPs more robust
Up until now we had to pay attention to relative JMPs in alternatives
about how their relative offset gets computed so that the jump target
is still correct. Or, as it is the case for near CALLs (opcode e8), we
still have to go and readjust the offset at patching time.
What is more, the static_cpu_has_safe() facility had to forcefully
generate 5-byte JMPs since we couldn't rely on the compiler to generate
properly sized ones so we had to force the longest ones. Worse than
that, sometimes it would generate a replacement JMP which is longer than
the original one, thus overwriting the beginning of the next instruction
at patching time.
So, in order to alleviate all that and make using JMPs more
straight-forward we go and pad the original instruction in an
alternative block with NOPs at build time, should the replacement(s) be
longer. This way, alternatives users shouldn't pay special attention
so that original and replacement instruction sizes are fine but the
assembler would simply add padding where needed and not do anything
otherwise.
As a second aspect, we go and recompute JMPs at patching time so that we
can try to make 5-byte JMPs into two-byte ones if possible. If not, we
still have to recompute the offsets as the replacement JMP gets put far
away in the .altinstr_replacement section leading to a wrong offset if
copied verbatim.
For example, on a locally generated kernel image
old insn VA: 0xffffffff810014bd, CPU feat: X86_FEATURE_ALWAYS, size: 2
__switch_to:
ffffffff810014bd: eb 21 jmp ffffffff810014e0
repl insn: size: 5
ffffffff81d0b23c: e9 b1 62 2f ff jmpq ffffffff810014f2
gets corrected to a 2-byte JMP:
apply_alternatives: feat: 3*32+21, old: (ffffffff810014bd, len: 2), repl: (ffffffff81d0b23c, len: 5)
alt_insn: e9 b1 62 2f ff
recompute_jumps: next_rip: ffffffff81d0b241, tgt_rip: ffffffff810014f2, new_displ: 0x00000033, ret len: 2
converted to: eb 33 90 90 90
and a 5-byte JMP:
old insn VA: 0xffffffff81001516, CPU feat: X86_FEATURE_ALWAYS, size: 2
__switch_to:
ffffffff81001516: eb 30 jmp ffffffff81001548
repl insn: size: 5
ffffffff81d0b241: e9 10 63 2f ff jmpq ffffffff81001556
gets shortened into a two-byte one:
apply_alternatives: feat: 3*32+21, old: (ffffffff81001516, len: 2), repl: (ffffffff81d0b241, len: 5)
alt_insn: e9 10 63 2f ff
recompute_jumps: next_rip: ffffffff81d0b246, tgt_rip: ffffffff81001556, new_displ: 0x0000003e, ret len: 2
converted to: eb 3e 90 90 90
... and so on.
This leads to a net win of around
40ish replacements * 3 bytes savings =~ 120 bytes of I$
on an AMD guest which means some savings of precious instruction cache
bandwidth. The padding to the shorter 2-byte JMPs are single-byte NOPs
which on smart microarchitectures means discarding NOPs at decode time
and thus freeing up execution bandwidth.
Signed-off-by: Borislav Petkov <bp@suse.de>
2015-01-05 20:48:41 +08:00
|
|
|
do { \
|
2023-02-09 01:10:51 +08:00
|
|
|
if (unlikely(debug_alternative & DA_##type)) { \
|
x86/alternatives: Make JMPs more robust
Up until now we had to pay attention to relative JMPs in alternatives
about how their relative offset gets computed so that the jump target
is still correct. Or, as it is the case for near CALLs (opcode e8), we
still have to go and readjust the offset at patching time.
What is more, the static_cpu_has_safe() facility had to forcefully
generate 5-byte JMPs since we couldn't rely on the compiler to generate
properly sized ones so we had to force the longest ones. Worse than
that, sometimes it would generate a replacement JMP which is longer than
the original one, thus overwriting the beginning of the next instruction
at patching time.
So, in order to alleviate all that and make using JMPs more
straight-forward we go and pad the original instruction in an
alternative block with NOPs at build time, should the replacement(s) be
longer. This way, alternatives users shouldn't pay special attention
so that original and replacement instruction sizes are fine but the
assembler would simply add padding where needed and not do anything
otherwise.
As a second aspect, we go and recompute JMPs at patching time so that we
can try to make 5-byte JMPs into two-byte ones if possible. If not, we
still have to recompute the offsets as the replacement JMP gets put far
away in the .altinstr_replacement section leading to a wrong offset if
copied verbatim.
For example, on a locally generated kernel image
old insn VA: 0xffffffff810014bd, CPU feat: X86_FEATURE_ALWAYS, size: 2
__switch_to:
ffffffff810014bd: eb 21 jmp ffffffff810014e0
repl insn: size: 5
ffffffff81d0b23c: e9 b1 62 2f ff jmpq ffffffff810014f2
gets corrected to a 2-byte JMP:
apply_alternatives: feat: 3*32+21, old: (ffffffff810014bd, len: 2), repl: (ffffffff81d0b23c, len: 5)
alt_insn: e9 b1 62 2f ff
recompute_jumps: next_rip: ffffffff81d0b241, tgt_rip: ffffffff810014f2, new_displ: 0x00000033, ret len: 2
converted to: eb 33 90 90 90
and a 5-byte JMP:
old insn VA: 0xffffffff81001516, CPU feat: X86_FEATURE_ALWAYS, size: 2
__switch_to:
ffffffff81001516: eb 30 jmp ffffffff81001548
repl insn: size: 5
ffffffff81d0b241: e9 10 63 2f ff jmpq ffffffff81001556
gets shortened into a two-byte one:
apply_alternatives: feat: 3*32+21, old: (ffffffff81001516, len: 2), repl: (ffffffff81d0b241, len: 5)
alt_insn: e9 10 63 2f ff
recompute_jumps: next_rip: ffffffff81d0b246, tgt_rip: ffffffff81001556, new_displ: 0x0000003e, ret len: 2
converted to: eb 3e 90 90 90
... and so on.
This leads to a net win of around
40ish replacements * 3 bytes savings =~ 120 bytes of I$
on an AMD guest which means some savings of precious instruction cache
bandwidth. The padding to the shorter 2-byte JMPs are single-byte NOPs
which on smart microarchitectures means discarding NOPs at decode time
and thus freeing up execution bandwidth.
Signed-off-by: Borislav Petkov <bp@suse.de>
2015-01-05 20:48:41 +08:00
|
|
|
int j; \
|
|
|
|
\
|
|
|
|
if (!(len)) \
|
|
|
|
break; \
|
|
|
|
\
|
2020-06-16 01:49:46 +08:00
|
|
|
printk(KERN_DEBUG pr_fmt(fmt), ##args); \
|
x86/alternatives: Make JMPs more robust
Up until now we had to pay attention to relative JMPs in alternatives
about how their relative offset gets computed so that the jump target
is still correct. Or, as it is the case for near CALLs (opcode e8), we
still have to go and readjust the offset at patching time.
What is more, the static_cpu_has_safe() facility had to forcefully
generate 5-byte JMPs since we couldn't rely on the compiler to generate
properly sized ones so we had to force the longest ones. Worse than
that, sometimes it would generate a replacement JMP which is longer than
the original one, thus overwriting the beginning of the next instruction
at patching time.
So, in order to alleviate all that and make using JMPs more
straight-forward we go and pad the original instruction in an
alternative block with NOPs at build time, should the replacement(s) be
longer. This way, alternatives users shouldn't pay special attention
so that original and replacement instruction sizes are fine but the
assembler would simply add padding where needed and not do anything
otherwise.
As a second aspect, we go and recompute JMPs at patching time so that we
can try to make 5-byte JMPs into two-byte ones if possible. If not, we
still have to recompute the offsets as the replacement JMP gets put far
away in the .altinstr_replacement section leading to a wrong offset if
copied verbatim.
For example, on a locally generated kernel image
old insn VA: 0xffffffff810014bd, CPU feat: X86_FEATURE_ALWAYS, size: 2
__switch_to:
ffffffff810014bd: eb 21 jmp ffffffff810014e0
repl insn: size: 5
ffffffff81d0b23c: e9 b1 62 2f ff jmpq ffffffff810014f2
gets corrected to a 2-byte JMP:
apply_alternatives: feat: 3*32+21, old: (ffffffff810014bd, len: 2), repl: (ffffffff81d0b23c, len: 5)
alt_insn: e9 b1 62 2f ff
recompute_jumps: next_rip: ffffffff81d0b241, tgt_rip: ffffffff810014f2, new_displ: 0x00000033, ret len: 2
converted to: eb 33 90 90 90
and a 5-byte JMP:
old insn VA: 0xffffffff81001516, CPU feat: X86_FEATURE_ALWAYS, size: 2
__switch_to:
ffffffff81001516: eb 30 jmp ffffffff81001548
repl insn: size: 5
ffffffff81d0b241: e9 10 63 2f ff jmpq ffffffff81001556
gets shortened into a two-byte one:
apply_alternatives: feat: 3*32+21, old: (ffffffff81001516, len: 2), repl: (ffffffff81d0b241, len: 5)
alt_insn: e9 10 63 2f ff
recompute_jumps: next_rip: ffffffff81d0b246, tgt_rip: ffffffff81001556, new_displ: 0x0000003e, ret len: 2
converted to: eb 3e 90 90 90
... and so on.
This leads to a net win of around
40ish replacements * 3 bytes savings =~ 120 bytes of I$
on an AMD guest which means some savings of precious instruction cache
bandwidth. The padding to the shorter 2-byte JMPs are single-byte NOPs
which on smart microarchitectures means discarding NOPs at decode time
and thus freeing up execution bandwidth.
Signed-off-by: Borislav Petkov <bp@suse.de>
2015-01-05 20:48:41 +08:00
|
|
|
for (j = 0; j < (len) - 1; j++) \
|
|
|
|
printk(KERN_CONT "%02hhx ", buf[j]); \
|
|
|
|
printk(KERN_CONT "%02hhx\n", buf[j]); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2021-05-07 03:07:26 +08:00
|
|
|
static const unsigned char x86nops[] =
|
2011-04-19 06:19:51 +08:00
|
|
|
{
|
x86: Remove dynamic NOP selection
This ensures that a NOP is a NOP and not a random other instruction that
is also a NOP. It allows simplification of dynamic code patching that
wants to verify existing code before writing new instructions (ftrace,
jump_label, static_call, etc..).
Differentiating on NOPs is not a feature.
This pessimises 32bit (DONTCARE) and 32bit on 64bit CPUs (CARELESS).
32bit is not a performance target.
Everything x86_64 since AMD K10 (2007) and Intel IvyBridge (2012) is
fine with using NOPL (as opposed to prefix NOP). And per FEATURE_NOPL
being required for x86_64, all x86_64 CPUs can use NOPL. So stop
caring about NOPs, simplify things and get on with life.
[ The problem seems to be that some uarchs can only decode NOPL on a
single front-end port while others have severe decode penalties for
excessive prefixes. All modern uarchs can handle both, except Atom,
which has prefix penalties. ]
[ Also, much doubt you can actually measure any of this on normal
workloads. ]
After this, FEATURE_NOPL is unused except for required-features for
x86_64. FEATURE_K8 is only used for PTI.
[ bp: Kernel build measurements showed ~0.3s slowdown on Sandybridge
which is hardly a slowdown. Get rid of X86_FEATURE_K7, while at it. ]
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Acked-by: Alexei Starovoitov <alexei.starovoitov@gmail.com> # bpf
Acked-by: Linus Torvalds <torvalds@linuxfoundation.org>
Link: https://lkml.kernel.org/r/20210312115749.065275711@infradead.org
2021-03-12 19:32:54 +08:00
|
|
|
BYTES_NOP1,
|
|
|
|
BYTES_NOP2,
|
|
|
|
BYTES_NOP3,
|
|
|
|
BYTES_NOP4,
|
|
|
|
BYTES_NOP5,
|
|
|
|
BYTES_NOP6,
|
|
|
|
BYTES_NOP7,
|
|
|
|
BYTES_NOP8,
|
2023-05-15 17:28:05 +08:00
|
|
|
#ifdef CONFIG_64BIT
|
|
|
|
BYTES_NOP9,
|
|
|
|
BYTES_NOP10,
|
|
|
|
BYTES_NOP11,
|
|
|
|
#endif
|
2006-03-23 18:59:32 +08:00
|
|
|
};
|
2006-06-26 19:56:16 +08:00
|
|
|
|
x86: Remove dynamic NOP selection
This ensures that a NOP is a NOP and not a random other instruction that
is also a NOP. It allows simplification of dynamic code patching that
wants to verify existing code before writing new instructions (ftrace,
jump_label, static_call, etc..).
Differentiating on NOPs is not a feature.
This pessimises 32bit (DONTCARE) and 32bit on 64bit CPUs (CARELESS).
32bit is not a performance target.
Everything x86_64 since AMD K10 (2007) and Intel IvyBridge (2012) is
fine with using NOPL (as opposed to prefix NOP). And per FEATURE_NOPL
being required for x86_64, all x86_64 CPUs can use NOPL. So stop
caring about NOPs, simplify things and get on with life.
[ The problem seems to be that some uarchs can only decode NOPL on a
single front-end port while others have severe decode penalties for
excessive prefixes. All modern uarchs can handle both, except Atom,
which has prefix penalties. ]
[ Also, much doubt you can actually measure any of this on normal
workloads. ]
After this, FEATURE_NOPL is unused except for required-features for
x86_64. FEATURE_K8 is only used for PTI.
[ bp: Kernel build measurements showed ~0.3s slowdown on Sandybridge
which is hardly a slowdown. Get rid of X86_FEATURE_K7, while at it. ]
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Acked-by: Alexei Starovoitov <alexei.starovoitov@gmail.com> # bpf
Acked-by: Linus Torvalds <torvalds@linuxfoundation.org>
Link: https://lkml.kernel.org/r/20210312115749.065275711@infradead.org
2021-03-12 19:32:54 +08:00
|
|
|
const unsigned char * const x86_nops[ASM_NOP_MAX+1] =
|
2011-04-19 06:19:51 +08:00
|
|
|
{
|
2007-10-18 00:04:41 +08:00
|
|
|
NULL,
|
x86: Remove dynamic NOP selection
This ensures that a NOP is a NOP and not a random other instruction that
is also a NOP. It allows simplification of dynamic code patching that
wants to verify existing code before writing new instructions (ftrace,
jump_label, static_call, etc..).
Differentiating on NOPs is not a feature.
This pessimises 32bit (DONTCARE) and 32bit on 64bit CPUs (CARELESS).
32bit is not a performance target.
Everything x86_64 since AMD K10 (2007) and Intel IvyBridge (2012) is
fine with using NOPL (as opposed to prefix NOP). And per FEATURE_NOPL
being required for x86_64, all x86_64 CPUs can use NOPL. So stop
caring about NOPs, simplify things and get on with life.
[ The problem seems to be that some uarchs can only decode NOPL on a
single front-end port while others have severe decode penalties for
excessive prefixes. All modern uarchs can handle both, except Atom,
which has prefix penalties. ]
[ Also, much doubt you can actually measure any of this on normal
workloads. ]
After this, FEATURE_NOPL is unused except for required-features for
x86_64. FEATURE_K8 is only used for PTI.
[ bp: Kernel build measurements showed ~0.3s slowdown on Sandybridge
which is hardly a slowdown. Get rid of X86_FEATURE_K7, while at it. ]
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Acked-by: Alexei Starovoitov <alexei.starovoitov@gmail.com> # bpf
Acked-by: Linus Torvalds <torvalds@linuxfoundation.org>
Link: https://lkml.kernel.org/r/20210312115749.065275711@infradead.org
2021-03-12 19:32:54 +08:00
|
|
|
x86nops,
|
|
|
|
x86nops + 1,
|
|
|
|
x86nops + 1 + 2,
|
|
|
|
x86nops + 1 + 2 + 3,
|
|
|
|
x86nops + 1 + 2 + 3 + 4,
|
|
|
|
x86nops + 1 + 2 + 3 + 4 + 5,
|
|
|
|
x86nops + 1 + 2 + 3 + 4 + 5 + 6,
|
|
|
|
x86nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
|
2023-05-15 17:28:05 +08:00
|
|
|
#ifdef CONFIG_64BIT
|
|
|
|
x86nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
|
|
|
|
x86nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9,
|
|
|
|
x86nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10,
|
|
|
|
#endif
|
2007-10-18 00:04:41 +08:00
|
|
|
};
|
2006-03-23 18:59:32 +08:00
|
|
|
|
2023-02-09 01:10:53 +08:00
|
|
|
/*
|
2023-02-09 01:10:54 +08:00
|
|
|
* Fill the buffer with a single effective instruction of size @len.
|
|
|
|
*
|
2023-02-09 01:10:53 +08:00
|
|
|
* In order not to issue an ORC stack depth tracking CFI entry (Call Frame Info)
|
|
|
|
* for every single-byte NOP, try to generate the maximally available NOP of
|
|
|
|
* size <= ASM_NOP_MAX such that only a single CFI entry is generated (vs one for
|
|
|
|
* each single-byte NOPs). If @len to fill out is > ASM_NOP_MAX, pad with INT3 and
|
|
|
|
* *jump* over instead of executing long and daft NOPs.
|
|
|
|
*/
|
|
|
|
static void __init_or_module add_nop(u8 *instr, unsigned int len)
|
2006-12-07 09:14:08 +08:00
|
|
|
{
|
2023-02-09 01:10:53 +08:00
|
|
|
u8 *target = instr + len;
|
|
|
|
|
|
|
|
if (!len)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (len <= ASM_NOP_MAX) {
|
|
|
|
memcpy(instr, x86_nops[len], len);
|
|
|
|
return;
|
2006-12-07 09:14:08 +08:00
|
|
|
}
|
2023-02-09 01:10:53 +08:00
|
|
|
|
|
|
|
if (len < 128) {
|
|
|
|
__text_gen_insn(instr, JMP8_INSN_OPCODE, instr, target, JMP8_INSN_SIZE);
|
|
|
|
instr += JMP8_INSN_SIZE;
|
|
|
|
} else {
|
|
|
|
__text_gen_insn(instr, JMP32_INSN_OPCODE, instr, target, JMP32_INSN_SIZE);
|
|
|
|
instr += JMP32_INSN_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;instr < target; instr++)
|
|
|
|
*instr = INT3_INSN_OPCODE;
|
2006-12-07 09:14:08 +08:00
|
|
|
}
|
|
|
|
|
2021-10-26 20:01:42 +08:00
|
|
|
extern s32 __retpoline_sites[], __retpoline_sites_end[];
|
2022-06-15 05:15:37 +08:00
|
|
|
extern s32 __return_sites[], __return_sites_end[];
|
2022-10-27 17:28:14 +08:00
|
|
|
extern s32 __cfi_sites[], __cfi_sites_end[];
|
2022-03-08 23:30:56 +08:00
|
|
|
extern s32 __ibt_endbr_seal[], __ibt_endbr_seal_end[];
|
2006-06-26 19:56:16 +08:00
|
|
|
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
|
2010-04-21 23:08:14 +08:00
|
|
|
extern s32 __smp_locks[], __smp_locks_end[];
|
2019-04-26 08:11:33 +08:00
|
|
|
void text_poke_early(void *addr, const void *opcode, size_t len);
|
2006-06-26 19:56:16 +08:00
|
|
|
|
2023-02-09 01:10:54 +08:00
|
|
|
/*
|
|
|
|
* Matches NOP and NOPL, not any of the other possible NOPs.
|
|
|
|
*/
|
2023-02-09 01:10:53 +08:00
|
|
|
static bool insn_is_nop(struct insn *insn)
|
2021-06-01 23:51:22 +08:00
|
|
|
{
|
2023-06-14 22:35:50 +08:00
|
|
|
/* Anything NOP, but no REP NOP */
|
|
|
|
if (insn->opcode.bytes[0] == 0x90 &&
|
|
|
|
(!insn->prefixes.nbytes || insn->prefixes.bytes[0] != 0xF3))
|
2023-02-09 01:10:53 +08:00
|
|
|
return true;
|
2021-06-01 23:51:22 +08:00
|
|
|
|
2023-06-14 22:35:50 +08:00
|
|
|
/* NOPL */
|
2023-02-09 01:10:53 +08:00
|
|
|
if (insn->opcode.bytes[0] == 0x0F && insn->opcode.bytes[1] == 0x1F)
|
|
|
|
return true;
|
2021-06-01 23:51:22 +08:00
|
|
|
|
2023-02-09 01:10:53 +08:00
|
|
|
/* TODO: more nops */
|
2021-06-01 23:51:22 +08:00
|
|
|
|
2023-02-09 01:10:53 +08:00
|
|
|
return false;
|
|
|
|
}
|
2021-06-01 23:51:22 +08:00
|
|
|
|
2023-02-09 01:10:54 +08:00
|
|
|
/*
|
|
|
|
* Find the offset of the first non-NOP instruction starting at @offset
|
|
|
|
* but no further than @len.
|
|
|
|
*/
|
2023-02-09 01:10:53 +08:00
|
|
|
static int skip_nops(u8 *instr, int offset, int len)
|
|
|
|
{
|
|
|
|
struct insn insn;
|
2021-06-01 23:51:22 +08:00
|
|
|
|
2023-02-09 01:10:53 +08:00
|
|
|
for (; offset < len; offset += insn.length) {
|
|
|
|
if (insn_decode_kernel(&insn, &instr[offset]))
|
|
|
|
break;
|
2021-06-01 23:51:22 +08:00
|
|
|
|
2023-02-09 01:10:53 +08:00
|
|
|
if (!insn_is_nop(&insn))
|
|
|
|
break;
|
|
|
|
}
|
2021-06-01 23:51:22 +08:00
|
|
|
|
2023-02-09 01:10:53 +08:00
|
|
|
return offset;
|
2021-06-01 23:51:22 +08:00
|
|
|
}
|
|
|
|
|
2023-02-09 01:10:54 +08:00
|
|
|
/*
|
|
|
|
* Optimize a sequence of NOPs, possibly preceded by an unconditional jump
|
|
|
|
* to the end of the NOP sequence into a single NOP.
|
|
|
|
*/
|
2023-05-13 22:01:39 +08:00
|
|
|
static bool __init_or_module
|
|
|
|
__optimize_nops(u8 *instr, size_t len, struct insn *insn, int *next, int *prev, int *target)
|
2023-02-09 01:10:54 +08:00
|
|
|
{
|
|
|
|
int i = *next - insn->length;
|
|
|
|
|
|
|
|
switch (insn->opcode.bytes[0]) {
|
|
|
|
case JMP8_INSN_OPCODE:
|
|
|
|
case JMP32_INSN_OPCODE:
|
|
|
|
*prev = i;
|
|
|
|
*target = *next + insn->immediate.value;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (insn_is_nop(insn)) {
|
|
|
|
int nop = i;
|
|
|
|
|
|
|
|
*next = skip_nops(instr, *next, len);
|
|
|
|
if (*target && *next == *target)
|
|
|
|
nop = *prev;
|
|
|
|
|
|
|
|
add_nop(instr + nop, *next - nop);
|
|
|
|
DUMP_BYTES(ALT, instr, len, "%px: [%d:%d) optimized NOPs: ", instr, nop, *next);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
*target = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-12-03 23:02:58 +08:00
|
|
|
/*
|
|
|
|
* "noinline" to cause control flow change and thus invalidate I$ and
|
|
|
|
* cause refetch after modification.
|
|
|
|
*/
|
2021-10-26 20:01:42 +08:00
|
|
|
static void __init_or_module noinline optimize_nops(u8 *instr, size_t len)
|
2015-01-11 03:34:07 +08:00
|
|
|
{
|
2023-02-09 01:10:54 +08:00
|
|
|
int prev, target = 0;
|
|
|
|
|
2023-02-09 01:10:53 +08:00
|
|
|
for (int next, i = 0; i < len; i = next) {
|
|
|
|
struct insn insn;
|
x86/alternatives: Make optimize_nops() interrupt safe and synced
Richard reported the following crash:
[ 0.036000] BUG: unable to handle kernel paging request at 55501e06
[ 0.036000] IP: [<c0aae48b>] common_interrupt+0xb/0x38
[ 0.036000] Call Trace:
[ 0.036000] [<c0409c80>] ? add_nops+0x90/0xa0
[ 0.036000] [<c040a054>] apply_alternatives+0x274/0x630
Chuck decoded:
" 0: 8d 90 90 83 04 24 lea 0x24048390(%eax),%edx
6: 80 fc 0f cmp $0xf,%ah
9: a8 0f test $0xf,%al
>> b: a0 06 1e 50 55 mov 0x55501e06,%al
10: 57 push %edi
11: 56 push %esi
Interrupt 0x30 occurred while the alternatives code was replacing the
initial 0x90,0x90,0x90 NOPs (from the ASM_CLAC macro) with the
optimized version, 0x8d,0x76,0x00. Only the first byte has been
replaced so far, and it makes a mess out of the insn decoding."
optimize_nops() is buggy in two aspects:
- It's not disabling interrupts across the modification
- It's lacking a sync_core() call
Add both.
Fixes: 4fd4b6e5537c 'x86/alternatives: Use optimized NOPs for padding'
Reported-and-tested-by: "Richard W.M. Jones" <rjones@redhat.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Richard W.M. Jones <rjones@redhat.com>
Cc: Chuck Ebbert <cebbert.lkml@gmail.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/alpine.DEB.2.11.1509031232340.15006@nanos
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2015-09-03 18:34:55 +08:00
|
|
|
|
2021-03-26 23:12:01 +08:00
|
|
|
if (insn_decode_kernel(&insn, &instr[i]))
|
|
|
|
return;
|
|
|
|
|
2023-02-09 01:10:53 +08:00
|
|
|
next = i + insn.length;
|
2021-03-26 23:12:01 +08:00
|
|
|
|
2023-02-09 01:10:54 +08:00
|
|
|
__optimize_nops(instr, len, &insn, &next, &prev, &target);
|
2018-01-10 19:28:16 +08:00
|
|
|
}
|
2015-01-11 03:34:07 +08:00
|
|
|
}
|
|
|
|
|
2023-02-09 01:10:52 +08:00
|
|
|
/*
|
|
|
|
* In this context, "source" is where the instructions are placed in the
|
|
|
|
* section .altinstr_replacement, for example during kernel build by the
|
|
|
|
* toolchain.
|
|
|
|
* "Destination" is where the instructions are being patched in by this
|
|
|
|
* machinery.
|
|
|
|
*
|
|
|
|
* The source offset is:
|
|
|
|
*
|
|
|
|
* src_imm = target - src_next_ip (1)
|
|
|
|
*
|
|
|
|
* and the target offset is:
|
|
|
|
*
|
|
|
|
* dst_imm = target - dst_next_ip (2)
|
|
|
|
*
|
|
|
|
* so rework (1) as an expression for target like:
|
|
|
|
*
|
|
|
|
* target = src_imm + src_next_ip (1a)
|
|
|
|
*
|
|
|
|
* and substitute in (2) to get:
|
|
|
|
*
|
|
|
|
* dst_imm = (src_imm + src_next_ip) - dst_next_ip (3)
|
|
|
|
*
|
|
|
|
* Now, since the instruction stream is 'identical' at src and dst (it
|
|
|
|
* is being copied after all) it can be stated that:
|
|
|
|
*
|
|
|
|
* src_next_ip = src + ip_offset
|
|
|
|
* dst_next_ip = dst + ip_offset (4)
|
|
|
|
*
|
|
|
|
* Substitute (4) in (3) and observe ip_offset being cancelled out to
|
|
|
|
* obtain:
|
|
|
|
*
|
|
|
|
* dst_imm = src_imm + (src + ip_offset) - (dst + ip_offset)
|
|
|
|
* = src_imm + src - dst + ip_offset - ip_offset
|
|
|
|
* = src_imm + src - dst (5)
|
|
|
|
*
|
|
|
|
* IOW, only the relative displacement of the code block matters.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define apply_reloc_n(n_, p_, d_) \
|
|
|
|
do { \
|
|
|
|
s32 v = *(s##n_ *)(p_); \
|
|
|
|
v += (d_); \
|
|
|
|
BUG_ON((v >> 31) != (v >> (n_-1))); \
|
|
|
|
*(s##n_ *)(p_) = (s##n_)v; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
|
|
static __always_inline
|
|
|
|
void apply_reloc(int n, void *ptr, uintptr_t diff)
|
|
|
|
{
|
|
|
|
switch (n) {
|
|
|
|
case 1: apply_reloc_n(8, ptr, diff); break;
|
|
|
|
case 2: apply_reloc_n(16, ptr, diff); break;
|
|
|
|
case 4: apply_reloc_n(32, ptr, diff); break;
|
|
|
|
default: BUG();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static __always_inline
|
|
|
|
bool need_reloc(unsigned long offset, u8 *src, size_t src_len)
|
|
|
|
{
|
|
|
|
u8 *target = src + offset;
|
|
|
|
/*
|
|
|
|
* If the target is inside the patched block, it's relative to the
|
|
|
|
* block itself and does not need relocation.
|
|
|
|
*/
|
|
|
|
return (target < src || target > src + src_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __init_or_module noinline
|
|
|
|
apply_relocation(u8 *buf, size_t len, u8 *dest, u8 *src, size_t src_len)
|
|
|
|
{
|
2023-02-09 01:10:54 +08:00
|
|
|
int prev, target = 0;
|
|
|
|
|
2023-02-09 01:10:52 +08:00
|
|
|
for (int next, i = 0; i < len; i = next) {
|
|
|
|
struct insn insn;
|
|
|
|
|
|
|
|
if (WARN_ON_ONCE(insn_decode_kernel(&insn, &buf[i])))
|
|
|
|
return;
|
|
|
|
|
|
|
|
next = i + insn.length;
|
|
|
|
|
2023-02-09 01:10:54 +08:00
|
|
|
if (__optimize_nops(buf, len, &insn, &next, &prev, &target))
|
|
|
|
continue;
|
|
|
|
|
2023-02-09 01:10:52 +08:00
|
|
|
switch (insn.opcode.bytes[0]) {
|
|
|
|
case 0x0f:
|
|
|
|
if (insn.opcode.bytes[1] < 0x80 ||
|
|
|
|
insn.opcode.bytes[1] > 0x8f)
|
|
|
|
break;
|
|
|
|
|
|
|
|
fallthrough; /* Jcc.d32 */
|
|
|
|
case 0x70 ... 0x7f: /* Jcc.d8 */
|
|
|
|
case JMP8_INSN_OPCODE:
|
|
|
|
case JMP32_INSN_OPCODE:
|
|
|
|
case CALL_INSN_OPCODE:
|
|
|
|
if (need_reloc(next + insn.immediate.value, src, src_len)) {
|
|
|
|
apply_reloc(insn.immediate.nbytes,
|
|
|
|
buf + i + insn_offset_immediate(&insn),
|
|
|
|
src - dest);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Where possible, convert JMP.d32 into JMP.d8.
|
|
|
|
*/
|
|
|
|
if (insn.opcode.bytes[0] == JMP32_INSN_OPCODE) {
|
|
|
|
s32 imm = insn.immediate.value;
|
|
|
|
imm += src - dest;
|
|
|
|
imm += JMP32_INSN_SIZE - JMP8_INSN_SIZE;
|
|
|
|
if ((imm >> 31) == (imm >> 7)) {
|
|
|
|
buf[i+0] = JMP8_INSN_OPCODE;
|
|
|
|
buf[i+1] = (s8)imm;
|
|
|
|
|
|
|
|
memset(&buf[i+2], INT3_INSN_OPCODE, insn.length - 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (insn_rip_relative(&insn)) {
|
|
|
|
if (need_reloc(next + insn.displacement.value, src, src_len)) {
|
|
|
|
apply_reloc(insn.displacement.nbytes,
|
|
|
|
buf + i + insn_offset_displacement(&insn),
|
|
|
|
src - dest);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-31 03:27:09 +08:00
|
|
|
/*
|
|
|
|
* Replace instructions with better alternatives for this CPU type. This runs
|
|
|
|
* before SMP is initialized to avoid SMP problems with self modifying code.
|
|
|
|
* This implies that asymmetric systems where APs have less capabilities than
|
|
|
|
* the boot processor are not handled. Tough. Make sure you disable such
|
|
|
|
* features by hand.
|
2016-12-03 23:02:58 +08:00
|
|
|
*
|
|
|
|
* Marked "noinline" to cause control flow change and thus insn cache
|
|
|
|
* to refetch changed I$ lines.
|
2014-12-31 03:27:09 +08:00
|
|
|
*/
|
2016-12-03 23:02:58 +08:00
|
|
|
void __init_or_module noinline apply_alternatives(struct alt_instr *start,
|
|
|
|
struct alt_instr *end)
|
2006-03-23 18:59:32 +08:00
|
|
|
{
|
|
|
|
struct alt_instr *a;
|
2011-07-13 21:24:10 +08:00
|
|
|
u8 *instr, *replacement;
|
2019-04-25 19:03:31 +08:00
|
|
|
u8 insn_buff[MAX_PATCH_LEN];
|
2006-03-23 18:59:32 +08:00
|
|
|
|
2023-02-09 01:10:51 +08:00
|
|
|
DPRINTK(ALT, "alt table %px, -> %px", start, end);
|
2011-05-18 06:29:12 +08:00
|
|
|
/*
|
|
|
|
* The scan order should be from start to end. A later scanned
|
2014-12-31 03:27:09 +08:00
|
|
|
* alternative code can overwrite previously scanned alternative code.
|
2011-05-18 06:29:12 +08:00
|
|
|
* Some kernel functions (e.g. memcpy, memset, etc) use this order to
|
|
|
|
* patch code.
|
|
|
|
*
|
|
|
|
* So be careful if you want to change the scan order to any other
|
|
|
|
* order.
|
|
|
|
*/
|
2006-03-23 18:59:32 +08:00
|
|
|
for (a = start; a < end; a++) {
|
2019-04-25 19:03:31 +08:00
|
|
|
int insn_buff_sz = 0;
|
x86/alternatives: Make JMPs more robust
Up until now we had to pay attention to relative JMPs in alternatives
about how their relative offset gets computed so that the jump target
is still correct. Or, as it is the case for near CALLs (opcode e8), we
still have to go and readjust the offset at patching time.
What is more, the static_cpu_has_safe() facility had to forcefully
generate 5-byte JMPs since we couldn't rely on the compiler to generate
properly sized ones so we had to force the longest ones. Worse than
that, sometimes it would generate a replacement JMP which is longer than
the original one, thus overwriting the beginning of the next instruction
at patching time.
So, in order to alleviate all that and make using JMPs more
straight-forward we go and pad the original instruction in an
alternative block with NOPs at build time, should the replacement(s) be
longer. This way, alternatives users shouldn't pay special attention
so that original and replacement instruction sizes are fine but the
assembler would simply add padding where needed and not do anything
otherwise.
As a second aspect, we go and recompute JMPs at patching time so that we
can try to make 5-byte JMPs into two-byte ones if possible. If not, we
still have to recompute the offsets as the replacement JMP gets put far
away in the .altinstr_replacement section leading to a wrong offset if
copied verbatim.
For example, on a locally generated kernel image
old insn VA: 0xffffffff810014bd, CPU feat: X86_FEATURE_ALWAYS, size: 2
__switch_to:
ffffffff810014bd: eb 21 jmp ffffffff810014e0
repl insn: size: 5
ffffffff81d0b23c: e9 b1 62 2f ff jmpq ffffffff810014f2
gets corrected to a 2-byte JMP:
apply_alternatives: feat: 3*32+21, old: (ffffffff810014bd, len: 2), repl: (ffffffff81d0b23c, len: 5)
alt_insn: e9 b1 62 2f ff
recompute_jumps: next_rip: ffffffff81d0b241, tgt_rip: ffffffff810014f2, new_displ: 0x00000033, ret len: 2
converted to: eb 33 90 90 90
and a 5-byte JMP:
old insn VA: 0xffffffff81001516, CPU feat: X86_FEATURE_ALWAYS, size: 2
__switch_to:
ffffffff81001516: eb 30 jmp ffffffff81001548
repl insn: size: 5
ffffffff81d0b241: e9 10 63 2f ff jmpq ffffffff81001556
gets shortened into a two-byte one:
apply_alternatives: feat: 3*32+21, old: (ffffffff81001516, len: 2), repl: (ffffffff81d0b241, len: 5)
alt_insn: e9 10 63 2f ff
recompute_jumps: next_rip: ffffffff81d0b246, tgt_rip: ffffffff81001556, new_displ: 0x0000003e, ret len: 2
converted to: eb 3e 90 90 90
... and so on.
This leads to a net win of around
40ish replacements * 3 bytes savings =~ 120 bytes of I$
on an AMD guest which means some savings of precious instruction cache
bandwidth. The padding to the shorter 2-byte JMPs are single-byte NOPs
which on smart microarchitectures means discarding NOPs at decode time
and thus freeing up execution bandwidth.
Signed-off-by: Borislav Petkov <bp@suse.de>
2015-01-05 20:48:41 +08:00
|
|
|
|
2011-07-13 21:24:10 +08:00
|
|
|
instr = (u8 *)&a->instr_offset + a->instr_offset;
|
|
|
|
replacement = (u8 *)&a->repl_offset + a->repl_offset;
|
2019-04-25 19:03:31 +08:00
|
|
|
BUG_ON(a->instrlen > sizeof(insn_buff));
|
2022-12-22 19:42:24 +08:00
|
|
|
BUG_ON(a->cpuid >= (NCAPINTS + NBUGINTS) * 32);
|
2021-03-11 22:23:10 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Patch if either:
|
|
|
|
* - feature is present
|
2022-12-22 19:42:24 +08:00
|
|
|
* - feature not present but ALT_FLAG_NOT is set to mean,
|
2021-03-11 22:23:10 +08:00
|
|
|
* patch if feature is *NOT* present.
|
|
|
|
*/
|
2023-02-09 01:10:52 +08:00
|
|
|
if (!boot_cpu_has(a->cpuid) == !(a->flags & ALT_FLAG_NOT)) {
|
|
|
|
optimize_nops(instr, a->instrlen);
|
|
|
|
continue;
|
|
|
|
}
|
2011-07-13 21:24:10 +08:00
|
|
|
|
2023-02-09 01:10:51 +08:00
|
|
|
DPRINTK(ALT, "feat: %s%d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d)",
|
2022-12-22 19:42:24 +08:00
|
|
|
(a->flags & ALT_FLAG_NOT) ? "!" : "",
|
|
|
|
a->cpuid >> 5,
|
|
|
|
a->cpuid & 0x1f,
|
2018-12-10 19:30:30 +08:00
|
|
|
instr, instr, a->instrlen,
|
2021-03-26 23:12:01 +08:00
|
|
|
replacement, a->replacementlen);
|
2014-12-31 03:27:09 +08:00
|
|
|
|
2019-04-25 19:03:31 +08:00
|
|
|
memcpy(insn_buff, replacement, a->replacementlen);
|
|
|
|
insn_buff_sz = a->replacementlen;
|
2011-07-13 21:24:10 +08:00
|
|
|
|
2021-03-26 23:12:01 +08:00
|
|
|
for (; insn_buff_sz < a->instrlen; insn_buff_sz++)
|
|
|
|
insn_buff[insn_buff_sz] = 0x90;
|
|
|
|
|
2023-02-09 01:10:52 +08:00
|
|
|
apply_relocation(insn_buff, a->instrlen, instr, replacement, a->replacementlen);
|
|
|
|
|
|
|
|
DUMP_BYTES(ALT, instr, a->instrlen, "%px: old_insn: ", instr);
|
|
|
|
DUMP_BYTES(ALT, replacement, a->replacementlen, "%px: rpl_insn: ", replacement);
|
2023-02-09 01:10:51 +08:00
|
|
|
DUMP_BYTES(ALT, insn_buff, insn_buff_sz, "%px: final_insn: ", instr);
|
2011-07-13 21:24:10 +08:00
|
|
|
|
2019-04-25 19:03:31 +08:00
|
|
|
text_poke_early(instr, insn_buff, insn_buff_sz);
|
2006-03-23 18:59:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-24 04:59:17 +08:00
|
|
|
static inline bool is_jcc32(struct insn *insn)
|
|
|
|
{
|
|
|
|
/* Jcc.d32 second opcode byte is in the range: 0x80-0x8f */
|
|
|
|
return insn->opcode.bytes[0] == 0x0f && (insn->opcode.bytes[1] & 0xf0) == 0x80;
|
|
|
|
}
|
|
|
|
|
2022-04-19 00:50:36 +08:00
|
|
|
#if defined(CONFIG_RETPOLINE) && defined(CONFIG_OBJTOOL)
|
2021-10-26 20:01:42 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* CALL/JMP *%\reg
|
|
|
|
*/
|
|
|
|
static int emit_indirect(int op, int reg, u8 *bytes)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
u8 modrm;
|
|
|
|
|
|
|
|
switch (op) {
|
|
|
|
case CALL_INSN_OPCODE:
|
|
|
|
modrm = 0x10; /* Reg = 2; CALL r/m */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JMP32_INSN_OPCODE:
|
|
|
|
modrm = 0x20; /* Reg = 4; JMP r/m */
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reg >= 8) {
|
|
|
|
bytes[i++] = 0x41; /* REX.B prefix */
|
|
|
|
reg -= 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
modrm |= 0xc0; /* Mod = 3 */
|
|
|
|
modrm += reg;
|
|
|
|
|
|
|
|
bytes[i++] = 0xff; /* opcode */
|
|
|
|
bytes[i++] = modrm;
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2022-09-15 19:11:28 +08:00
|
|
|
static int emit_call_track_retpoline(void *addr, struct insn *insn, int reg, u8 *bytes)
|
|
|
|
{
|
|
|
|
u8 op = insn->opcode.bytes[0];
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clang does 'weird' Jcc __x86_indirect_thunk_r11 conditional
|
|
|
|
* tail-calls. Deal with them.
|
|
|
|
*/
|
|
|
|
if (is_jcc32(insn)) {
|
|
|
|
bytes[i++] = op;
|
|
|
|
op = insn->opcode.bytes[1];
|
|
|
|
goto clang_jcc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (insn->length == 6)
|
|
|
|
bytes[i++] = 0x2e; /* CS-prefix */
|
|
|
|
|
|
|
|
switch (op) {
|
|
|
|
case CALL_INSN_OPCODE:
|
|
|
|
__text_gen_insn(bytes+i, op, addr+i,
|
|
|
|
__x86_indirect_call_thunk_array[reg],
|
|
|
|
CALL_INSN_SIZE);
|
|
|
|
i += CALL_INSN_SIZE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JMP32_INSN_OPCODE:
|
|
|
|
clang_jcc:
|
|
|
|
__text_gen_insn(bytes+i, op, addr+i,
|
|
|
|
__x86_indirect_jump_thunk_array[reg],
|
|
|
|
JMP32_INSN_SIZE);
|
|
|
|
i += JMP32_INSN_SIZE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2022-10-25 23:32:49 +08:00
|
|
|
WARN(1, "%pS %px %*ph\n", addr, addr, 6, addr);
|
2022-09-15 19:11:28 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
WARN_ON_ONCE(i != insn->length);
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2021-10-26 20:01:42 +08:00
|
|
|
/*
|
|
|
|
* Rewrite the compiler generated retpoline thunk calls.
|
|
|
|
*
|
|
|
|
* For spectre_v2=off (!X86_FEATURE_RETPOLINE), rewrite them into immediate
|
|
|
|
* indirect instructions, avoiding the extra indirection.
|
|
|
|
*
|
|
|
|
* For example, convert:
|
|
|
|
*
|
|
|
|
* CALL __x86_indirect_thunk_\reg
|
|
|
|
*
|
|
|
|
* into:
|
|
|
|
*
|
|
|
|
* CALL *%\reg
|
|
|
|
*
|
2022-02-17 03:57:00 +08:00
|
|
|
* It also tries to inline spectre_v2=retpoline,lfence when size permits.
|
2021-10-26 20:01:42 +08:00
|
|
|
*/
|
|
|
|
static int patch_retpoline(void *addr, struct insn *insn, u8 *bytes)
|
|
|
|
{
|
|
|
|
retpoline_thunk_t *target;
|
2021-10-26 20:01:43 +08:00
|
|
|
int reg, ret, i = 0;
|
|
|
|
u8 op, cc;
|
2021-10-26 20:01:42 +08:00
|
|
|
|
|
|
|
target = addr + insn->length + insn->immediate.value;
|
|
|
|
reg = target - __x86_indirect_thunk_array;
|
|
|
|
|
|
|
|
if (WARN_ON_ONCE(reg & ~0xf))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* If anyone ever does: CALL/JMP *%rsp, we're in deep trouble. */
|
|
|
|
BUG_ON(reg == 4);
|
|
|
|
|
2021-10-26 20:01:44 +08:00
|
|
|
if (cpu_feature_enabled(X86_FEATURE_RETPOLINE) &&
|
2022-09-15 19:11:28 +08:00
|
|
|
!cpu_feature_enabled(X86_FEATURE_RETPOLINE_LFENCE)) {
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_CALL_DEPTH))
|
|
|
|
return emit_call_track_retpoline(addr, insn, reg, bytes);
|
|
|
|
|
2021-10-26 20:01:42 +08:00
|
|
|
return -1;
|
2022-09-15 19:11:28 +08:00
|
|
|
}
|
2021-10-26 20:01:42 +08:00
|
|
|
|
2021-10-26 20:01:43 +08:00
|
|
|
op = insn->opcode.bytes[0];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert:
|
|
|
|
*
|
|
|
|
* Jcc.d32 __x86_indirect_thunk_\reg
|
|
|
|
*
|
|
|
|
* into:
|
|
|
|
*
|
|
|
|
* Jncc.d8 1f
|
2021-10-26 20:01:44 +08:00
|
|
|
* [ LFENCE ]
|
2021-10-26 20:01:43 +08:00
|
|
|
* JMP *%\reg
|
2021-10-26 20:01:44 +08:00
|
|
|
* [ NOP ]
|
2021-10-26 20:01:43 +08:00
|
|
|
* 1:
|
|
|
|
*/
|
2022-09-15 19:11:28 +08:00
|
|
|
if (is_jcc32(insn)) {
|
2021-10-26 20:01:43 +08:00
|
|
|
cc = insn->opcode.bytes[1] & 0xf;
|
|
|
|
cc ^= 1; /* invert condition */
|
|
|
|
|
|
|
|
bytes[i++] = 0x70 + cc; /* Jcc.d8 */
|
|
|
|
bytes[i++] = insn->length - 2; /* sizeof(Jcc.d8) == 2 */
|
|
|
|
|
|
|
|
/* Continue as if: JMP.d32 __x86_indirect_thunk_\reg */
|
|
|
|
op = JMP32_INSN_OPCODE;
|
|
|
|
}
|
|
|
|
|
2021-10-26 20:01:44 +08:00
|
|
|
/*
|
2022-02-17 03:57:00 +08:00
|
|
|
* For RETPOLINE_LFENCE: prepend the indirect CALL/JMP with an LFENCE.
|
2021-10-26 20:01:44 +08:00
|
|
|
*/
|
2022-02-17 03:57:00 +08:00
|
|
|
if (cpu_feature_enabled(X86_FEATURE_RETPOLINE_LFENCE)) {
|
2021-10-26 20:01:44 +08:00
|
|
|
bytes[i++] = 0x0f;
|
|
|
|
bytes[i++] = 0xae;
|
|
|
|
bytes[i++] = 0xe8; /* LFENCE */
|
|
|
|
}
|
|
|
|
|
2021-10-26 20:01:43 +08:00
|
|
|
ret = emit_indirect(op, reg, bytes + i);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
i += ret;
|
2021-10-26 20:01:42 +08:00
|
|
|
|
2022-09-08 18:04:50 +08:00
|
|
|
/*
|
|
|
|
* The compiler is supposed to EMIT an INT3 after every unconditional
|
|
|
|
* JMP instruction due to AMD BTC. However, if the compiler is too old
|
|
|
|
* or SLS isn't enabled, we still need an INT3 after indirect JMPs
|
|
|
|
* even on Intel.
|
|
|
|
*/
|
|
|
|
if (op == JMP32_INSN_OPCODE && i < insn->length)
|
|
|
|
bytes[i++] = INT3_INSN_OPCODE;
|
|
|
|
|
2021-10-26 20:01:42 +08:00
|
|
|
for (; i < insn->length;)
|
|
|
|
bytes[i++] = BYTES_NOP1;
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Generated by 'objtool --retpoline'.
|
|
|
|
*/
|
|
|
|
void __init_or_module noinline apply_retpolines(s32 *start, s32 *end)
|
|
|
|
{
|
|
|
|
s32 *s;
|
|
|
|
|
|
|
|
for (s = start; s < end; s++) {
|
|
|
|
void *addr = (void *)s + *s;
|
|
|
|
struct insn insn;
|
|
|
|
int len, ret;
|
|
|
|
u8 bytes[16];
|
|
|
|
u8 op1, op2;
|
|
|
|
|
|
|
|
ret = insn_decode_kernel(&insn, addr);
|
|
|
|
if (WARN_ON_ONCE(ret < 0))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
op1 = insn.opcode.bytes[0];
|
|
|
|
op2 = insn.opcode.bytes[1];
|
|
|
|
|
|
|
|
switch (op1) {
|
|
|
|
case CALL_INSN_OPCODE:
|
|
|
|
case JMP32_INSN_OPCODE:
|
|
|
|
break;
|
|
|
|
|
2021-10-26 20:01:43 +08:00
|
|
|
case 0x0f: /* escape */
|
|
|
|
if (op2 >= 0x80 && op2 <= 0x8f)
|
|
|
|
break;
|
|
|
|
fallthrough;
|
2021-10-26 20:01:42 +08:00
|
|
|
default:
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-02-09 01:10:51 +08:00
|
|
|
DPRINTK(RETPOLINE, "retpoline at: %pS (%px) len: %d to: %pS",
|
2021-10-26 20:01:45 +08:00
|
|
|
addr, addr, insn.length,
|
|
|
|
addr + insn.length + insn.immediate.value);
|
|
|
|
|
2021-10-26 20:01:42 +08:00
|
|
|
len = patch_retpoline(addr, &insn, bytes);
|
|
|
|
if (len == insn.length) {
|
|
|
|
optimize_nops(bytes, len);
|
2023-02-09 01:10:51 +08:00
|
|
|
DUMP_BYTES(RETPOLINE, ((u8*)addr), len, "%px: orig: ", addr);
|
|
|
|
DUMP_BYTES(RETPOLINE, ((u8*)bytes), len, "%px: repl: ", addr);
|
2021-10-26 20:01:42 +08:00
|
|
|
text_poke_early(addr, bytes, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-28 06:21:17 +08:00
|
|
|
#ifdef CONFIG_RETHUNK
|
2022-09-15 19:11:25 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_CALL_THUNKS
|
|
|
|
void (*x86_return_thunk)(void) __ro_after_init = &__x86_return_thunk;
|
|
|
|
#endif
|
|
|
|
|
2022-06-15 05:15:37 +08:00
|
|
|
/*
|
|
|
|
* Rewrite the compiler generated return thunk tail-calls.
|
|
|
|
*
|
|
|
|
* For example, convert:
|
|
|
|
*
|
|
|
|
* JMP __x86_return_thunk
|
|
|
|
*
|
|
|
|
* into:
|
|
|
|
*
|
|
|
|
* RET
|
|
|
|
*/
|
|
|
|
static int patch_return(void *addr, struct insn *insn, u8 *bytes)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
|
2023-05-12 20:05:11 +08:00
|
|
|
/* Patch the custom return thunks... */
|
2022-09-15 19:11:25 +08:00
|
|
|
if (cpu_feature_enabled(X86_FEATURE_RETHUNK)) {
|
|
|
|
i = JMP32_INSN_SIZE;
|
|
|
|
__text_gen_insn(bytes, JMP32_INSN_OPCODE, addr, x86_return_thunk, i);
|
|
|
|
} else {
|
2023-05-12 20:05:11 +08:00
|
|
|
/* ... or patch them out if not needed. */
|
2022-09-15 19:11:25 +08:00
|
|
|
bytes[i++] = RET_INSN_OPCODE;
|
|
|
|
}
|
2022-06-15 05:15:37 +08:00
|
|
|
|
|
|
|
for (; i < insn->length;)
|
|
|
|
bytes[i++] = INT3_INSN_OPCODE;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
void __init_or_module noinline apply_returns(s32 *start, s32 *end)
|
|
|
|
{
|
|
|
|
s32 *s;
|
|
|
|
|
2023-05-12 20:05:11 +08:00
|
|
|
/*
|
|
|
|
* Do not patch out the default return thunks if those needed are the
|
|
|
|
* ones generated by the compiler.
|
|
|
|
*/
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_RETHUNK) &&
|
|
|
|
(x86_return_thunk == __x86_return_thunk))
|
|
|
|
return;
|
|
|
|
|
2022-06-15 05:15:37 +08:00
|
|
|
for (s = start; s < end; s++) {
|
x86,static_call: Use alternative RET encoding
In addition to teaching static_call about the new way to spell 'RET',
there is an added complication in that static_call() is allowed to
rewrite text before it is known which particular spelling is required.
In order to deal with this; have a static_call specific fixup in the
apply_return() 'alternative' patching routine that will rewrite the
static_call trampoline to match the definite sequence.
This in turn creates the problem of uniquely identifying static call
trampolines. Currently trampolines are 8 bytes, the first 5 being the
jmp.d32/ret sequence and the final 3 a byte sequence that spells out
'SCT'.
This sequence is used in __static_call_validate() to ensure it is
patching a trampoline and not a random other jmp.d32. That is,
false-positives shouldn't be plenty, but aren't a big concern.
OTOH the new __static_call_fixup() must not have false-positives, and
'SCT' decodes to the somewhat weird but semi plausible sequence:
push %rbx
rex.XB push %r12
Additionally, there are SLS concerns with immediate jumps. Combined it
seems like a good moment to change the signature to a single 3 byte
trap instruction that is unique to this usage and will not ever get
generated by accident.
As such, change the signature to: '0x0f, 0xb9, 0xcc', which decodes
to:
ud1 %esp, %ecx
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
2022-06-15 05:15:39 +08:00
|
|
|
void *dest = NULL, *addr = (void *)s + *s;
|
2022-06-15 05:15:37 +08:00
|
|
|
struct insn insn;
|
|
|
|
int len, ret;
|
|
|
|
u8 bytes[16];
|
x86,static_call: Use alternative RET encoding
In addition to teaching static_call about the new way to spell 'RET',
there is an added complication in that static_call() is allowed to
rewrite text before it is known which particular spelling is required.
In order to deal with this; have a static_call specific fixup in the
apply_return() 'alternative' patching routine that will rewrite the
static_call trampoline to match the definite sequence.
This in turn creates the problem of uniquely identifying static call
trampolines. Currently trampolines are 8 bytes, the first 5 being the
jmp.d32/ret sequence and the final 3 a byte sequence that spells out
'SCT'.
This sequence is used in __static_call_validate() to ensure it is
patching a trampoline and not a random other jmp.d32. That is,
false-positives shouldn't be plenty, but aren't a big concern.
OTOH the new __static_call_fixup() must not have false-positives, and
'SCT' decodes to the somewhat weird but semi plausible sequence:
push %rbx
rex.XB push %r12
Additionally, there are SLS concerns with immediate jumps. Combined it
seems like a good moment to change the signature to a single 3 byte
trap instruction that is unique to this usage and will not ever get
generated by accident.
As such, change the signature to: '0x0f, 0xb9, 0xcc', which decodes
to:
ud1 %esp, %ecx
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
2022-06-15 05:15:39 +08:00
|
|
|
u8 op;
|
2022-06-15 05:15:37 +08:00
|
|
|
|
|
|
|
ret = insn_decode_kernel(&insn, addr);
|
|
|
|
if (WARN_ON_ONCE(ret < 0))
|
|
|
|
continue;
|
|
|
|
|
x86,static_call: Use alternative RET encoding
In addition to teaching static_call about the new way to spell 'RET',
there is an added complication in that static_call() is allowed to
rewrite text before it is known which particular spelling is required.
In order to deal with this; have a static_call specific fixup in the
apply_return() 'alternative' patching routine that will rewrite the
static_call trampoline to match the definite sequence.
This in turn creates the problem of uniquely identifying static call
trampolines. Currently trampolines are 8 bytes, the first 5 being the
jmp.d32/ret sequence and the final 3 a byte sequence that spells out
'SCT'.
This sequence is used in __static_call_validate() to ensure it is
patching a trampoline and not a random other jmp.d32. That is,
false-positives shouldn't be plenty, but aren't a big concern.
OTOH the new __static_call_fixup() must not have false-positives, and
'SCT' decodes to the somewhat weird but semi plausible sequence:
push %rbx
rex.XB push %r12
Additionally, there are SLS concerns with immediate jumps. Combined it
seems like a good moment to change the signature to a single 3 byte
trap instruction that is unique to this usage and will not ever get
generated by accident.
As such, change the signature to: '0x0f, 0xb9, 0xcc', which decodes
to:
ud1 %esp, %ecx
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
2022-06-15 05:15:39 +08:00
|
|
|
op = insn.opcode.bytes[0];
|
|
|
|
if (op == JMP32_INSN_OPCODE)
|
|
|
|
dest = addr + insn.length + insn.immediate.value;
|
|
|
|
|
|
|
|
if (__static_call_fixup(addr, op, dest) ||
|
2022-07-14 05:38:19 +08:00
|
|
|
WARN_ONCE(dest != &__x86_return_thunk,
|
|
|
|
"missing return thunk: %pS-%pS: %*ph",
|
|
|
|
addr, dest, 5, addr))
|
2022-06-15 05:15:37 +08:00
|
|
|
continue;
|
|
|
|
|
2023-02-09 01:10:51 +08:00
|
|
|
DPRINTK(RET, "return thunk at: %pS (%px) len: %d to: %pS",
|
2022-06-15 05:15:37 +08:00
|
|
|
addr, addr, insn.length,
|
|
|
|
addr + insn.length + insn.immediate.value);
|
|
|
|
|
|
|
|
len = patch_return(addr, &insn, bytes);
|
|
|
|
if (len == insn.length) {
|
2023-02-09 01:10:51 +08:00
|
|
|
DUMP_BYTES(RET, ((u8*)addr), len, "%px: orig: ", addr);
|
|
|
|
DUMP_BYTES(RET, ((u8*)bytes), len, "%px: repl: ", addr);
|
2022-06-15 05:15:37 +08:00
|
|
|
text_poke_early(addr, bytes, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-06-28 06:21:17 +08:00
|
|
|
#else
|
|
|
|
void __init_or_module noinline apply_returns(s32 *start, s32 *end) { }
|
|
|
|
#endif /* CONFIG_RETHUNK */
|
|
|
|
|
2022-04-19 00:50:36 +08:00
|
|
|
#else /* !CONFIG_RETPOLINE || !CONFIG_OBJTOOL */
|
2021-10-26 20:01:42 +08:00
|
|
|
|
|
|
|
void __init_or_module noinline apply_retpolines(s32 *start, s32 *end) { }
|
2022-06-15 05:15:37 +08:00
|
|
|
void __init_or_module noinline apply_returns(s32 *start, s32 *end) { }
|
2021-10-26 20:01:42 +08:00
|
|
|
|
2022-04-19 00:50:36 +08:00
|
|
|
#endif /* CONFIG_RETPOLINE && CONFIG_OBJTOOL */
|
2021-10-26 20:01:42 +08:00
|
|
|
|
2022-03-08 23:30:56 +08:00
|
|
|
#ifdef CONFIG_X86_KERNEL_IBT
|
|
|
|
|
2023-05-13 22:01:39 +08:00
|
|
|
static void __init_or_module poison_endbr(void *addr, bool warn)
|
2022-10-27 17:28:14 +08:00
|
|
|
{
|
|
|
|
u32 endbr, poison = gen_endbr_poison();
|
|
|
|
|
|
|
|
if (WARN_ON_ONCE(get_kernel_nofault(endbr, addr)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!is_endbr(endbr)) {
|
|
|
|
WARN_ON_ONCE(warn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-02-09 01:10:51 +08:00
|
|
|
DPRINTK(ENDBR, "ENDBR at: %pS (%px)", addr, addr);
|
2022-10-27 17:28:14 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* When we have IBT, the lack of ENDBR will trigger #CP
|
|
|
|
*/
|
2023-02-09 01:10:51 +08:00
|
|
|
DUMP_BYTES(ENDBR, ((u8*)addr), 4, "%px: orig: ", addr);
|
|
|
|
DUMP_BYTES(ENDBR, ((u8*)&poison), 4, "%px: repl: ", addr);
|
2022-10-27 17:28:14 +08:00
|
|
|
text_poke_early(addr, &poison, 4);
|
|
|
|
}
|
|
|
|
|
2022-03-08 23:30:56 +08:00
|
|
|
/*
|
|
|
|
* Generated by: objtool --ibt
|
|
|
|
*/
|
2023-06-22 21:36:50 +08:00
|
|
|
void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end)
|
2022-03-08 23:30:56 +08:00
|
|
|
{
|
|
|
|
s32 *s;
|
|
|
|
|
|
|
|
for (s = start; s < end; s++) {
|
|
|
|
void *addr = (void *)s + *s;
|
|
|
|
|
2022-10-27 17:28:14 +08:00
|
|
|
poison_endbr(addr, true);
|
|
|
|
if (IS_ENABLED(CONFIG_FINEIBT))
|
|
|
|
poison_endbr(addr - 16, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2023-06-22 21:36:50 +08:00
|
|
|
void __init_or_module apply_seal_endbr(s32 *start, s32 *end) { }
|
2022-10-27 17:28:14 +08:00
|
|
|
|
|
|
|
#endif /* CONFIG_X86_KERNEL_IBT */
|
|
|
|
|
|
|
|
#ifdef CONFIG_FINEIBT
|
2022-10-27 17:28:15 +08:00
|
|
|
|
|
|
|
enum cfi_mode {
|
|
|
|
CFI_DEFAULT,
|
|
|
|
CFI_OFF,
|
|
|
|
CFI_KCFI,
|
|
|
|
CFI_FINEIBT,
|
|
|
|
};
|
|
|
|
|
|
|
|
static enum cfi_mode cfi_mode __ro_after_init = CFI_DEFAULT;
|
2022-10-27 17:28:16 +08:00
|
|
|
static bool cfi_rand __ro_after_init = true;
|
|
|
|
static u32 cfi_seed __ro_after_init;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Re-hash the CFI hash with a boot-time seed while making sure the result is
|
|
|
|
* not a valid ENDBR instruction.
|
|
|
|
*/
|
|
|
|
static u32 cfi_rehash(u32 hash)
|
|
|
|
{
|
|
|
|
hash ^= cfi_seed;
|
|
|
|
while (unlikely(is_endbr(hash) || is_endbr(-hash))) {
|
|
|
|
bool lsb = hash & 1;
|
|
|
|
hash >>= 1;
|
|
|
|
if (lsb)
|
|
|
|
hash ^= 0x80200003;
|
|
|
|
}
|
|
|
|
return hash;
|
|
|
|
}
|
2022-10-27 17:28:15 +08:00
|
|
|
|
|
|
|
static __init int cfi_parse_cmdline(char *str)
|
|
|
|
{
|
|
|
|
if (!str)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
while (str) {
|
|
|
|
char *next = strchr(str, ',');
|
|
|
|
if (next) {
|
|
|
|
*next = 0;
|
|
|
|
next++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(str, "auto")) {
|
|
|
|
cfi_mode = CFI_DEFAULT;
|
|
|
|
} else if (!strcmp(str, "off")) {
|
|
|
|
cfi_mode = CFI_OFF;
|
2022-10-27 17:28:16 +08:00
|
|
|
cfi_rand = false;
|
2022-10-27 17:28:15 +08:00
|
|
|
} else if (!strcmp(str, "kcfi")) {
|
|
|
|
cfi_mode = CFI_KCFI;
|
|
|
|
} else if (!strcmp(str, "fineibt")) {
|
|
|
|
cfi_mode = CFI_FINEIBT;
|
2022-10-27 17:28:16 +08:00
|
|
|
} else if (!strcmp(str, "norand")) {
|
|
|
|
cfi_rand = false;
|
2022-10-27 17:28:15 +08:00
|
|
|
} else {
|
|
|
|
pr_err("Ignoring unknown cfi option (%s).", str);
|
|
|
|
}
|
|
|
|
|
|
|
|
str = next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
early_param("cfi", cfi_parse_cmdline);
|
|
|
|
|
2022-10-27 17:28:14 +08:00
|
|
|
/*
|
|
|
|
* kCFI FineIBT
|
|
|
|
*
|
|
|
|
* __cfi_\func: __cfi_\func:
|
|
|
|
* movl $0x12345678,%eax // 5 endbr64 // 4
|
|
|
|
* nop subl $0x12345678,%r10d // 7
|
|
|
|
* nop jz 1f // 2
|
|
|
|
* nop ud2 // 2
|
|
|
|
* nop 1: nop // 1
|
|
|
|
* nop
|
|
|
|
* nop
|
|
|
|
* nop
|
|
|
|
* nop
|
|
|
|
* nop
|
|
|
|
* nop
|
|
|
|
* nop
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* caller: caller:
|
|
|
|
* movl $(-0x12345678),%r10d // 6 movl $0x12345678,%r10d // 6
|
|
|
|
* addl $-15(%r11),%r10d // 4 sub $16,%r11 // 4
|
|
|
|
* je 1f // 2 nop4 // 4
|
|
|
|
* ud2 // 2
|
|
|
|
* 1: call __x86_indirect_thunk_r11 // 5 call *%r11; nop2; // 5
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
asm( ".pushsection .rodata \n"
|
|
|
|
"fineibt_preamble_start: \n"
|
|
|
|
" endbr64 \n"
|
|
|
|
" subl $0x12345678, %r10d \n"
|
|
|
|
" je fineibt_preamble_end \n"
|
|
|
|
" ud2 \n"
|
|
|
|
" nop \n"
|
|
|
|
"fineibt_preamble_end: \n"
|
|
|
|
".popsection\n"
|
|
|
|
);
|
|
|
|
|
|
|
|
extern u8 fineibt_preamble_start[];
|
|
|
|
extern u8 fineibt_preamble_end[];
|
|
|
|
|
|
|
|
#define fineibt_preamble_size (fineibt_preamble_end - fineibt_preamble_start)
|
|
|
|
#define fineibt_preamble_hash 7
|
|
|
|
|
|
|
|
asm( ".pushsection .rodata \n"
|
|
|
|
"fineibt_caller_start: \n"
|
|
|
|
" movl $0x12345678, %r10d \n"
|
|
|
|
" sub $16, %r11 \n"
|
|
|
|
ASM_NOP4
|
|
|
|
"fineibt_caller_end: \n"
|
|
|
|
".popsection \n"
|
|
|
|
);
|
|
|
|
|
|
|
|
extern u8 fineibt_caller_start[];
|
|
|
|
extern u8 fineibt_caller_end[];
|
|
|
|
|
|
|
|
#define fineibt_caller_size (fineibt_caller_end - fineibt_caller_start)
|
|
|
|
#define fineibt_caller_hash 2
|
|
|
|
|
|
|
|
#define fineibt_caller_jmp (fineibt_caller_size - 2)
|
|
|
|
|
|
|
|
static u32 decode_preamble_hash(void *addr)
|
|
|
|
{
|
|
|
|
u8 *p = addr;
|
|
|
|
|
|
|
|
/* b8 78 56 34 12 mov $0x12345678,%eax */
|
|
|
|
if (p[0] == 0xb8)
|
|
|
|
return *(u32 *)(addr + 1);
|
|
|
|
|
|
|
|
return 0; /* invalid hash value */
|
|
|
|
}
|
|
|
|
|
|
|
|
static u32 decode_caller_hash(void *addr)
|
|
|
|
{
|
|
|
|
u8 *p = addr;
|
|
|
|
|
|
|
|
/* 41 ba 78 56 34 12 mov $0x12345678,%r10d */
|
|
|
|
if (p[0] == 0x41 && p[1] == 0xba)
|
|
|
|
return -*(u32 *)(addr + 2);
|
|
|
|
|
|
|
|
/* e8 0c 78 56 34 12 jmp.d8 +12 */
|
|
|
|
if (p[0] == JMP8_INSN_OPCODE && p[1] == fineibt_caller_jmp)
|
|
|
|
return -*(u32 *)(addr + 2);
|
|
|
|
|
|
|
|
return 0; /* invalid hash value */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* .retpoline_sites */
|
|
|
|
static int cfi_disable_callers(s32 *start, s32 *end)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Disable kCFI by patching in a JMP.d8, this leaves the hash immediate
|
|
|
|
* in tact for later usage. Also see decode_caller_hash() and
|
|
|
|
* cfi_rewrite_callers().
|
|
|
|
*/
|
|
|
|
const u8 jmp[] = { JMP8_INSN_OPCODE, fineibt_caller_jmp };
|
|
|
|
s32 *s;
|
2022-03-08 23:30:56 +08:00
|
|
|
|
2022-10-27 17:28:14 +08:00
|
|
|
for (s = start; s < end; s++) {
|
|
|
|
void *addr = (void *)s + *s;
|
|
|
|
u32 hash;
|
|
|
|
|
|
|
|
addr -= fineibt_caller_size;
|
|
|
|
hash = decode_caller_hash(addr);
|
|
|
|
if (!hash) /* nocfi callers */
|
2022-03-08 23:30:56 +08:00
|
|
|
continue;
|
|
|
|
|
2022-10-27 17:28:14 +08:00
|
|
|
text_poke_early(addr, jmp, 2);
|
|
|
|
}
|
2022-03-08 23:30:56 +08:00
|
|
|
|
2022-10-27 17:28:14 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-10-27 17:28:16 +08:00
|
|
|
static int cfi_enable_callers(s32 *start, s32 *end)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Re-enable kCFI, undo what cfi_disable_callers() did.
|
|
|
|
*/
|
|
|
|
const u8 mov[] = { 0x41, 0xba };
|
|
|
|
s32 *s;
|
|
|
|
|
|
|
|
for (s = start; s < end; s++) {
|
|
|
|
void *addr = (void *)s + *s;
|
|
|
|
u32 hash;
|
|
|
|
|
|
|
|
addr -= fineibt_caller_size;
|
|
|
|
hash = decode_caller_hash(addr);
|
|
|
|
if (!hash) /* nocfi callers */
|
2022-03-08 23:30:56 +08:00
|
|
|
continue;
|
|
|
|
|
2022-10-27 17:28:16 +08:00
|
|
|
text_poke_early(addr, mov, 2);
|
|
|
|
}
|
2022-03-08 23:30:56 +08:00
|
|
|
|
2022-10-27 17:28:16 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-10-27 17:28:14 +08:00
|
|
|
/* .cfi_sites */
|
2022-10-27 17:28:16 +08:00
|
|
|
static int cfi_rand_preamble(s32 *start, s32 *end)
|
|
|
|
{
|
|
|
|
s32 *s;
|
|
|
|
|
|
|
|
for (s = start; s < end; s++) {
|
|
|
|
void *addr = (void *)s + *s;
|
|
|
|
u32 hash;
|
|
|
|
|
|
|
|
hash = decode_preamble_hash(addr);
|
|
|
|
if (WARN(!hash, "no CFI hash found at: %pS %px %*ph\n",
|
|
|
|
addr, addr, 5, addr))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
hash = cfi_rehash(hash);
|
|
|
|
text_poke_early(addr + 1, &hash, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-10-27 17:28:14 +08:00
|
|
|
static int cfi_rewrite_preamble(s32 *start, s32 *end)
|
|
|
|
{
|
|
|
|
s32 *s;
|
|
|
|
|
|
|
|
for (s = start; s < end; s++) {
|
|
|
|
void *addr = (void *)s + *s;
|
|
|
|
u32 hash;
|
|
|
|
|
|
|
|
hash = decode_preamble_hash(addr);
|
|
|
|
if (WARN(!hash, "no CFI hash found at: %pS %px %*ph\n",
|
|
|
|
addr, addr, 5, addr))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
text_poke_early(addr, fineibt_preamble_start, fineibt_preamble_size);
|
|
|
|
WARN_ON(*(u32 *)(addr + fineibt_preamble_hash) != 0x12345678);
|
|
|
|
text_poke_early(addr + fineibt_preamble_hash, &hash, 4);
|
2022-03-08 23:30:56 +08:00
|
|
|
}
|
2022-10-27 17:28:14 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* .retpoline_sites */
|
2022-10-27 17:28:16 +08:00
|
|
|
static int cfi_rand_callers(s32 *start, s32 *end)
|
|
|
|
{
|
|
|
|
s32 *s;
|
|
|
|
|
|
|
|
for (s = start; s < end; s++) {
|
|
|
|
void *addr = (void *)s + *s;
|
|
|
|
u32 hash;
|
|
|
|
|
|
|
|
addr -= fineibt_caller_size;
|
|
|
|
hash = decode_caller_hash(addr);
|
|
|
|
if (hash) {
|
|
|
|
hash = -cfi_rehash(hash);
|
|
|
|
text_poke_early(addr + 2, &hash, 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-10-27 17:28:14 +08:00
|
|
|
static int cfi_rewrite_callers(s32 *start, s32 *end)
|
|
|
|
{
|
|
|
|
s32 *s;
|
|
|
|
|
|
|
|
for (s = start; s < end; s++) {
|
|
|
|
void *addr = (void *)s + *s;
|
|
|
|
u32 hash;
|
|
|
|
|
|
|
|
addr -= fineibt_caller_size;
|
|
|
|
hash = decode_caller_hash(addr);
|
|
|
|
if (hash) {
|
|
|
|
text_poke_early(addr, fineibt_caller_start, fineibt_caller_size);
|
|
|
|
WARN_ON(*(u32 *)(addr + fineibt_caller_hash) != 0x12345678);
|
|
|
|
text_poke_early(addr + fineibt_caller_hash, &hash, 4);
|
|
|
|
}
|
|
|
|
/* rely on apply_retpolines() */
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
|
|
|
|
s32 *start_cfi, s32 *end_cfi, bool builtin)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (WARN_ONCE(fineibt_preamble_size != 16,
|
|
|
|
"FineIBT preamble wrong size: %ld", fineibt_preamble_size))
|
|
|
|
return;
|
|
|
|
|
2022-10-27 17:28:15 +08:00
|
|
|
if (cfi_mode == CFI_DEFAULT) {
|
|
|
|
cfi_mode = CFI_KCFI;
|
|
|
|
if (HAS_KERNEL_IBT && cpu_feature_enabled(X86_FEATURE_IBT))
|
|
|
|
cfi_mode = CFI_FINEIBT;
|
|
|
|
}
|
|
|
|
|
2022-10-27 17:28:16 +08:00
|
|
|
/*
|
|
|
|
* Rewrite the callers to not use the __cfi_ stubs, such that we might
|
|
|
|
* rewrite them. This disables all CFI. If this succeeds but any of the
|
|
|
|
* later stages fails, we're without CFI.
|
|
|
|
*/
|
|
|
|
ret = cfi_disable_callers(start_retpoline, end_retpoline);
|
|
|
|
if (ret)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (cfi_rand) {
|
|
|
|
if (builtin)
|
|
|
|
cfi_seed = get_random_u32();
|
|
|
|
|
|
|
|
ret = cfi_rand_preamble(start_cfi, end_cfi);
|
2022-10-27 17:28:15 +08:00
|
|
|
if (ret)
|
|
|
|
goto err;
|
|
|
|
|
2022-10-27 17:28:16 +08:00
|
|
|
ret = cfi_rand_callers(start_retpoline, end_retpoline);
|
|
|
|
if (ret)
|
|
|
|
goto err;
|
2022-03-08 23:30:56 +08:00
|
|
|
}
|
2022-10-27 17:28:16 +08:00
|
|
|
|
|
|
|
switch (cfi_mode) {
|
|
|
|
case CFI_OFF:
|
2022-10-27 17:28:15 +08:00
|
|
|
if (builtin)
|
|
|
|
pr_info("Disabling CFI\n");
|
2022-10-27 17:28:14 +08:00
|
|
|
return;
|
|
|
|
|
2022-10-27 17:28:15 +08:00
|
|
|
case CFI_KCFI:
|
2022-10-27 17:28:16 +08:00
|
|
|
ret = cfi_enable_callers(start_retpoline, end_retpoline);
|
|
|
|
if (ret)
|
|
|
|
goto err;
|
|
|
|
|
2022-10-27 17:28:15 +08:00
|
|
|
if (builtin)
|
|
|
|
pr_info("Using kCFI\n");
|
|
|
|
return;
|
2022-10-27 17:28:14 +08:00
|
|
|
|
2022-10-27 17:28:15 +08:00
|
|
|
case CFI_FINEIBT:
|
|
|
|
ret = cfi_rewrite_preamble(start_cfi, end_cfi);
|
|
|
|
if (ret)
|
|
|
|
goto err;
|
2022-10-27 17:28:14 +08:00
|
|
|
|
2022-10-27 17:28:15 +08:00
|
|
|
ret = cfi_rewrite_callers(start_retpoline, end_retpoline);
|
|
|
|
if (ret)
|
|
|
|
goto err;
|
2022-10-27 17:28:14 +08:00
|
|
|
|
2022-10-27 17:28:15 +08:00
|
|
|
if (builtin)
|
|
|
|
pr_info("Using FineIBT CFI\n");
|
|
|
|
return;
|
2022-10-27 17:28:14 +08:00
|
|
|
|
2022-10-27 17:28:15 +08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2022-10-27 17:28:14 +08:00
|
|
|
|
|
|
|
err:
|
|
|
|
pr_err("Something went horribly wrong trying to rewrite the CFI implementation.\n");
|
2022-03-08 23:30:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2022-10-27 17:28:14 +08:00
|
|
|
static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
|
|
|
|
s32 *start_cfi, s32 *end_cfi, bool builtin)
|
|
|
|
{
|
|
|
|
}
|
2022-03-08 23:30:56 +08:00
|
|
|
|
2022-10-27 17:28:14 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
void apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
|
|
|
|
s32 *start_cfi, s32 *end_cfi)
|
|
|
|
{
|
|
|
|
return __apply_fineibt(start_retpoline, end_retpoline,
|
|
|
|
start_cfi, end_cfi,
|
|
|
|
/* .builtin = */ false);
|
|
|
|
}
|
2022-03-08 23:30:56 +08:00
|
|
|
|
2006-07-01 19:36:18 +08:00
|
|
|
#ifdef CONFIG_SMP
|
2010-04-21 23:08:14 +08:00
|
|
|
static void alternatives_smp_lock(const s32 *start, const s32 *end,
|
|
|
|
u8 *text, u8 *text_end)
|
2006-03-23 18:59:32 +08:00
|
|
|
{
|
2010-04-21 23:08:14 +08:00
|
|
|
const s32 *poff;
|
2006-03-23 18:59:32 +08:00
|
|
|
|
2010-04-21 23:08:14 +08:00
|
|
|
for (poff = start; poff < end; poff++) {
|
|
|
|
u8 *ptr = (u8 *)poff + *poff;
|
|
|
|
|
|
|
|
if (!*poff || ptr < text || ptr >= text_end)
|
2006-03-23 18:59:32 +08:00
|
|
|
continue;
|
x86: alternatives : fix LOCK_PREFIX race with preemptible kernel and CPU hotplug
If a kernel thread is preempted in single-cpu mode right after the NOP (nop
about to be turned into a lock prefix), then we CPU hotplug a CPU, and then the
thread is scheduled back again, a SMP-unsafe atomic operation will be used on
shared SMP variables, leading to corruption. No corruption would happen in the
reverse case : going from SMP to UP is ok because we split a bit instruction
into tiny pieces, which does not present this condition.
Changing the 0x90 (single-byte nop) currently used into a 0x3E DS segment
override prefix should fix this issue. Since the default of the atomic
instructions is to use the DS segment anyway, it should not affect the
behavior.
The exception to this are references that use ESP/RSP and EBP/RBP as
the base register (they will use the SS segment), however, in Linux
(a) DS == SS at all times, and (b) we do not distinguish between
segment violations reported as #SS as opposed to #GP, so there is no
need to disassemble the instruction to figure out the suitable segment.
This patch assumes that the 0x3E prefix will leave atomic operations as-is (thus
assuming they normally touch data in the DS segment). Since there seem to be no
obvious ill-use of other segment override prefixes for atomic operations, it
should be safe. It can be verified with a quick
grep -r LOCK_PREFIX include/asm-x86/
grep -A 1 -r LOCK_PREFIX arch/x86/
Taken from
This source :
AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System
Instructions
States
"Instructions that Reference a Non-Stack Segment—If an instruction encoding
references any base register other than rBP or rSP, or if an instruction
contains an immediate offset, the default segment is the data segment (DS).
These instructions can use the segment-override prefix to select one of the
non-default segments, as shown in Table 1-5."
Therefore, forcing the DS segment on the atomic operations, which already use
the DS segment, should not change.
This source :
http://wiki.osdev.org/X86_Instruction_Encoding
States
"In 64-bit the CS, SS, DS and ES segment overrides are ignored."
Confirmed by "AMD 64-Bit Technology" A.7
http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/x86-64_overview.pdf
"In 64-bit mode, the DS, ES, SS and CS segment-override prefixes have no effect.
These four prefixes are no longer treated as segment-override prefixes in the
context of multipleprefix rules. Instead, they are treated as null prefixes."
This patch applies to 2.6.27-rc2, but would also have to be applied to earlier
kernels (2.6.26, 2.6.25, ...).
Performance impact of the fix : tests done on "xaddq" and "xaddl" shows it
actually improves performances on Intel Xeon, AMD64, Pentium M. It does not
change the performance on Pentium II, Pentium 3 and Pentium 4.
Xeon E5405 2.0GHz :
NR_TESTS 10000000
test empty cycles : 162207948
test test 1-byte nop xadd cycles : 170755422
test test DS override prefix xadd cycles : 170000118 *
test test LOCK xadd cycles : 472012134
AMD64 2.0GHz :
NR_TESTS 10000000
test empty cycles : 146674549
test test 1-byte nop xadd cycles : 150273860
test test DS override prefix xadd cycles : 149982382 *
test test LOCK xadd cycles : 270000690
Pentium 4 3.0GHz
NR_TESTS 10000000
test empty cycles : 290001195
test test 1-byte nop xadd cycles : 310000560
test test DS override prefix xadd cycles : 310000575 *
test test LOCK xadd cycles : 1050103740
Pentium M 2.0GHz
NR_TESTS 10000000
test empty cycles : 180000523
test test 1-byte nop xadd cycles : 320000345
test test DS override prefix xadd cycles : 310000374 *
test test LOCK xadd cycles : 480000357
Pentium 3 550MHz
NR_TESTS 10000000
test empty cycles : 510000231
test test 1-byte nop xadd cycles : 620000128
test test DS override prefix xadd cycles : 620000110 *
test test LOCK xadd cycles : 800000088
Pentium II 350MHz
NR_TESTS 10000000
test empty cycles : 200833494
test test 1-byte nop xadd cycles : 340000130
test test DS override prefix xadd cycles : 340000126 *
test test LOCK xadd cycles : 530000078
Speed test modules can be found at
http://ltt.polymtl.ca/svn/trunk/tests/kernel/test-prefix-speed-32.c
http://ltt.polymtl.ca/svn/trunk/tests/kernel/test-prefix-speed.c
Macro-benchmarks
2.0GHz E5405 Core 2 dual Quad-Core Xeon
Summary
* replace smp lock prefixes with DS segment selector prefixes
no lock prefix (s) with lock prefix (s) Speedup
make -j1 kernel/ 33.94 +/- 0.07 34.91 +/- 0.27 2.8 %
hackbench 50 2.99 +/- 0.01 3.74 +/- 0.01 25.1 %
* replace smp lock prefixes with 0x90 nops
no lock prefix (s) with lock prefix (s) Speedup
make -j1 kernel/ 34.16 +/- 0.32 34.91 +/- 0.27 2.2 %
hackbench 50 3.00 +/- 0.01 3.74 +/- 0.01 24.7 %
Detail :
1 CPU, replace smp lock prefixes with DS segment selector prefixes
make -j1 kernel/
real 0m34.067s
user 0m30.630s
sys 0m2.980s
real 0m33.867s
user 0m30.582s
sys 0m3.024s
real 0m33.939s
user 0m30.738s
sys 0m2.876s
real 0m33.913s
user 0m30.806s
sys 0m2.808s
avg : 33.94s
std. dev. : 0.07s
hackbench 50
Time: 2.978
Time: 2.982
Time: 3.010
Time: 2.984
Time: 2.982
avg : 2.99
std. dev. : 0.01
1 CPU, noreplace-smp
make -j1 kernel/
real 0m35.326s
user 0m30.630s
sys 0m3.260s
real 0m34.325s
user 0m30.802s
sys 0m3.084s
real 0m35.568s
user 0m30.722s
sys 0m3.168s
real 0m34.435s
user 0m30.886s
sys 0m2.996s
avg.: 34.91s
std. dev. : 0.27s
hackbench 50
Time: 3.733
Time: 3.750
Time: 3.761
Time: 3.737
Time: 3.741
avg : 3.74
std. dev. : 0.01
1 CPU, replace smp lock prefixes with 0x90 nops
make -j1 kernel/
real 0m34.139s
user 0m30.782s
sys 0m2.820s
real 0m34.010s
user 0m30.630s
sys 0m2.976s
real 0m34.777s
user 0m30.658s
sys 0m2.916s
real 0m33.924s
user 0m30.634s
sys 0m2.924s
real 0m33.962s
user 0m30.774s
sys 0m2.800s
real 0m34.141s
user 0m30.770s
sys 0m2.828s
avg : 34.16
std. dev. : 0.32
hackbench 50
Time: 2.999
Time: 2.994
Time: 3.004
Time: 2.991
Time: 2.988
avg : 3.00
std. dev. : 0.01
I did more runs (20 runs of each) to compare the nop case to the DS
prefix case. Results in seconds. They actually does not seems to show a
significant difference.
NOP
34.155
33.955
34.012
35.299
35.679
34.141
33.995
35.016
34.254
33.957
33.957
34.008
35.013
34.494
33.893
34.295
34.314
34.854
33.991
34.132
DS
34.080
34.304
34.374
35.095
34.291
34.135
33.940
34.208
35.276
34.288
33.861
33.898
34.610
34.709
33.851
34.256
35.161
34.283
33.865
35.078
Used http://www.graphpad.com/quickcalcs/ttest1.cfm?Format=C to do the
T-test (yeah, I'm lazy) :
Group Group One (DS prefix) Group Two (nops)
Mean 34.37815 34.37070
SD 0.46108 0.51905
SEM 0.10310 0.11606
N 20 20
P value and statistical significance:
The two-tailed P value equals 0.9620
By conventional criteria, this difference is considered to be not statistically significant.
Confidence interval:
The mean of Group One minus Group Two equals 0.00745
95% confidence interval of this difference: From -0.30682 to 0.32172
Intermediate values used in calculations:
t = 0.0480
df = 38
standard error of difference = 0.155
So, unless these calculus are completely bogus, the difference between the nop
and the DS case seems not to be statistically significant.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Acked-by: H. Peter Anvin <hpa@zytor.com>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Jeremy Fitzhardinge <jeremy@goop.org>
CC: Roland McGrath <roland@redhat.com>
CC: Ingo Molnar <mingo@elte.hu>
Cc: Steven Rostedt <rostedt@goodmis.org>
CC: Steven Rostedt <srostedt@redhat.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Peter Zijlstra <peterz@infradead.org>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: David Miller <davem@davemloft.net>
CC: Ulrich Drepper <drepper@redhat.com>
CC: Rusty Russell <rusty@rustcorp.com.au>
CC: Gregory Haskins <ghaskins@novell.com>
CC: Arnaldo Carvalho de Melo <acme@redhat.com>
CC: "Luis Claudio R. Goncalves" <lclaudio@uudg.org>
CC: Clark Williams <williams@redhat.com>
CC: Christoph Lameter <cl@linux-foundation.org>
CC: Andi Kleen <andi@firstfloor.org>
CC: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
2008-08-15 04:58:15 +08:00
|
|
|
/* turn DS segment override prefix into lock prefix */
|
2010-04-30 07:53:17 +08:00
|
|
|
if (*ptr == 0x3e)
|
|
|
|
text_poke(ptr, ((unsigned char []){0xf0}), 1);
|
2012-09-19 00:36:14 +08:00
|
|
|
}
|
2006-03-23 18:59:32 +08:00
|
|
|
}
|
|
|
|
|
2010-04-21 23:08:14 +08:00
|
|
|
static void alternatives_smp_unlock(const s32 *start, const s32 *end,
|
|
|
|
u8 *text, u8 *text_end)
|
2006-03-23 18:59:32 +08:00
|
|
|
{
|
2010-04-21 23:08:14 +08:00
|
|
|
const s32 *poff;
|
2006-03-23 18:59:32 +08:00
|
|
|
|
2010-04-21 23:08:14 +08:00
|
|
|
for (poff = start; poff < end; poff++) {
|
|
|
|
u8 *ptr = (u8 *)poff + *poff;
|
|
|
|
|
|
|
|
if (!*poff || ptr < text || ptr >= text_end)
|
2006-03-23 18:59:32 +08:00
|
|
|
continue;
|
x86: alternatives : fix LOCK_PREFIX race with preemptible kernel and CPU hotplug
If a kernel thread is preempted in single-cpu mode right after the NOP (nop
about to be turned into a lock prefix), then we CPU hotplug a CPU, and then the
thread is scheduled back again, a SMP-unsafe atomic operation will be used on
shared SMP variables, leading to corruption. No corruption would happen in the
reverse case : going from SMP to UP is ok because we split a bit instruction
into tiny pieces, which does not present this condition.
Changing the 0x90 (single-byte nop) currently used into a 0x3E DS segment
override prefix should fix this issue. Since the default of the atomic
instructions is to use the DS segment anyway, it should not affect the
behavior.
The exception to this are references that use ESP/RSP and EBP/RBP as
the base register (they will use the SS segment), however, in Linux
(a) DS == SS at all times, and (b) we do not distinguish between
segment violations reported as #SS as opposed to #GP, so there is no
need to disassemble the instruction to figure out the suitable segment.
This patch assumes that the 0x3E prefix will leave atomic operations as-is (thus
assuming they normally touch data in the DS segment). Since there seem to be no
obvious ill-use of other segment override prefixes for atomic operations, it
should be safe. It can be verified with a quick
grep -r LOCK_PREFIX include/asm-x86/
grep -A 1 -r LOCK_PREFIX arch/x86/
Taken from
This source :
AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System
Instructions
States
"Instructions that Reference a Non-Stack Segment—If an instruction encoding
references any base register other than rBP or rSP, or if an instruction
contains an immediate offset, the default segment is the data segment (DS).
These instructions can use the segment-override prefix to select one of the
non-default segments, as shown in Table 1-5."
Therefore, forcing the DS segment on the atomic operations, which already use
the DS segment, should not change.
This source :
http://wiki.osdev.org/X86_Instruction_Encoding
States
"In 64-bit the CS, SS, DS and ES segment overrides are ignored."
Confirmed by "AMD 64-Bit Technology" A.7
http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/x86-64_overview.pdf
"In 64-bit mode, the DS, ES, SS and CS segment-override prefixes have no effect.
These four prefixes are no longer treated as segment-override prefixes in the
context of multipleprefix rules. Instead, they are treated as null prefixes."
This patch applies to 2.6.27-rc2, but would also have to be applied to earlier
kernels (2.6.26, 2.6.25, ...).
Performance impact of the fix : tests done on "xaddq" and "xaddl" shows it
actually improves performances on Intel Xeon, AMD64, Pentium M. It does not
change the performance on Pentium II, Pentium 3 and Pentium 4.
Xeon E5405 2.0GHz :
NR_TESTS 10000000
test empty cycles : 162207948
test test 1-byte nop xadd cycles : 170755422
test test DS override prefix xadd cycles : 170000118 *
test test LOCK xadd cycles : 472012134
AMD64 2.0GHz :
NR_TESTS 10000000
test empty cycles : 146674549
test test 1-byte nop xadd cycles : 150273860
test test DS override prefix xadd cycles : 149982382 *
test test LOCK xadd cycles : 270000690
Pentium 4 3.0GHz
NR_TESTS 10000000
test empty cycles : 290001195
test test 1-byte nop xadd cycles : 310000560
test test DS override prefix xadd cycles : 310000575 *
test test LOCK xadd cycles : 1050103740
Pentium M 2.0GHz
NR_TESTS 10000000
test empty cycles : 180000523
test test 1-byte nop xadd cycles : 320000345
test test DS override prefix xadd cycles : 310000374 *
test test LOCK xadd cycles : 480000357
Pentium 3 550MHz
NR_TESTS 10000000
test empty cycles : 510000231
test test 1-byte nop xadd cycles : 620000128
test test DS override prefix xadd cycles : 620000110 *
test test LOCK xadd cycles : 800000088
Pentium II 350MHz
NR_TESTS 10000000
test empty cycles : 200833494
test test 1-byte nop xadd cycles : 340000130
test test DS override prefix xadd cycles : 340000126 *
test test LOCK xadd cycles : 530000078
Speed test modules can be found at
http://ltt.polymtl.ca/svn/trunk/tests/kernel/test-prefix-speed-32.c
http://ltt.polymtl.ca/svn/trunk/tests/kernel/test-prefix-speed.c
Macro-benchmarks
2.0GHz E5405 Core 2 dual Quad-Core Xeon
Summary
* replace smp lock prefixes with DS segment selector prefixes
no lock prefix (s) with lock prefix (s) Speedup
make -j1 kernel/ 33.94 +/- 0.07 34.91 +/- 0.27 2.8 %
hackbench 50 2.99 +/- 0.01 3.74 +/- 0.01 25.1 %
* replace smp lock prefixes with 0x90 nops
no lock prefix (s) with lock prefix (s) Speedup
make -j1 kernel/ 34.16 +/- 0.32 34.91 +/- 0.27 2.2 %
hackbench 50 3.00 +/- 0.01 3.74 +/- 0.01 24.7 %
Detail :
1 CPU, replace smp lock prefixes with DS segment selector prefixes
make -j1 kernel/
real 0m34.067s
user 0m30.630s
sys 0m2.980s
real 0m33.867s
user 0m30.582s
sys 0m3.024s
real 0m33.939s
user 0m30.738s
sys 0m2.876s
real 0m33.913s
user 0m30.806s
sys 0m2.808s
avg : 33.94s
std. dev. : 0.07s
hackbench 50
Time: 2.978
Time: 2.982
Time: 3.010
Time: 2.984
Time: 2.982
avg : 2.99
std. dev. : 0.01
1 CPU, noreplace-smp
make -j1 kernel/
real 0m35.326s
user 0m30.630s
sys 0m3.260s
real 0m34.325s
user 0m30.802s
sys 0m3.084s
real 0m35.568s
user 0m30.722s
sys 0m3.168s
real 0m34.435s
user 0m30.886s
sys 0m2.996s
avg.: 34.91s
std. dev. : 0.27s
hackbench 50
Time: 3.733
Time: 3.750
Time: 3.761
Time: 3.737
Time: 3.741
avg : 3.74
std. dev. : 0.01
1 CPU, replace smp lock prefixes with 0x90 nops
make -j1 kernel/
real 0m34.139s
user 0m30.782s
sys 0m2.820s
real 0m34.010s
user 0m30.630s
sys 0m2.976s
real 0m34.777s
user 0m30.658s
sys 0m2.916s
real 0m33.924s
user 0m30.634s
sys 0m2.924s
real 0m33.962s
user 0m30.774s
sys 0m2.800s
real 0m34.141s
user 0m30.770s
sys 0m2.828s
avg : 34.16
std. dev. : 0.32
hackbench 50
Time: 2.999
Time: 2.994
Time: 3.004
Time: 2.991
Time: 2.988
avg : 3.00
std. dev. : 0.01
I did more runs (20 runs of each) to compare the nop case to the DS
prefix case. Results in seconds. They actually does not seems to show a
significant difference.
NOP
34.155
33.955
34.012
35.299
35.679
34.141
33.995
35.016
34.254
33.957
33.957
34.008
35.013
34.494
33.893
34.295
34.314
34.854
33.991
34.132
DS
34.080
34.304
34.374
35.095
34.291
34.135
33.940
34.208
35.276
34.288
33.861
33.898
34.610
34.709
33.851
34.256
35.161
34.283
33.865
35.078
Used http://www.graphpad.com/quickcalcs/ttest1.cfm?Format=C to do the
T-test (yeah, I'm lazy) :
Group Group One (DS prefix) Group Two (nops)
Mean 34.37815 34.37070
SD 0.46108 0.51905
SEM 0.10310 0.11606
N 20 20
P value and statistical significance:
The two-tailed P value equals 0.9620
By conventional criteria, this difference is considered to be not statistically significant.
Confidence interval:
The mean of Group One minus Group Two equals 0.00745
95% confidence interval of this difference: From -0.30682 to 0.32172
Intermediate values used in calculations:
t = 0.0480
df = 38
standard error of difference = 0.155
So, unless these calculus are completely bogus, the difference between the nop
and the DS case seems not to be statistically significant.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Acked-by: H. Peter Anvin <hpa@zytor.com>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Jeremy Fitzhardinge <jeremy@goop.org>
CC: Roland McGrath <roland@redhat.com>
CC: Ingo Molnar <mingo@elte.hu>
Cc: Steven Rostedt <rostedt@goodmis.org>
CC: Steven Rostedt <srostedt@redhat.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Peter Zijlstra <peterz@infradead.org>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: David Miller <davem@davemloft.net>
CC: Ulrich Drepper <drepper@redhat.com>
CC: Rusty Russell <rusty@rustcorp.com.au>
CC: Gregory Haskins <ghaskins@novell.com>
CC: Arnaldo Carvalho de Melo <acme@redhat.com>
CC: "Luis Claudio R. Goncalves" <lclaudio@uudg.org>
CC: Clark Williams <williams@redhat.com>
CC: Christoph Lameter <cl@linux-foundation.org>
CC: Andi Kleen <andi@firstfloor.org>
CC: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
2008-08-15 04:58:15 +08:00
|
|
|
/* turn lock prefix into DS segment override prefix */
|
2010-04-30 07:53:17 +08:00
|
|
|
if (*ptr == 0xf0)
|
|
|
|
text_poke(ptr, ((unsigned char []){0x3E}), 1);
|
2012-09-19 00:36:14 +08:00
|
|
|
}
|
2006-03-23 18:59:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
struct smp_alt_module {
|
|
|
|
/* what is this ??? */
|
|
|
|
struct module *mod;
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
/* ptrs to lock prefixes */
|
2010-04-21 23:08:14 +08:00
|
|
|
const s32 *locks;
|
|
|
|
const s32 *locks_end;
|
2006-03-23 18:59:32 +08:00
|
|
|
|
|
|
|
/* .text segment, needed to avoid patching init code ;) */
|
|
|
|
u8 *text;
|
|
|
|
u8 *text_end;
|
|
|
|
|
|
|
|
struct list_head next;
|
|
|
|
};
|
|
|
|
static LIST_HEAD(smp_alt_modules);
|
2017-11-02 09:18:21 +08:00
|
|
|
static bool uniproc_patched = false; /* protected by text_mutex */
|
2006-03-23 18:59:32 +08:00
|
|
|
|
2009-08-19 15:40:48 +08:00
|
|
|
void __init_or_module alternatives_smp_module_add(struct module *mod,
|
|
|
|
char *name,
|
|
|
|
void *locks, void *locks_end,
|
|
|
|
void *text, void *text_end)
|
2006-03-23 18:59:32 +08:00
|
|
|
{
|
|
|
|
struct smp_alt_module *smp;
|
|
|
|
|
2017-11-02 09:18:21 +08:00
|
|
|
mutex_lock(&text_mutex);
|
2012-08-06 15:59:49 +08:00
|
|
|
if (!uniproc_patched)
|
|
|
|
goto unlock;
|
2007-05-03 01:27:13 +08:00
|
|
|
|
2012-08-06 15:59:49 +08:00
|
|
|
if (num_possible_cpus() == 1)
|
|
|
|
/* Don't bother remembering, we'll never have to undo it. */
|
|
|
|
goto smp_unlock;
|
2006-03-23 18:59:32 +08:00
|
|
|
|
|
|
|
smp = kzalloc(sizeof(*smp), GFP_KERNEL);
|
|
|
|
if (NULL == smp)
|
2012-08-06 15:59:49 +08:00
|
|
|
/* we'll run the (safe but slow) SMP code then ... */
|
|
|
|
goto unlock;
|
2006-03-23 18:59:32 +08:00
|
|
|
|
|
|
|
smp->mod = mod;
|
|
|
|
smp->name = name;
|
|
|
|
smp->locks = locks;
|
|
|
|
smp->locks_end = locks_end;
|
|
|
|
smp->text = text;
|
|
|
|
smp->text_end = text_end;
|
2023-02-09 01:10:51 +08:00
|
|
|
DPRINTK(SMP, "locks %p -> %p, text %p -> %p, name %s\n",
|
2014-12-31 03:27:09 +08:00
|
|
|
smp->locks, smp->locks_end,
|
2006-03-23 18:59:32 +08:00
|
|
|
smp->text, smp->text_end, smp->name);
|
|
|
|
|
|
|
|
list_add_tail(&smp->next, &smp_alt_modules);
|
2012-08-06 15:59:49 +08:00
|
|
|
smp_unlock:
|
|
|
|
alternatives_smp_unlock(locks, locks_end, text, text_end);
|
|
|
|
unlock:
|
2017-11-02 09:18:21 +08:00
|
|
|
mutex_unlock(&text_mutex);
|
2006-03-23 18:59:32 +08:00
|
|
|
}
|
|
|
|
|
2009-08-19 15:40:48 +08:00
|
|
|
void __init_or_module alternatives_smp_module_del(struct module *mod)
|
2006-03-23 18:59:32 +08:00
|
|
|
{
|
|
|
|
struct smp_alt_module *item;
|
|
|
|
|
2017-11-02 09:18:21 +08:00
|
|
|
mutex_lock(&text_mutex);
|
2006-03-23 18:59:32 +08:00
|
|
|
list_for_each_entry(item, &smp_alt_modules, next) {
|
|
|
|
if (mod != item->mod)
|
|
|
|
continue;
|
|
|
|
list_del(&item->next);
|
|
|
|
kfree(item);
|
2012-08-06 15:59:49 +08:00
|
|
|
break;
|
2006-03-23 18:59:32 +08:00
|
|
|
}
|
2017-11-02 09:18:21 +08:00
|
|
|
mutex_unlock(&text_mutex);
|
2006-03-23 18:59:32 +08:00
|
|
|
}
|
|
|
|
|
2012-08-06 15:59:49 +08:00
|
|
|
void alternatives_enable_smp(void)
|
2006-03-23 18:59:32 +08:00
|
|
|
{
|
|
|
|
struct smp_alt_module *mod;
|
|
|
|
|
2012-08-06 15:59:49 +08:00
|
|
|
/* Why bother if there are no other CPUs? */
|
|
|
|
BUG_ON(num_possible_cpus() == 1);
|
2006-03-23 18:59:32 +08:00
|
|
|
|
2017-11-02 09:18:21 +08:00
|
|
|
mutex_lock(&text_mutex);
|
2008-01-30 20:33:17 +08:00
|
|
|
|
2012-08-06 15:59:49 +08:00
|
|
|
if (uniproc_patched) {
|
2012-05-22 10:50:07 +08:00
|
|
|
pr_info("switching to SMP code\n");
|
2012-08-06 15:59:49 +08:00
|
|
|
BUG_ON(num_online_cpus() != 1);
|
2008-01-30 20:30:55 +08:00
|
|
|
clear_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
|
|
|
|
clear_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
|
2006-03-23 18:59:32 +08:00
|
|
|
list_for_each_entry(mod, &smp_alt_modules, next)
|
|
|
|
alternatives_smp_lock(mod->locks, mod->locks_end,
|
|
|
|
mod->text, mod->text_end);
|
2012-08-06 15:59:49 +08:00
|
|
|
uniproc_patched = false;
|
2006-03-23 18:59:32 +08:00
|
|
|
}
|
2017-11-02 09:18:21 +08:00
|
|
|
mutex_unlock(&text_mutex);
|
2006-03-23 18:59:32 +08:00
|
|
|
}
|
|
|
|
|
2017-11-02 09:18:21 +08:00
|
|
|
/*
|
|
|
|
* Return 1 if the address range is reserved for SMP-alternatives.
|
|
|
|
* Must hold text_mutex.
|
|
|
|
*/
|
2010-02-03 05:49:11 +08:00
|
|
|
int alternatives_text_reserved(void *start, void *end)
|
|
|
|
{
|
|
|
|
struct smp_alt_module *mod;
|
2010-04-21 23:08:14 +08:00
|
|
|
const s32 *poff;
|
2010-02-06 01:16:47 +08:00
|
|
|
u8 *text_start = start;
|
|
|
|
u8 *text_end = end;
|
2010-02-03 05:49:11 +08:00
|
|
|
|
2017-11-02 09:18:21 +08:00
|
|
|
lockdep_assert_held(&text_mutex);
|
|
|
|
|
2010-02-03 05:49:11 +08:00
|
|
|
list_for_each_entry(mod, &smp_alt_modules, next) {
|
2010-02-06 01:16:47 +08:00
|
|
|
if (mod->text > text_end || mod->text_end < text_start)
|
2010-02-03 05:49:11 +08:00
|
|
|
continue;
|
2010-04-21 23:08:14 +08:00
|
|
|
for (poff = mod->locks; poff < mod->locks_end; poff++) {
|
|
|
|
const u8 *ptr = (const u8 *)poff + *poff;
|
|
|
|
|
|
|
|
if (text_start <= ptr && text_end > ptr)
|
2010-02-03 05:49:11 +08:00
|
|
|
return 1;
|
2010-04-21 23:08:14 +08:00
|
|
|
}
|
2010-02-03 05:49:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
x86/alternatives: Make JMPs more robust
Up until now we had to pay attention to relative JMPs in alternatives
about how their relative offset gets computed so that the jump target
is still correct. Or, as it is the case for near CALLs (opcode e8), we
still have to go and readjust the offset at patching time.
What is more, the static_cpu_has_safe() facility had to forcefully
generate 5-byte JMPs since we couldn't rely on the compiler to generate
properly sized ones so we had to force the longest ones. Worse than
that, sometimes it would generate a replacement JMP which is longer than
the original one, thus overwriting the beginning of the next instruction
at patching time.
So, in order to alleviate all that and make using JMPs more
straight-forward we go and pad the original instruction in an
alternative block with NOPs at build time, should the replacement(s) be
longer. This way, alternatives users shouldn't pay special attention
so that original and replacement instruction sizes are fine but the
assembler would simply add padding where needed and not do anything
otherwise.
As a second aspect, we go and recompute JMPs at patching time so that we
can try to make 5-byte JMPs into two-byte ones if possible. If not, we
still have to recompute the offsets as the replacement JMP gets put far
away in the .altinstr_replacement section leading to a wrong offset if
copied verbatim.
For example, on a locally generated kernel image
old insn VA: 0xffffffff810014bd, CPU feat: X86_FEATURE_ALWAYS, size: 2
__switch_to:
ffffffff810014bd: eb 21 jmp ffffffff810014e0
repl insn: size: 5
ffffffff81d0b23c: e9 b1 62 2f ff jmpq ffffffff810014f2
gets corrected to a 2-byte JMP:
apply_alternatives: feat: 3*32+21, old: (ffffffff810014bd, len: 2), repl: (ffffffff81d0b23c, len: 5)
alt_insn: e9 b1 62 2f ff
recompute_jumps: next_rip: ffffffff81d0b241, tgt_rip: ffffffff810014f2, new_displ: 0x00000033, ret len: 2
converted to: eb 33 90 90 90
and a 5-byte JMP:
old insn VA: 0xffffffff81001516, CPU feat: X86_FEATURE_ALWAYS, size: 2
__switch_to:
ffffffff81001516: eb 30 jmp ffffffff81001548
repl insn: size: 5
ffffffff81d0b241: e9 10 63 2f ff jmpq ffffffff81001556
gets shortened into a two-byte one:
apply_alternatives: feat: 3*32+21, old: (ffffffff81001516, len: 2), repl: (ffffffff81d0b241, len: 5)
alt_insn: e9 10 63 2f ff
recompute_jumps: next_rip: ffffffff81d0b246, tgt_rip: ffffffff81001556, new_displ: 0x0000003e, ret len: 2
converted to: eb 3e 90 90 90
... and so on.
This leads to a net win of around
40ish replacements * 3 bytes savings =~ 120 bytes of I$
on an AMD guest which means some savings of precious instruction cache
bandwidth. The padding to the shorter 2-byte JMPs are single-byte NOPs
which on smart microarchitectures means discarding NOPs at decode time
and thus freeing up execution bandwidth.
Signed-off-by: Borislav Petkov <bp@suse.de>
2015-01-05 20:48:41 +08:00
|
|
|
#endif /* CONFIG_SMP */
|
2006-07-01 19:36:18 +08:00
|
|
|
|
2006-12-07 09:14:08 +08:00
|
|
|
#ifdef CONFIG_PARAVIRT
|
2023-02-09 01:10:53 +08:00
|
|
|
|
|
|
|
/* Use this to add nops to a buffer, then text_poke the whole buffer. */
|
|
|
|
static void __init_or_module add_nops(void *insns, unsigned int len)
|
|
|
|
{
|
|
|
|
while (len > 0) {
|
|
|
|
unsigned int noplen = len;
|
|
|
|
if (noplen > ASM_NOP_MAX)
|
|
|
|
noplen = ASM_NOP_MAX;
|
|
|
|
memcpy(insns, x86_nops[noplen], noplen);
|
|
|
|
insns += noplen;
|
|
|
|
len -= noplen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-19 15:40:48 +08:00
|
|
|
void __init_or_module apply_paravirt(struct paravirt_patch_site *start,
|
|
|
|
struct paravirt_patch_site *end)
|
2006-12-07 09:14:08 +08:00
|
|
|
{
|
2007-05-03 01:27:14 +08:00
|
|
|
struct paravirt_patch_site *p;
|
2019-04-25 19:03:31 +08:00
|
|
|
char insn_buff[MAX_PATCH_LEN];
|
2006-12-07 09:14:08 +08:00
|
|
|
|
|
|
|
for (p = start; p < end; p++) {
|
|
|
|
unsigned int used;
|
|
|
|
|
2007-08-11 04:31:03 +08:00
|
|
|
BUG_ON(p->len > MAX_PATCH_LEN);
|
2007-08-19 05:31:41 +08:00
|
|
|
/* prep the buffer with the original instructions */
|
2019-04-25 19:03:31 +08:00
|
|
|
memcpy(insn_buff, p->instr, p->len);
|
2021-03-11 22:23:19 +08:00
|
|
|
used = paravirt_patch(p->type, insn_buff, (unsigned long)p->instr, p->len);
|
2007-05-03 01:27:13 +08:00
|
|
|
|
2007-05-03 01:27:14 +08:00
|
|
|
BUG_ON(used > p->len);
|
|
|
|
|
2006-12-07 09:14:08 +08:00
|
|
|
/* Pad the rest with nops */
|
2019-04-25 19:03:31 +08:00
|
|
|
add_nops(insn_buff + used, p->len - used);
|
|
|
|
text_poke_early(p->instr, insn_buff, p->len);
|
2006-12-07 09:14:08 +08:00
|
|
|
}
|
|
|
|
}
|
2007-05-03 01:27:14 +08:00
|
|
|
extern struct paravirt_patch_site __start_parainstructions[],
|
2006-12-07 09:14:08 +08:00
|
|
|
__stop_parainstructions[];
|
|
|
|
#endif /* CONFIG_PARAVIRT */
|
|
|
|
|
2019-05-03 18:22:47 +08:00
|
|
|
/*
|
|
|
|
* Self-test for the INT3 based CALL emulation code.
|
|
|
|
*
|
|
|
|
* This exercises int3_emulate_call() to make sure INT3 pt_regs are set up
|
|
|
|
* properly and that there is a stack gap between the INT3 frame and the
|
|
|
|
* previous context. Without this gap doing a virtual PUSH on the interrupted
|
|
|
|
* stack would corrupt the INT3 IRET frame.
|
|
|
|
*
|
|
|
|
* See entry_{32,64}.S for more details.
|
|
|
|
*/
|
2019-07-09 04:55:30 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We define the int3_magic() function in assembly to control the calling
|
|
|
|
* convention such that we can 'call' it from assembly.
|
|
|
|
*/
|
|
|
|
|
|
|
|
extern void int3_magic(unsigned int *ptr); /* defined in asm */
|
|
|
|
|
|
|
|
asm (
|
|
|
|
" .pushsection .init.text, \"ax\", @progbits\n"
|
|
|
|
" .type int3_magic, @function\n"
|
|
|
|
"int3_magic:\n"
|
2022-03-08 23:30:40 +08:00
|
|
|
ANNOTATE_NOENDBR
|
2019-07-09 04:55:30 +08:00
|
|
|
" movl $1, (%" _ASM_ARG1 ")\n"
|
2021-12-04 21:43:41 +08:00
|
|
|
ASM_RET
|
2019-07-09 04:55:30 +08:00
|
|
|
" .size int3_magic, .-int3_magic\n"
|
|
|
|
" .popsection\n"
|
|
|
|
);
|
2019-05-03 18:22:47 +08:00
|
|
|
|
2022-03-08 23:30:37 +08:00
|
|
|
extern void int3_selftest_ip(void); /* defined in asm below */
|
2019-05-03 18:22:47 +08:00
|
|
|
|
|
|
|
static int __init
|
|
|
|
int3_exception_notify(struct notifier_block *self, unsigned long val, void *data)
|
|
|
|
{
|
2022-03-08 23:30:40 +08:00
|
|
|
unsigned long selftest = (unsigned long)&int3_selftest_ip;
|
2019-05-03 18:22:47 +08:00
|
|
|
struct die_args *args = data;
|
|
|
|
struct pt_regs *regs = args->regs;
|
|
|
|
|
2022-03-08 23:30:40 +08:00
|
|
|
OPTIMIZER_HIDE_VAR(selftest);
|
|
|
|
|
2019-05-03 18:22:47 +08:00
|
|
|
if (!regs || user_mode(regs))
|
|
|
|
return NOTIFY_DONE;
|
|
|
|
|
|
|
|
if (val != DIE_INT3)
|
|
|
|
return NOTIFY_DONE;
|
|
|
|
|
2022-03-08 23:30:40 +08:00
|
|
|
if (regs->ip - INT3_INSN_SIZE != selftest)
|
2019-05-03 18:22:47 +08:00
|
|
|
return NOTIFY_DONE;
|
|
|
|
|
|
|
|
int3_emulate_call(regs, (unsigned long)&int3_magic);
|
|
|
|
return NOTIFY_STOP;
|
|
|
|
}
|
|
|
|
|
2022-03-08 23:30:37 +08:00
|
|
|
/* Must be noinline to ensure uniqueness of int3_selftest_ip. */
|
|
|
|
static noinline void __init int3_selftest(void)
|
2019-05-03 18:22:47 +08:00
|
|
|
{
|
|
|
|
static __initdata struct notifier_block int3_exception_nb = {
|
|
|
|
.notifier_call = int3_exception_notify,
|
|
|
|
.priority = INT_MAX-1, /* last */
|
|
|
|
};
|
|
|
|
unsigned int val = 0;
|
|
|
|
|
|
|
|
BUG_ON(register_die_notifier(&int3_exception_nb));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Basically: int3_magic(&val); but really complicated :-)
|
|
|
|
*
|
2022-03-08 23:30:37 +08:00
|
|
|
* INT3 padded with NOP to CALL_INSN_SIZE. The int3_exception_nb
|
|
|
|
* notifier above will emulate CALL for us.
|
2019-05-03 18:22:47 +08:00
|
|
|
*/
|
2022-03-08 23:30:40 +08:00
|
|
|
asm volatile ("int3_selftest_ip:\n\t"
|
|
|
|
ANNOTATE_NOENDBR
|
|
|
|
" int3; nop; nop; nop; nop\n\t"
|
2019-07-09 04:55:30 +08:00
|
|
|
: ASM_CALL_CONSTRAINT
|
|
|
|
: __ASM_SEL_RAW(a, D) (&val)
|
|
|
|
: "memory");
|
2019-05-03 18:22:47 +08:00
|
|
|
|
|
|
|
BUG_ON(val != 1);
|
|
|
|
|
|
|
|
unregister_die_notifier(&int3_exception_nb);
|
|
|
|
}
|
|
|
|
|
2023-02-09 01:10:52 +08:00
|
|
|
static __initdata int __alt_reloc_selftest_addr;
|
|
|
|
|
|
|
|
__visible noinline void __init __alt_reloc_selftest(void *arg)
|
|
|
|
{
|
|
|
|
WARN_ON(arg != &__alt_reloc_selftest_addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static noinline void __init alt_reloc_selftest(void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Tests apply_relocation().
|
|
|
|
*
|
|
|
|
* This has a relative immediate (CALL) in a place other than the first
|
|
|
|
* instruction and additionally on x86_64 we get a RIP-relative LEA:
|
|
|
|
*
|
|
|
|
* lea 0x0(%rip),%rdi # 5d0: R_X86_64_PC32 .init.data+0x5566c
|
|
|
|
* call +0 # 5d5: R_X86_64_PLT32 __alt_reloc_selftest-0x4
|
|
|
|
*
|
|
|
|
* Getting this wrong will either crash and burn or tickle the WARN
|
|
|
|
* above.
|
|
|
|
*/
|
|
|
|
asm_inline volatile (
|
|
|
|
ALTERNATIVE("", "lea %[mem], %%" _ASM_ARG1 "; call __alt_reloc_selftest;", X86_FEATURE_ALWAYS)
|
|
|
|
: /* output */
|
|
|
|
: [mem] "m" (__alt_reloc_selftest_addr)
|
|
|
|
: _ASM_ARG1
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2006-03-23 18:59:32 +08:00
|
|
|
void __init alternative_instructions(void)
|
|
|
|
{
|
2019-05-03 18:22:47 +08:00
|
|
|
int3_selftest();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The patching is not fully atomic, so try to avoid local
|
|
|
|
* interruptions that might execute the to be patched code.
|
|
|
|
* Other CPUs are not running.
|
|
|
|
*/
|
2007-07-22 17:12:32 +08:00
|
|
|
stop_nmi();
|
2009-02-12 20:39:27 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Don't stop machine check exceptions while patching.
|
|
|
|
* MCEs only happen when something got corrupted and in this
|
|
|
|
* case we must do something about the corruption.
|
2019-09-02 20:02:59 +08:00
|
|
|
* Ignoring it is worse than an unlikely patching race.
|
2009-02-12 20:39:27 +08:00
|
|
|
* Also machine checks tend to be broadcast and if one CPU
|
|
|
|
* goes into machine check the others follow quickly, so we don't
|
|
|
|
* expect a machine check to cause undue problems during to code
|
|
|
|
* patching.
|
|
|
|
*/
|
2007-07-22 17:12:32 +08:00
|
|
|
|
2021-03-11 22:23:13 +08:00
|
|
|
/*
|
|
|
|
* Paravirt patching and alternative patching can be combined to
|
|
|
|
* replace a function call with a short direct code sequence (e.g.
|
|
|
|
* by setting a constant return value instead of doing that in an
|
|
|
|
* external function).
|
|
|
|
* In order to make this work the following sequence is required:
|
|
|
|
* 1. set (artificial) features depending on used paravirt
|
|
|
|
* functions which can later influence alternative patching
|
|
|
|
* 2. apply paravirt patching (generally replacing an indirect
|
|
|
|
* function call with a direct one)
|
|
|
|
* 3. apply alternative patching (e.g. replacing a direct function
|
|
|
|
* call with a custom code sequence)
|
|
|
|
* Doing paravirt patching after alternative patching would clobber
|
|
|
|
* the optimization of the custom code with a function call again.
|
|
|
|
*/
|
|
|
|
paravirt_set_cap();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* First patch paravirt functions, such that we overwrite the indirect
|
|
|
|
* call with the direct call.
|
|
|
|
*/
|
|
|
|
apply_paravirt(__parainstructions, __parainstructions_end);
|
|
|
|
|
2022-10-27 17:28:14 +08:00
|
|
|
__apply_fineibt(__retpoline_sites, __retpoline_sites_end,
|
|
|
|
__cfi_sites, __cfi_sites_end, true);
|
|
|
|
|
2021-10-26 20:01:42 +08:00
|
|
|
/*
|
|
|
|
* Rewrite the retpolines, must be done before alternatives since
|
|
|
|
* those can rewrite the retpoline thunks.
|
|
|
|
*/
|
|
|
|
apply_retpolines(__retpoline_sites, __retpoline_sites_end);
|
2022-06-15 05:15:37 +08:00
|
|
|
apply_returns(__return_sites, __return_sites_end);
|
2021-10-26 20:01:42 +08:00
|
|
|
|
2021-03-11 22:23:13 +08:00
|
|
|
/*
|
|
|
|
* Then patch alternatives, such that those paravirt calls that are in
|
|
|
|
* alternatives can be overwritten by their immediate fragments.
|
|
|
|
*/
|
2006-03-23 18:59:32 +08:00
|
|
|
apply_alternatives(__alt_instructions, __alt_instructions_end);
|
|
|
|
|
2022-09-15 19:11:23 +08:00
|
|
|
/*
|
|
|
|
* Now all calls are established. Apply the call thunks if
|
|
|
|
* required.
|
|
|
|
*/
|
|
|
|
callthunks_patch_builtin_calls();
|
|
|
|
|
2023-06-22 21:36:50 +08:00
|
|
|
/*
|
|
|
|
* Seal all functions that do not have their address taken.
|
|
|
|
*/
|
|
|
|
apply_seal_endbr(__ibt_endbr_seal, __ibt_endbr_seal_end);
|
2022-03-08 23:30:56 +08:00
|
|
|
|
2006-07-01 19:36:18 +08:00
|
|
|
#ifdef CONFIG_SMP
|
2012-08-06 15:59:49 +08:00
|
|
|
/* Patch to UP if other cpus not imminent. */
|
|
|
|
if (!noreplace_smp && (num_present_cpus() == 1 || setup_max_cpus <= 1)) {
|
|
|
|
uniproc_patched = true;
|
2006-03-23 18:59:32 +08:00
|
|
|
alternatives_smp_module_add(NULL, "core kernel",
|
|
|
|
__smp_locks, __smp_locks_end,
|
|
|
|
_text, _etext);
|
|
|
|
}
|
2007-07-22 17:12:32 +08:00
|
|
|
|
2019-05-03 18:22:47 +08:00
|
|
|
if (!uniproc_patched || num_possible_cpus() == 1) {
|
2007-10-18 00:04:34 +08:00
|
|
|
free_init_pages("SMP alternatives",
|
|
|
|
(unsigned long)__smp_locks,
|
|
|
|
(unsigned long)__smp_locks_end);
|
2019-05-03 18:22:47 +08:00
|
|
|
}
|
2012-08-06 15:59:49 +08:00
|
|
|
#endif
|
|
|
|
|
2007-07-22 17:12:32 +08:00
|
|
|
restart_nmi();
|
2015-04-30 15:09:26 +08:00
|
|
|
alternatives_patched = 1;
|
2023-02-09 01:10:52 +08:00
|
|
|
|
|
|
|
alt_reloc_selftest();
|
2006-03-23 18:59:32 +08:00
|
|
|
}
|
2007-07-22 17:12:31 +08:00
|
|
|
|
2008-03-06 21:48:49 +08:00
|
|
|
/**
|
|
|
|
* text_poke_early - Update instructions on a live kernel at boot time
|
|
|
|
* @addr: address to modify
|
|
|
|
* @opcode: source of the copy
|
|
|
|
* @len: length to copy
|
|
|
|
*
|
2007-07-22 17:12:31 +08:00
|
|
|
* When you use this code to patch more than one byte of an instruction
|
|
|
|
* you need to make sure that other CPUs cannot execute this code in parallel.
|
2008-03-06 21:48:49 +08:00
|
|
|
* Also no thread must be currently preempted in the middle of these
|
2019-09-02 20:02:59 +08:00
|
|
|
* instructions. And on the local CPU you need to be protected against NMI or
|
|
|
|
* MCE handlers seeing an inconsistent instruction while you patch.
|
2007-07-22 17:12:31 +08:00
|
|
|
*/
|
2019-04-26 08:11:33 +08:00
|
|
|
void __init_or_module text_poke_early(void *addr, const void *opcode,
|
|
|
|
size_t len)
|
2007-07-22 17:12:31 +08:00
|
|
|
{
|
2008-03-06 21:48:49 +08:00
|
|
|
unsigned long flags;
|
2019-04-26 08:11:31 +08:00
|
|
|
|
|
|
|
if (boot_cpu_has(X86_FEATURE_NX) &&
|
|
|
|
is_module_text_address((unsigned long)addr)) {
|
|
|
|
/*
|
|
|
|
* Modules text is marked initially as non-executable, so the
|
|
|
|
* code cannot be running and speculative code-fetches are
|
|
|
|
* prevented. Just change the code.
|
|
|
|
*/
|
|
|
|
memcpy(addr, opcode, len);
|
|
|
|
} else {
|
|
|
|
local_irq_save(flags);
|
|
|
|
memcpy(addr, opcode, len);
|
|
|
|
local_irq_restore(flags);
|
|
|
|
sync_core();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Could also do a CLFLUSH here to speed up CPU recovery; but
|
|
|
|
* that causes hangs on some VIA CPUs.
|
|
|
|
*/
|
|
|
|
}
|
2008-03-06 21:48:49 +08:00
|
|
|
}
|
|
|
|
|
2020-04-21 17:20:31 +08:00
|
|
|
typedef struct {
|
|
|
|
struct mm_struct *mm;
|
|
|
|
} temp_mm_state_t;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Using a temporary mm allows to set temporary mappings that are not accessible
|
|
|
|
* by other CPUs. Such mappings are needed to perform sensitive memory writes
|
|
|
|
* that override the kernel memory protections (e.g., W^X), without exposing the
|
|
|
|
* temporary page-table mappings that are required for these write operations to
|
|
|
|
* other CPUs. Using a temporary mm also allows to avoid TLB shootdowns when the
|
|
|
|
* mapping is torn down.
|
|
|
|
*
|
|
|
|
* Context: The temporary mm needs to be used exclusively by a single core. To
|
|
|
|
* harden security IRQs must be disabled while the temporary mm is
|
|
|
|
* loaded, thereby preventing interrupt handler bugs from overriding
|
|
|
|
* the kernel memory protection.
|
|
|
|
*/
|
|
|
|
static inline temp_mm_state_t use_temporary_mm(struct mm_struct *mm)
|
|
|
|
{
|
|
|
|
temp_mm_state_t temp_state;
|
|
|
|
|
|
|
|
lockdep_assert_irqs_disabled();
|
2020-10-09 22:42:25 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure not to be in TLB lazy mode, as otherwise we'll end up
|
|
|
|
* with a stale address space WITHOUT being in lazy mode after
|
|
|
|
* restoring the previous mm.
|
|
|
|
*/
|
2021-02-21 07:17:08 +08:00
|
|
|
if (this_cpu_read(cpu_tlbstate_shared.is_lazy))
|
2020-10-09 22:42:25 +08:00
|
|
|
leave_mm(smp_processor_id());
|
|
|
|
|
2020-04-21 17:20:31 +08:00
|
|
|
temp_state.mm = this_cpu_read(cpu_tlbstate.loaded_mm);
|
|
|
|
switch_mm_irqs_off(NULL, mm, current);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If breakpoints are enabled, disable them while the temporary mm is
|
|
|
|
* used. Userspace might set up watchpoints on addresses that are used
|
|
|
|
* in the temporary mm, which would lead to wrong signals being sent or
|
|
|
|
* crashes.
|
|
|
|
*
|
|
|
|
* Note that breakpoints are not disabled selectively, which also causes
|
|
|
|
* kernel breakpoints (e.g., perf's) to be disabled. This might be
|
|
|
|
* undesirable, but still seems reasonable as the code that runs in the
|
|
|
|
* temporary mm should be short.
|
|
|
|
*/
|
|
|
|
if (hw_breakpoint_active())
|
|
|
|
hw_breakpoint_disable();
|
|
|
|
|
|
|
|
return temp_state;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void unuse_temporary_mm(temp_mm_state_t prev_state)
|
|
|
|
{
|
|
|
|
lockdep_assert_irqs_disabled();
|
|
|
|
switch_mm_irqs_off(NULL, prev_state.mm, current);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Restore the breakpoints if they were disabled before the temporary mm
|
|
|
|
* was loaded.
|
|
|
|
*/
|
|
|
|
if (hw_breakpoint_active())
|
|
|
|
hw_breakpoint_restore();
|
|
|
|
}
|
|
|
|
|
2019-04-27 07:22:46 +08:00
|
|
|
__ro_after_init struct mm_struct *poking_mm;
|
|
|
|
__ro_after_init unsigned long poking_addr;
|
|
|
|
|
2022-05-21 07:57:52 +08:00
|
|
|
static void text_poke_memcpy(void *dst, const void *src, size_t len)
|
|
|
|
{
|
|
|
|
memcpy(dst, src, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void text_poke_memset(void *dst, const void *src, size_t len)
|
|
|
|
{
|
|
|
|
int c = *(const int *)src;
|
|
|
|
|
|
|
|
memset(dst, c, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef void text_poke_f(void *dst, const void *src, size_t len);
|
|
|
|
|
|
|
|
static void *__text_poke(text_poke_f func, void *addr, const void *src, size_t len)
|
2008-03-06 21:48:49 +08:00
|
|
|
{
|
2019-04-26 08:11:27 +08:00
|
|
|
bool cross_page_boundary = offset_in_page(addr) + len > PAGE_SIZE;
|
|
|
|
struct page *pages[2] = {NULL};
|
|
|
|
temp_mm_state_t prev;
|
2009-03-06 23:37:54 +08:00
|
|
|
unsigned long flags;
|
2019-04-26 08:11:27 +08:00
|
|
|
pte_t pte, *ptep;
|
|
|
|
spinlock_t *ptl;
|
|
|
|
pgprot_t pgprot;
|
2008-03-06 21:48:49 +08:00
|
|
|
|
2018-07-20 04:55:27 +08:00
|
|
|
/*
|
2019-04-26 08:11:27 +08:00
|
|
|
* While boot memory allocator is running we cannot use struct pages as
|
|
|
|
* they are not yet initialized. There is no way to recover.
|
2018-07-20 04:55:27 +08:00
|
|
|
*/
|
|
|
|
BUG_ON(!after_bootmem);
|
|
|
|
|
2008-04-24 23:03:33 +08:00
|
|
|
if (!core_kernel_text((unsigned long)addr)) {
|
|
|
|
pages[0] = vmalloc_to_page(addr);
|
2019-04-26 08:11:27 +08:00
|
|
|
if (cross_page_boundary)
|
|
|
|
pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
|
x86: fix test_poke for vmalloced pages
* Ingo Molnar (mingo@elte.hu) wrote:
>
> * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> wrote:
>
> > The shadow vmap for DEBUG_RODATA kernel text modification uses
> > virt_to_page to get the pages from the pointer address.
> >
> > However, I think vmalloc_to_page would be required in case the page is
> > used for modules.
> >
> > Since only the core kernel text is marked read-only, use
> > kernel_text_address() to make sure we only shadow map the core kernel
> > text, not modules.
>
> actually, i think we should mark module text readonly too.
>
Yes, but in the meantime, the x86 tree would need this patch to make
kprobes work correctly on modules.
I suspect that without this fix, with the enhanced hotplug and kprobes
patch, kprobes will use text_poke to insert breakpoints in modules
(vmalloced pages used), which will map the wrong pages and corrupt
random kernel locations instead of updating the correct page.
Work that would write protect the module pages should clearly be done,
but it can come in a later time. We have to make sure we interact
correctly with the page allocation debugging, as an example.
Here is the patch against x86.git 2.6.25-rc5 :
The shadow vmap for DEBUG_RODATA kernel text modification uses virt_to_page to
get the pages from the pointer address.
However, I think vmalloc_to_page would be required in case the page is used for
modules.
Since only the core kernel text is marked read-only, use kernel_text_address()
to make sure we only shadow map the core kernel text, not modules.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
CC: akpm@linux-foundation.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2008-03-12 23:54:16 +08:00
|
|
|
} else {
|
2008-04-24 23:03:33 +08:00
|
|
|
pages[0] = virt_to_page(addr);
|
2008-04-25 23:07:03 +08:00
|
|
|
WARN_ON(!PageReserved(pages[0]));
|
2019-04-26 08:11:27 +08:00
|
|
|
if (cross_page_boundary)
|
|
|
|
pages[1] = virt_to_page(addr + PAGE_SIZE);
|
2008-03-06 21:48:49 +08:00
|
|
|
}
|
2019-04-26 08:11:27 +08:00
|
|
|
/*
|
|
|
|
* If something went wrong, crash and burn since recovery paths are not
|
|
|
|
* implemented.
|
|
|
|
*/
|
|
|
|
BUG_ON(!pages[0] || (cross_page_boundary && !pages[1]));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Map the page without the global bit, as TLB flushing is done with
|
|
|
|
* flush_tlb_mm_range(), which is intended for non-global PTEs.
|
|
|
|
*/
|
|
|
|
pgprot = __pgprot(pgprot_val(PAGE_KERNEL) & ~_PAGE_GLOBAL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The lock is not really needed, but this allows to avoid open-coding.
|
|
|
|
*/
|
|
|
|
ptep = get_locked_pte(poking_mm, poking_addr, &ptl);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This must not fail; preallocated in poking_init().
|
|
|
|
*/
|
|
|
|
VM_BUG_ON(!ptep);
|
|
|
|
|
2020-08-13 18:50:26 +08:00
|
|
|
local_irq_save(flags);
|
|
|
|
|
2019-04-26 08:11:27 +08:00
|
|
|
pte = mk_pte(pages[0], pgprot);
|
|
|
|
set_pte_at(poking_mm, poking_addr, ptep, pte);
|
|
|
|
|
|
|
|
if (cross_page_boundary) {
|
|
|
|
pte = mk_pte(pages[1], pgprot);
|
|
|
|
set_pte_at(poking_mm, poking_addr + PAGE_SIZE, ptep + 1, pte);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Loading the temporary mm behaves as a compiler barrier, which
|
|
|
|
* guarantees that the PTE will be set at the time memcpy() is done.
|
|
|
|
*/
|
|
|
|
prev = use_temporary_mm(poking_mm);
|
|
|
|
|
|
|
|
kasan_disable_current();
|
2022-05-21 07:57:52 +08:00
|
|
|
func((u8 *)poking_addr + offset_in_page(addr), src, len);
|
2019-04-26 08:11:27 +08:00
|
|
|
kasan_enable_current();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ensure that the PTE is only cleared after the instructions of memcpy
|
|
|
|
* were issued by using a compiler barrier.
|
|
|
|
*/
|
|
|
|
barrier();
|
|
|
|
|
|
|
|
pte_clear(poking_mm, poking_addr, ptep);
|
|
|
|
if (cross_page_boundary)
|
|
|
|
pte_clear(poking_mm, poking_addr + PAGE_SIZE, ptep + 1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Loading the previous page-table hierarchy requires a serializing
|
|
|
|
* instruction that already allows the core to see the updated version.
|
|
|
|
* Xen-PV is assumed to serialize execution in a similar manner.
|
|
|
|
*/
|
|
|
|
unuse_temporary_mm(prev);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Flushing the TLB might involve IPIs, which would require enabled
|
|
|
|
* IRQs, but not if the mm is not used, as it is in this point.
|
|
|
|
*/
|
|
|
|
flush_tlb_mm_range(poking_mm, poking_addr, poking_addr +
|
|
|
|
(cross_page_boundary ? 2 : 1) * PAGE_SIZE,
|
|
|
|
PAGE_SHIFT, false);
|
|
|
|
|
2022-05-21 07:57:52 +08:00
|
|
|
if (func == text_poke_memcpy) {
|
|
|
|
/*
|
|
|
|
* If the text does not match what we just wrote then something is
|
|
|
|
* fundamentally screwy; there's nothing we can really do about that.
|
|
|
|
*/
|
|
|
|
BUG_ON(memcmp(addr, src, len));
|
|
|
|
}
|
2019-04-26 08:11:27 +08:00
|
|
|
|
2009-03-10 00:40:40 +08:00
|
|
|
local_irq_restore(flags);
|
2020-08-13 18:50:26 +08:00
|
|
|
pte_unmap_unlock(ptep, ptl);
|
2008-03-06 21:48:49 +08:00
|
|
|
return addr;
|
2007-07-22 17:12:31 +08:00
|
|
|
}
|
2010-02-25 21:34:38 +08:00
|
|
|
|
2019-04-26 08:11:21 +08:00
|
|
|
/**
|
|
|
|
* text_poke - Update instructions on a live kernel
|
|
|
|
* @addr: address to modify
|
|
|
|
* @opcode: source of the copy
|
|
|
|
* @len: length to copy
|
|
|
|
*
|
|
|
|
* Only atomic text poke/set should be allowed when not doing early patching.
|
|
|
|
* It means the size must be writable atomically and the address must be aligned
|
|
|
|
* in a way that permits an atomic write. It also makes sure we fit on a single
|
|
|
|
* page.
|
2019-04-26 08:11:41 +08:00
|
|
|
*
|
|
|
|
* Note that the caller must ensure that if the modified code is part of a
|
|
|
|
* module, the module would not be removed during poking. This can be achieved
|
|
|
|
* by registering a module notifier, and ordering module removal and patching
|
|
|
|
* trough a mutex.
|
2019-04-26 08:11:21 +08:00
|
|
|
*/
|
|
|
|
void *text_poke(void *addr, const void *opcode, size_t len)
|
|
|
|
{
|
|
|
|
lockdep_assert_held(&text_mutex);
|
|
|
|
|
2022-05-21 07:57:52 +08:00
|
|
|
return __text_poke(text_poke_memcpy, addr, opcode, len);
|
2019-04-26 08:11:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* text_poke_kgdb - Update instructions on a live kernel by kgdb
|
|
|
|
* @addr: address to modify
|
|
|
|
* @opcode: source of the copy
|
|
|
|
* @len: length to copy
|
|
|
|
*
|
|
|
|
* Only atomic text poke/set should be allowed when not doing early patching.
|
|
|
|
* It means the size must be writable atomically and the address must be aligned
|
|
|
|
* in a way that permits an atomic write. It also makes sure we fit on a single
|
|
|
|
* page.
|
|
|
|
*
|
|
|
|
* Context: should only be used by kgdb, which ensures no other core is running,
|
|
|
|
* despite the fact it does not hold the text_mutex.
|
|
|
|
*/
|
|
|
|
void *text_poke_kgdb(void *addr, const void *opcode, size_t len)
|
|
|
|
{
|
2022-05-21 07:57:52 +08:00
|
|
|
return __text_poke(text_poke_memcpy, addr, opcode, len);
|
2019-04-26 08:11:21 +08:00
|
|
|
}
|
|
|
|
|
2022-09-15 19:11:20 +08:00
|
|
|
void *text_poke_copy_locked(void *addr, const void *opcode, size_t len,
|
|
|
|
bool core_ok)
|
2022-02-05 02:57:38 +08:00
|
|
|
{
|
|
|
|
unsigned long start = (unsigned long)addr;
|
|
|
|
size_t patched = 0;
|
|
|
|
|
2022-09-15 19:11:20 +08:00
|
|
|
if (WARN_ON_ONCE(!core_ok && core_kernel_text(start)))
|
2022-02-05 02:57:38 +08:00
|
|
|
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);
|
|
|
|
|
2022-05-21 07:57:52 +08:00
|
|
|
__text_poke(text_poke_memcpy, (void *)ptr, opcode + patched, s);
|
|
|
|
patched += s;
|
|
|
|
}
|
2022-09-15 19:11:20 +08:00
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* text_poke_copy - Copy instructions into (an unused part of) RX memory
|
|
|
|
* @addr: address to modify
|
|
|
|
* @opcode: source of the copy
|
|
|
|
* @len: length to copy, could be more than 2x PAGE_SIZE
|
|
|
|
*
|
|
|
|
* Not safe against concurrent execution; useful for JITs to dump
|
|
|
|
* new code blocks into unused regions of RX memory. Can be used in
|
|
|
|
* conjunction with synchronize_rcu_tasks() to wait for existing
|
|
|
|
* execution to quiesce after having made sure no existing functions
|
|
|
|
* pointers are live.
|
|
|
|
*/
|
|
|
|
void *text_poke_copy(void *addr, const void *opcode, size_t len)
|
|
|
|
{
|
|
|
|
mutex_lock(&text_mutex);
|
|
|
|
addr = text_poke_copy_locked(addr, opcode, len, false);
|
2022-05-21 07:57:52 +08:00
|
|
|
mutex_unlock(&text_mutex);
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* text_poke_set - memset into (an unused part of) RX memory
|
|
|
|
* @addr: address to modify
|
|
|
|
* @c: the byte to fill the area with
|
|
|
|
* @len: length to copy, could be more than 2x PAGE_SIZE
|
|
|
|
*
|
|
|
|
* This is useful to overwrite unused regions of RX memory with illegal
|
|
|
|
* instructions.
|
|
|
|
*/
|
|
|
|
void *text_poke_set(void *addr, int c, size_t len)
|
|
|
|
{
|
|
|
|
unsigned long start = (unsigned long)addr;
|
|
|
|
size_t patched = 0;
|
|
|
|
|
|
|
|
if (WARN_ON_ONCE(core_kernel_text(start)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
mutex_lock(&text_mutex);
|
|
|
|
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(text_poke_memset, (void *)ptr, (void *)&c, s);
|
2022-02-05 02:57:38 +08:00
|
|
|
patched += s;
|
|
|
|
}
|
|
|
|
mutex_unlock(&text_mutex);
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
2013-07-12 17:21:48 +08:00
|
|
|
static void do_sync_core(void *info)
|
|
|
|
{
|
|
|
|
sync_core();
|
|
|
|
}
|
|
|
|
|
x86/kprobes: Fix ordering while text-patching
Kprobes does something like:
register:
arch_arm_kprobe()
text_poke(INT3)
/* guarantees nothing, INT3 will become visible at some point, maybe */
kprobe_optimizer()
/* guarantees the bytes after INT3 are unused */
synchronize_rcu_tasks();
text_poke_bp(JMP32);
/* implies IPI-sync, kprobe really is enabled */
unregister:
__disarm_kprobe()
unoptimize_kprobe()
text_poke_bp(INT3 + tail);
/* implies IPI-sync, so tail is guaranteed visible */
arch_disarm_kprobe()
text_poke(old);
/* guarantees nothing, old will maybe become visible */
synchronize_rcu()
free-stuff
Now the problem is that on register, the synchronize_rcu_tasks() does
not imply sufficient to guarantee all CPUs have already observed INT3
(although in practice this is exceedingly unlikely not to have
happened) (similar to how MEMBARRIER_CMD_PRIVATE_EXPEDITED does not
imply MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE).
Worse, even if it did, we'd have to do 2 synchronize calls to provide
the guarantee we're looking for, the first to ensure INT3 is visible,
the second to guarantee nobody is then still using the instruction
bytes after INT3.
Similar on unregister; the synchronize_rcu() between
__unregister_kprobe_top() and __unregister_kprobe_bottom() does not
guarantee all CPUs are free of the INT3 (and observe the old text).
Therefore, sprinkle some IPI-sync love around. This guarantees that
all CPUs agree on the text and RCU once again provides the required
guaranteed.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132458.162172862@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-10-10 03:15:28 +08:00
|
|
|
void text_poke_sync(void)
|
|
|
|
{
|
|
|
|
on_each_cpu(do_sync_core, NULL, 1);
|
|
|
|
}
|
|
|
|
|
2023-01-24 04:59:17 +08:00
|
|
|
/*
|
|
|
|
* NOTE: crazy scheme to allow patching Jcc.d32 but not increase the size of
|
|
|
|
* this thing. When len == 6 everything is prefixed with 0x0f and we map
|
|
|
|
* opcode to Jcc.d8, using len to distinguish.
|
|
|
|
*/
|
2019-08-26 19:38:58 +08:00
|
|
|
struct text_poke_loc {
|
2021-12-04 21:43:43 +08:00
|
|
|
/* addr := _stext + rel_addr */
|
|
|
|
s32 rel_addr;
|
|
|
|
s32 disp;
|
|
|
|
u8 len;
|
2019-08-26 19:38:58 +08:00
|
|
|
u8 opcode;
|
|
|
|
const u8 text[POKE_MAX_OPCODE_SIZE];
|
2021-12-04 21:43:43 +08:00
|
|
|
/* see text_poke_bp_batch() */
|
2020-05-12 20:19:09 +08:00
|
|
|
u8 old;
|
2019-08-26 19:38:58 +08:00
|
|
|
};
|
|
|
|
|
2019-12-11 08:25:57 +08:00
|
|
|
struct bp_patching_desc {
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
struct text_poke_loc *vec;
|
|
|
|
int nr_entries;
|
2019-12-11 08:25:57 +08:00
|
|
|
atomic_t refs;
|
|
|
|
};
|
|
|
|
|
x86/alternative: Fix race in try_get_desc()
I encountered some occasional crashes of poke_int3_handler() when
kprobes are set, while accessing desc->vec.
The text poke mechanism claims to have an RCU-like behavior, but it
does not appear that there is any quiescent state to ensure that
nobody holds reference to desc. As a result, the following race
appears to be possible, which can lead to memory corruption.
CPU0 CPU1
---- ----
text_poke_bp_batch()
-> smp_store_release(&bp_desc, &desc)
[ notice that desc is on
the stack ]
poke_int3_handler()
[ int3 might be kprobe's
so sync events are do not
help ]
-> try_get_desc(descp=&bp_desc)
desc = __READ_ONCE(bp_desc)
if (!desc) [false, success]
WRITE_ONCE(bp_desc, NULL);
atomic_dec_and_test(&desc.refs)
[ success, desc space on the stack
is being reused and might have
non-zero value. ]
arch_atomic_inc_not_zero(&desc->refs)
[ might succeed since desc points to
stack memory that was freed and might
be reused. ]
Fix this issue with small backportable patch. Instead of trying to
make RCU-like behavior for bp_desc, just eliminate the unnecessary
level of indirection of bp_desc, and hold the whole descriptor as a
global. Anyhow, there is only a single descriptor at any given
moment.
Fixes: 1f676247f36a4 ("x86/alternatives: Implement a better poke_int3_handler() completion scheme")
Signed-off-by: Nadav Amit <namit@vmware.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@kernel.org
Link: https://lkml.kernel.org/r/20220920224743.3089-1-namit@vmware.com
2022-09-22 02:09:32 +08:00
|
|
|
static struct bp_patching_desc bp_desc;
|
2019-12-11 08:25:57 +08:00
|
|
|
|
2020-01-21 22:53:09 +08:00
|
|
|
static __always_inline
|
x86/alternative: Fix race in try_get_desc()
I encountered some occasional crashes of poke_int3_handler() when
kprobes are set, while accessing desc->vec.
The text poke mechanism claims to have an RCU-like behavior, but it
does not appear that there is any quiescent state to ensure that
nobody holds reference to desc. As a result, the following race
appears to be possible, which can lead to memory corruption.
CPU0 CPU1
---- ----
text_poke_bp_batch()
-> smp_store_release(&bp_desc, &desc)
[ notice that desc is on
the stack ]
poke_int3_handler()
[ int3 might be kprobe's
so sync events are do not
help ]
-> try_get_desc(descp=&bp_desc)
desc = __READ_ONCE(bp_desc)
if (!desc) [false, success]
WRITE_ONCE(bp_desc, NULL);
atomic_dec_and_test(&desc.refs)
[ success, desc space on the stack
is being reused and might have
non-zero value. ]
arch_atomic_inc_not_zero(&desc->refs)
[ might succeed since desc points to
stack memory that was freed and might
be reused. ]
Fix this issue with small backportable patch. Instead of trying to
make RCU-like behavior for bp_desc, just eliminate the unnecessary
level of indirection of bp_desc, and hold the whole descriptor as a
global. Anyhow, there is only a single descriptor at any given
moment.
Fixes: 1f676247f36a4 ("x86/alternatives: Implement a better poke_int3_handler() completion scheme")
Signed-off-by: Nadav Amit <namit@vmware.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@kernel.org
Link: https://lkml.kernel.org/r/20220920224743.3089-1-namit@vmware.com
2022-09-22 02:09:32 +08:00
|
|
|
struct bp_patching_desc *try_get_desc(void)
|
2019-12-11 08:25:57 +08:00
|
|
|
{
|
x86/alternative: Fix race in try_get_desc()
I encountered some occasional crashes of poke_int3_handler() when
kprobes are set, while accessing desc->vec.
The text poke mechanism claims to have an RCU-like behavior, but it
does not appear that there is any quiescent state to ensure that
nobody holds reference to desc. As a result, the following race
appears to be possible, which can lead to memory corruption.
CPU0 CPU1
---- ----
text_poke_bp_batch()
-> smp_store_release(&bp_desc, &desc)
[ notice that desc is on
the stack ]
poke_int3_handler()
[ int3 might be kprobe's
so sync events are do not
help ]
-> try_get_desc(descp=&bp_desc)
desc = __READ_ONCE(bp_desc)
if (!desc) [false, success]
WRITE_ONCE(bp_desc, NULL);
atomic_dec_and_test(&desc.refs)
[ success, desc space on the stack
is being reused and might have
non-zero value. ]
arch_atomic_inc_not_zero(&desc->refs)
[ might succeed since desc points to
stack memory that was freed and might
be reused. ]
Fix this issue with small backportable patch. Instead of trying to
make RCU-like behavior for bp_desc, just eliminate the unnecessary
level of indirection of bp_desc, and hold the whole descriptor as a
global. Anyhow, there is only a single descriptor at any given
moment.
Fixes: 1f676247f36a4 ("x86/alternatives: Implement a better poke_int3_handler() completion scheme")
Signed-off-by: Nadav Amit <namit@vmware.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@kernel.org
Link: https://lkml.kernel.org/r/20220920224743.3089-1-namit@vmware.com
2022-09-22 02:09:32 +08:00
|
|
|
struct bp_patching_desc *desc = &bp_desc;
|
2019-12-11 08:25:57 +08:00
|
|
|
|
2023-06-05 15:01:15 +08:00
|
|
|
if (!raw_atomic_inc_not_zero(&desc->refs))
|
2019-12-11 08:25:57 +08:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return desc;
|
|
|
|
}
|
|
|
|
|
x86/alternative: Fix race in try_get_desc()
I encountered some occasional crashes of poke_int3_handler() when
kprobes are set, while accessing desc->vec.
The text poke mechanism claims to have an RCU-like behavior, but it
does not appear that there is any quiescent state to ensure that
nobody holds reference to desc. As a result, the following race
appears to be possible, which can lead to memory corruption.
CPU0 CPU1
---- ----
text_poke_bp_batch()
-> smp_store_release(&bp_desc, &desc)
[ notice that desc is on
the stack ]
poke_int3_handler()
[ int3 might be kprobe's
so sync events are do not
help ]
-> try_get_desc(descp=&bp_desc)
desc = __READ_ONCE(bp_desc)
if (!desc) [false, success]
WRITE_ONCE(bp_desc, NULL);
atomic_dec_and_test(&desc.refs)
[ success, desc space on the stack
is being reused and might have
non-zero value. ]
arch_atomic_inc_not_zero(&desc->refs)
[ might succeed since desc points to
stack memory that was freed and might
be reused. ]
Fix this issue with small backportable patch. Instead of trying to
make RCU-like behavior for bp_desc, just eliminate the unnecessary
level of indirection of bp_desc, and hold the whole descriptor as a
global. Anyhow, there is only a single descriptor at any given
moment.
Fixes: 1f676247f36a4 ("x86/alternatives: Implement a better poke_int3_handler() completion scheme")
Signed-off-by: Nadav Amit <namit@vmware.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@kernel.org
Link: https://lkml.kernel.org/r/20220920224743.3089-1-namit@vmware.com
2022-09-22 02:09:32 +08:00
|
|
|
static __always_inline void put_desc(void)
|
2019-12-11 08:25:57 +08:00
|
|
|
{
|
x86/alternative: Fix race in try_get_desc()
I encountered some occasional crashes of poke_int3_handler() when
kprobes are set, while accessing desc->vec.
The text poke mechanism claims to have an RCU-like behavior, but it
does not appear that there is any quiescent state to ensure that
nobody holds reference to desc. As a result, the following race
appears to be possible, which can lead to memory corruption.
CPU0 CPU1
---- ----
text_poke_bp_batch()
-> smp_store_release(&bp_desc, &desc)
[ notice that desc is on
the stack ]
poke_int3_handler()
[ int3 might be kprobe's
so sync events are do not
help ]
-> try_get_desc(descp=&bp_desc)
desc = __READ_ONCE(bp_desc)
if (!desc) [false, success]
WRITE_ONCE(bp_desc, NULL);
atomic_dec_and_test(&desc.refs)
[ success, desc space on the stack
is being reused and might have
non-zero value. ]
arch_atomic_inc_not_zero(&desc->refs)
[ might succeed since desc points to
stack memory that was freed and might
be reused. ]
Fix this issue with small backportable patch. Instead of trying to
make RCU-like behavior for bp_desc, just eliminate the unnecessary
level of indirection of bp_desc, and hold the whole descriptor as a
global. Anyhow, there is only a single descriptor at any given
moment.
Fixes: 1f676247f36a4 ("x86/alternatives: Implement a better poke_int3_handler() completion scheme")
Signed-off-by: Nadav Amit <namit@vmware.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@kernel.org
Link: https://lkml.kernel.org/r/20220920224743.3089-1-namit@vmware.com
2022-09-22 02:09:32 +08:00
|
|
|
struct bp_patching_desc *desc = &bp_desc;
|
|
|
|
|
2019-12-11 08:25:57 +08:00
|
|
|
smp_mb__before_atomic();
|
2023-06-05 15:01:15 +08:00
|
|
|
raw_atomic_dec(&desc->refs);
|
2019-12-11 08:25:57 +08:00
|
|
|
}
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
|
2020-01-21 22:53:09 +08:00
|
|
|
static __always_inline void *text_poke_addr(struct text_poke_loc *tp)
|
2019-10-09 18:26:53 +08:00
|
|
|
{
|
|
|
|
return _stext + tp->rel_addr;
|
|
|
|
}
|
|
|
|
|
2020-02-20 20:28:06 +08:00
|
|
|
static __always_inline int patch_cmp(const void *key, const void *elt)
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
{
|
|
|
|
struct text_poke_loc *tp = (struct text_poke_loc *) elt;
|
|
|
|
|
2019-10-09 18:26:53 +08:00
|
|
|
if (key < text_poke_addr(tp))
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
return -1;
|
2019-10-09 18:26:53 +08:00
|
|
|
if (key > text_poke_addr(tp))
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
2013-07-12 17:21:48 +08:00
|
|
|
|
2020-07-24 00:14:05 +08:00
|
|
|
noinstr int poke_int3_handler(struct pt_regs *regs)
|
2013-07-12 17:21:48 +08:00
|
|
|
{
|
2019-12-11 08:25:57 +08:00
|
|
|
struct bp_patching_desc *desc;
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
struct text_poke_loc *tp;
|
2021-12-04 21:43:43 +08:00
|
|
|
int ret = 0;
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
void *ip;
|
2019-12-11 08:25:57 +08:00
|
|
|
|
|
|
|
if (user_mode(regs))
|
|
|
|
return 0;
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
|
2017-07-31 18:21:54 +08:00
|
|
|
/*
|
|
|
|
* Having observed our INT3 instruction, we now must observe
|
x86/alternative: Fix race in try_get_desc()
I encountered some occasional crashes of poke_int3_handler() when
kprobes are set, while accessing desc->vec.
The text poke mechanism claims to have an RCU-like behavior, but it
does not appear that there is any quiescent state to ensure that
nobody holds reference to desc. As a result, the following race
appears to be possible, which can lead to memory corruption.
CPU0 CPU1
---- ----
text_poke_bp_batch()
-> smp_store_release(&bp_desc, &desc)
[ notice that desc is on
the stack ]
poke_int3_handler()
[ int3 might be kprobe's
so sync events are do not
help ]
-> try_get_desc(descp=&bp_desc)
desc = __READ_ONCE(bp_desc)
if (!desc) [false, success]
WRITE_ONCE(bp_desc, NULL);
atomic_dec_and_test(&desc.refs)
[ success, desc space on the stack
is being reused and might have
non-zero value. ]
arch_atomic_inc_not_zero(&desc->refs)
[ might succeed since desc points to
stack memory that was freed and might
be reused. ]
Fix this issue with small backportable patch. Instead of trying to
make RCU-like behavior for bp_desc, just eliminate the unnecessary
level of indirection of bp_desc, and hold the whole descriptor as a
global. Anyhow, there is only a single descriptor at any given
moment.
Fixes: 1f676247f36a4 ("x86/alternatives: Implement a better poke_int3_handler() completion scheme")
Signed-off-by: Nadav Amit <namit@vmware.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@kernel.org
Link: https://lkml.kernel.org/r/20220920224743.3089-1-namit@vmware.com
2022-09-22 02:09:32 +08:00
|
|
|
* bp_desc with non-zero refcount:
|
2017-07-31 18:21:54 +08:00
|
|
|
*
|
x86/alternative: Fix race in try_get_desc()
I encountered some occasional crashes of poke_int3_handler() when
kprobes are set, while accessing desc->vec.
The text poke mechanism claims to have an RCU-like behavior, but it
does not appear that there is any quiescent state to ensure that
nobody holds reference to desc. As a result, the following race
appears to be possible, which can lead to memory corruption.
CPU0 CPU1
---- ----
text_poke_bp_batch()
-> smp_store_release(&bp_desc, &desc)
[ notice that desc is on
the stack ]
poke_int3_handler()
[ int3 might be kprobe's
so sync events are do not
help ]
-> try_get_desc(descp=&bp_desc)
desc = __READ_ONCE(bp_desc)
if (!desc) [false, success]
WRITE_ONCE(bp_desc, NULL);
atomic_dec_and_test(&desc.refs)
[ success, desc space on the stack
is being reused and might have
non-zero value. ]
arch_atomic_inc_not_zero(&desc->refs)
[ might succeed since desc points to
stack memory that was freed and might
be reused. ]
Fix this issue with small backportable patch. Instead of trying to
make RCU-like behavior for bp_desc, just eliminate the unnecessary
level of indirection of bp_desc, and hold the whole descriptor as a
global. Anyhow, there is only a single descriptor at any given
moment.
Fixes: 1f676247f36a4 ("x86/alternatives: Implement a better poke_int3_handler() completion scheme")
Signed-off-by: Nadav Amit <namit@vmware.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@kernel.org
Link: https://lkml.kernel.org/r/20220920224743.3089-1-namit@vmware.com
2022-09-22 02:09:32 +08:00
|
|
|
* bp_desc.refs = 1 INT3
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
* WMB RMB
|
x86/alternative: Fix race in try_get_desc()
I encountered some occasional crashes of poke_int3_handler() when
kprobes are set, while accessing desc->vec.
The text poke mechanism claims to have an RCU-like behavior, but it
does not appear that there is any quiescent state to ensure that
nobody holds reference to desc. As a result, the following race
appears to be possible, which can lead to memory corruption.
CPU0 CPU1
---- ----
text_poke_bp_batch()
-> smp_store_release(&bp_desc, &desc)
[ notice that desc is on
the stack ]
poke_int3_handler()
[ int3 might be kprobe's
so sync events are do not
help ]
-> try_get_desc(descp=&bp_desc)
desc = __READ_ONCE(bp_desc)
if (!desc) [false, success]
WRITE_ONCE(bp_desc, NULL);
atomic_dec_and_test(&desc.refs)
[ success, desc space on the stack
is being reused and might have
non-zero value. ]
arch_atomic_inc_not_zero(&desc->refs)
[ might succeed since desc points to
stack memory that was freed and might
be reused. ]
Fix this issue with small backportable patch. Instead of trying to
make RCU-like behavior for bp_desc, just eliminate the unnecessary
level of indirection of bp_desc, and hold the whole descriptor as a
global. Anyhow, there is only a single descriptor at any given
moment.
Fixes: 1f676247f36a4 ("x86/alternatives: Implement a better poke_int3_handler() completion scheme")
Signed-off-by: Nadav Amit <namit@vmware.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@kernel.org
Link: https://lkml.kernel.org/r/20220920224743.3089-1-namit@vmware.com
2022-09-22 02:09:32 +08:00
|
|
|
* write INT3 if (bp_desc.refs != 0)
|
2017-07-31 18:21:54 +08:00
|
|
|
*/
|
2013-07-12 17:21:48 +08:00
|
|
|
smp_rmb();
|
|
|
|
|
x86/alternative: Fix race in try_get_desc()
I encountered some occasional crashes of poke_int3_handler() when
kprobes are set, while accessing desc->vec.
The text poke mechanism claims to have an RCU-like behavior, but it
does not appear that there is any quiescent state to ensure that
nobody holds reference to desc. As a result, the following race
appears to be possible, which can lead to memory corruption.
CPU0 CPU1
---- ----
text_poke_bp_batch()
-> smp_store_release(&bp_desc, &desc)
[ notice that desc is on
the stack ]
poke_int3_handler()
[ int3 might be kprobe's
so sync events are do not
help ]
-> try_get_desc(descp=&bp_desc)
desc = __READ_ONCE(bp_desc)
if (!desc) [false, success]
WRITE_ONCE(bp_desc, NULL);
atomic_dec_and_test(&desc.refs)
[ success, desc space on the stack
is being reused and might have
non-zero value. ]
arch_atomic_inc_not_zero(&desc->refs)
[ might succeed since desc points to
stack memory that was freed and might
be reused. ]
Fix this issue with small backportable patch. Instead of trying to
make RCU-like behavior for bp_desc, just eliminate the unnecessary
level of indirection of bp_desc, and hold the whole descriptor as a
global. Anyhow, there is only a single descriptor at any given
moment.
Fixes: 1f676247f36a4 ("x86/alternatives: Implement a better poke_int3_handler() completion scheme")
Signed-off-by: Nadav Amit <namit@vmware.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@kernel.org
Link: https://lkml.kernel.org/r/20220920224743.3089-1-namit@vmware.com
2022-09-22 02:09:32 +08:00
|
|
|
desc = try_get_desc();
|
2019-12-11 08:25:57 +08:00
|
|
|
if (!desc)
|
2013-07-23 16:09:28 +08:00
|
|
|
return 0;
|
2013-07-12 17:21:48 +08:00
|
|
|
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
/*
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
* Discount the INT3. See text_poke_bp_batch().
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
*/
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
ip = (void *) regs->ip - INT3_INSN_SIZE;
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Skip the binary search if there is a single member in the vector.
|
|
|
|
*/
|
2019-12-11 08:25:57 +08:00
|
|
|
if (unlikely(desc->nr_entries > 1)) {
|
2020-02-20 20:28:06 +08:00
|
|
|
tp = __inline_bsearch(ip, desc->vec, desc->nr_entries,
|
|
|
|
sizeof(struct text_poke_loc),
|
|
|
|
patch_cmp);
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
if (!tp)
|
2019-12-11 08:25:57 +08:00
|
|
|
goto out_put;
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
} else {
|
2019-12-11 08:25:57 +08:00
|
|
|
tp = desc->vec;
|
2019-10-09 18:26:53 +08:00
|
|
|
if (text_poke_addr(tp) != ip)
|
2019-12-11 08:25:57 +08:00
|
|
|
goto out_put;
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
}
|
|
|
|
|
2021-12-04 21:43:43 +08:00
|
|
|
ip += tp->len;
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
|
|
|
|
switch (tp->opcode) {
|
|
|
|
case INT3_INSN_OPCODE:
|
|
|
|
/*
|
|
|
|
* Someone poked an explicit INT3, they'll want to handle it,
|
|
|
|
* do not consume.
|
|
|
|
*/
|
2019-12-11 08:25:57 +08:00
|
|
|
goto out_put;
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
|
2020-08-18 21:57:47 +08:00
|
|
|
case RET_INSN_OPCODE:
|
|
|
|
int3_emulate_ret(regs);
|
|
|
|
break;
|
|
|
|
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
case CALL_INSN_OPCODE:
|
2021-12-04 21:43:43 +08:00
|
|
|
int3_emulate_call(regs, (long)ip + tp->disp);
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case JMP32_INSN_OPCODE:
|
|
|
|
case JMP8_INSN_OPCODE:
|
2021-12-04 21:43:43 +08:00
|
|
|
int3_emulate_jmp(regs, (long)ip + tp->disp);
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
break;
|
|
|
|
|
2023-01-24 04:59:17 +08:00
|
|
|
case 0x70 ... 0x7f: /* Jcc */
|
|
|
|
int3_emulate_jcc(regs, tp->opcode & 0xf, (long)ip, tp->disp);
|
|
|
|
break;
|
|
|
|
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
default:
|
|
|
|
BUG();
|
|
|
|
}
|
2013-07-23 16:09:28 +08:00
|
|
|
|
2019-12-11 08:25:57 +08:00
|
|
|
ret = 1;
|
|
|
|
|
|
|
|
out_put:
|
x86/alternative: Fix race in try_get_desc()
I encountered some occasional crashes of poke_int3_handler() when
kprobes are set, while accessing desc->vec.
The text poke mechanism claims to have an RCU-like behavior, but it
does not appear that there is any quiescent state to ensure that
nobody holds reference to desc. As a result, the following race
appears to be possible, which can lead to memory corruption.
CPU0 CPU1
---- ----
text_poke_bp_batch()
-> smp_store_release(&bp_desc, &desc)
[ notice that desc is on
the stack ]
poke_int3_handler()
[ int3 might be kprobe's
so sync events are do not
help ]
-> try_get_desc(descp=&bp_desc)
desc = __READ_ONCE(bp_desc)
if (!desc) [false, success]
WRITE_ONCE(bp_desc, NULL);
atomic_dec_and_test(&desc.refs)
[ success, desc space on the stack
is being reused and might have
non-zero value. ]
arch_atomic_inc_not_zero(&desc->refs)
[ might succeed since desc points to
stack memory that was freed and might
be reused. ]
Fix this issue with small backportable patch. Instead of trying to
make RCU-like behavior for bp_desc, just eliminate the unnecessary
level of indirection of bp_desc, and hold the whole descriptor as a
global. Anyhow, there is only a single descriptor at any given
moment.
Fixes: 1f676247f36a4 ("x86/alternatives: Implement a better poke_int3_handler() completion scheme")
Signed-off-by: Nadav Amit <namit@vmware.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@kernel.org
Link: https://lkml.kernel.org/r/20220920224743.3089-1-namit@vmware.com
2022-09-22 02:09:32 +08:00
|
|
|
put_desc();
|
2019-12-11 08:25:57 +08:00
|
|
|
return ret;
|
2013-07-12 17:21:48 +08:00
|
|
|
}
|
2013-07-23 16:09:28 +08:00
|
|
|
|
2019-08-26 19:38:58 +08:00
|
|
|
#define TP_VEC_MAX (PAGE_SIZE / sizeof(struct text_poke_loc))
|
|
|
|
static struct text_poke_loc tp_vec[TP_VEC_MAX];
|
|
|
|
static int tp_vec_nr;
|
|
|
|
|
2013-07-12 17:21:48 +08:00
|
|
|
/**
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
* text_poke_bp_batch() -- update instructions on live kernel on SMP
|
|
|
|
* @tp: vector of instructions to patch
|
|
|
|
* @nr_entries: number of entries in the vector
|
2013-07-12 17:21:48 +08:00
|
|
|
*
|
|
|
|
* Modify multi-byte instruction by using int3 breakpoint on SMP.
|
2013-07-18 19:47:53 +08:00
|
|
|
* We completely avoid stop_machine() here, and achieve the
|
|
|
|
* synchronization using int3 breakpoint.
|
2013-07-12 17:21:48 +08:00
|
|
|
*
|
|
|
|
* The way it is done:
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
* - For each entry in the vector:
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
* - add a int3 trap to the address that will be patched
|
2013-07-12 17:21:48 +08:00
|
|
|
* - sync cores
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
* - For each entry in the vector:
|
|
|
|
* - update all but the first byte of the patched range
|
2013-07-12 17:21:48 +08:00
|
|
|
* - sync cores
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
* - For each entry in the vector:
|
|
|
|
* - replace the first byte (int3) by the first byte of
|
|
|
|
* replacing opcode
|
2013-07-12 17:21:48 +08:00
|
|
|
* - sync cores
|
|
|
|
*/
|
2019-08-26 19:38:58 +08:00
|
|
|
static void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries)
|
2013-07-12 17:21:48 +08:00
|
|
|
{
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
unsigned char int3 = INT3_INSN_OPCODE;
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
unsigned int i;
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
int do_sync;
|
2018-08-28 14:55:14 +08:00
|
|
|
|
|
|
|
lockdep_assert_held(&text_mutex);
|
|
|
|
|
x86/alternative: Fix race in try_get_desc()
I encountered some occasional crashes of poke_int3_handler() when
kprobes are set, while accessing desc->vec.
The text poke mechanism claims to have an RCU-like behavior, but it
does not appear that there is any quiescent state to ensure that
nobody holds reference to desc. As a result, the following race
appears to be possible, which can lead to memory corruption.
CPU0 CPU1
---- ----
text_poke_bp_batch()
-> smp_store_release(&bp_desc, &desc)
[ notice that desc is on
the stack ]
poke_int3_handler()
[ int3 might be kprobe's
so sync events are do not
help ]
-> try_get_desc(descp=&bp_desc)
desc = __READ_ONCE(bp_desc)
if (!desc) [false, success]
WRITE_ONCE(bp_desc, NULL);
atomic_dec_and_test(&desc.refs)
[ success, desc space on the stack
is being reused and might have
non-zero value. ]
arch_atomic_inc_not_zero(&desc->refs)
[ might succeed since desc points to
stack memory that was freed and might
be reused. ]
Fix this issue with small backportable patch. Instead of trying to
make RCU-like behavior for bp_desc, just eliminate the unnecessary
level of indirection of bp_desc, and hold the whole descriptor as a
global. Anyhow, there is only a single descriptor at any given
moment.
Fixes: 1f676247f36a4 ("x86/alternatives: Implement a better poke_int3_handler() completion scheme")
Signed-off-by: Nadav Amit <namit@vmware.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@kernel.org
Link: https://lkml.kernel.org/r/20220920224743.3089-1-namit@vmware.com
2022-09-22 02:09:32 +08:00
|
|
|
bp_desc.vec = tp;
|
|
|
|
bp_desc.nr_entries = nr_entries;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Corresponds to the implicit memory barrier in try_get_desc() to
|
|
|
|
* ensure reading a non-zero refcount provides up to date bp_desc data.
|
|
|
|
*/
|
|
|
|
atomic_set_release(&bp_desc.refs, 1);
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
|
2023-05-31 21:24:19 +08:00
|
|
|
/*
|
|
|
|
* Function tracing can enable thousands of places that need to be
|
|
|
|
* updated. This can take quite some time, and with full kernel debugging
|
|
|
|
* enabled, this could cause the softlockup watchdog to trigger.
|
|
|
|
* This function gets called every 256 entries added to be patched.
|
|
|
|
* Call cond_resched() here to make sure that other tasks can get scheduled
|
|
|
|
* while processing all the functions being patched.
|
|
|
|
*/
|
|
|
|
cond_resched();
|
|
|
|
|
2013-07-12 17:21:48 +08:00
|
|
|
/*
|
2017-07-31 18:21:54 +08:00
|
|
|
* Corresponding read barrier in int3 notifier for making sure the
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
* nr_entries and handler are correctly ordered wrt. patching.
|
2013-07-12 17:21:48 +08:00
|
|
|
*/
|
|
|
|
smp_wmb();
|
|
|
|
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
/*
|
|
|
|
* First step: add a int3 trap to the address that will be patched.
|
|
|
|
*/
|
2020-05-12 20:19:09 +08:00
|
|
|
for (i = 0; i < nr_entries; i++) {
|
|
|
|
tp[i].old = *(u8 *)text_poke_addr(&tp[i]);
|
2019-11-11 21:08:26 +08:00
|
|
|
text_poke(text_poke_addr(&tp[i]), &int3, INT3_INSN_SIZE);
|
2020-05-12 20:19:09 +08:00
|
|
|
}
|
2013-07-12 17:21:48 +08:00
|
|
|
|
x86/kprobes: Fix ordering while text-patching
Kprobes does something like:
register:
arch_arm_kprobe()
text_poke(INT3)
/* guarantees nothing, INT3 will become visible at some point, maybe */
kprobe_optimizer()
/* guarantees the bytes after INT3 are unused */
synchronize_rcu_tasks();
text_poke_bp(JMP32);
/* implies IPI-sync, kprobe really is enabled */
unregister:
__disarm_kprobe()
unoptimize_kprobe()
text_poke_bp(INT3 + tail);
/* implies IPI-sync, so tail is guaranteed visible */
arch_disarm_kprobe()
text_poke(old);
/* guarantees nothing, old will maybe become visible */
synchronize_rcu()
free-stuff
Now the problem is that on register, the synchronize_rcu_tasks() does
not imply sufficient to guarantee all CPUs have already observed INT3
(although in practice this is exceedingly unlikely not to have
happened) (similar to how MEMBARRIER_CMD_PRIVATE_EXPEDITED does not
imply MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE).
Worse, even if it did, we'd have to do 2 synchronize calls to provide
the guarantee we're looking for, the first to ensure INT3 is visible,
the second to guarantee nobody is then still using the instruction
bytes after INT3.
Similar on unregister; the synchronize_rcu() between
__unregister_kprobe_top() and __unregister_kprobe_bottom() does not
guarantee all CPUs are free of the INT3 (and observe the old text).
Therefore, sprinkle some IPI-sync love around. This guarantees that
all CPUs agree on the text and RCU once again provides the required
guaranteed.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132458.162172862@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-10-10 03:15:28 +08:00
|
|
|
text_poke_sync();
|
2013-07-12 17:21:48 +08:00
|
|
|
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
/*
|
|
|
|
* Second step: update all but the first byte of the patched range.
|
|
|
|
*/
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
for (do_sync = 0, i = 0; i < nr_entries; i++) {
|
2023-01-24 04:59:17 +08:00
|
|
|
u8 old[POKE_MAX_OPCODE_SIZE+1] = { tp[i].old, };
|
|
|
|
u8 _new[POKE_MAX_OPCODE_SIZE+1];
|
|
|
|
const u8 *new = tp[i].text;
|
2021-12-04 21:43:43 +08:00
|
|
|
int len = tp[i].len;
|
2019-10-09 18:44:20 +08:00
|
|
|
|
2019-11-11 21:08:26 +08:00
|
|
|
if (len - INT3_INSN_SIZE > 0) {
|
2020-05-12 20:19:09 +08:00
|
|
|
memcpy(old + INT3_INSN_SIZE,
|
|
|
|
text_poke_addr(&tp[i]) + INT3_INSN_SIZE,
|
|
|
|
len - INT3_INSN_SIZE);
|
2023-01-24 04:59:17 +08:00
|
|
|
|
|
|
|
if (len == 6) {
|
|
|
|
_new[0] = 0x0f;
|
|
|
|
memcpy(_new + 1, new, 5);
|
|
|
|
new = _new;
|
|
|
|
}
|
|
|
|
|
2019-11-11 21:08:26 +08:00
|
|
|
text_poke(text_poke_addr(&tp[i]) + INT3_INSN_SIZE,
|
2023-01-24 04:59:17 +08:00
|
|
|
new + INT3_INSN_SIZE,
|
2019-11-11 21:08:26 +08:00
|
|
|
len - INT3_INSN_SIZE);
|
2023-01-24 04:59:17 +08:00
|
|
|
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
do_sync++;
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
}
|
2020-05-12 20:19:09 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Emit a perf event to record the text poke, primarily to
|
|
|
|
* support Intel PT decoding which must walk the executable code
|
|
|
|
* to reconstruct the trace. The flow up to here is:
|
|
|
|
* - write INT3 byte
|
|
|
|
* - IPI-SYNC
|
|
|
|
* - write instruction tail
|
|
|
|
* At this point the actual control flow will be through the
|
|
|
|
* INT3 and handler and not hit the old or new instruction.
|
|
|
|
* Intel PT outputs FUP/TIP packets for the INT3, so the flow
|
|
|
|
* can still be decoded. Subsequently:
|
|
|
|
* - emit RECORD_TEXT_POKE with the new instruction
|
|
|
|
* - IPI-SYNC
|
|
|
|
* - write first byte
|
|
|
|
* - IPI-SYNC
|
|
|
|
* So before the text poke event timestamp, the decoder will see
|
|
|
|
* either the old instruction flow or FUP/TIP of INT3. After the
|
|
|
|
* text poke event timestamp, the decoder will see either the
|
|
|
|
* new instruction flow or FUP/TIP of INT3. Thus decoders can
|
|
|
|
* use the timestamp as the point at which to modify the
|
|
|
|
* executable code.
|
|
|
|
* The old instruction is recorded so that the event can be
|
|
|
|
* processed forwards or backwards.
|
|
|
|
*/
|
2023-01-24 04:59:17 +08:00
|
|
|
perf_event_text_poke(text_poke_addr(&tp[i]), old, len, new, len);
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
}
|
|
|
|
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
if (do_sync) {
|
2013-07-12 17:21:48 +08:00
|
|
|
/*
|
|
|
|
* According to Intel, this core syncing is very likely
|
|
|
|
* not necessary and we'd be safe even without it. But
|
|
|
|
* better safe than sorry (plus there's not only Intel).
|
|
|
|
*/
|
x86/kprobes: Fix ordering while text-patching
Kprobes does something like:
register:
arch_arm_kprobe()
text_poke(INT3)
/* guarantees nothing, INT3 will become visible at some point, maybe */
kprobe_optimizer()
/* guarantees the bytes after INT3 are unused */
synchronize_rcu_tasks();
text_poke_bp(JMP32);
/* implies IPI-sync, kprobe really is enabled */
unregister:
__disarm_kprobe()
unoptimize_kprobe()
text_poke_bp(INT3 + tail);
/* implies IPI-sync, so tail is guaranteed visible */
arch_disarm_kprobe()
text_poke(old);
/* guarantees nothing, old will maybe become visible */
synchronize_rcu()
free-stuff
Now the problem is that on register, the synchronize_rcu_tasks() does
not imply sufficient to guarantee all CPUs have already observed INT3
(although in practice this is exceedingly unlikely not to have
happened) (similar to how MEMBARRIER_CMD_PRIVATE_EXPEDITED does not
imply MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE).
Worse, even if it did, we'd have to do 2 synchronize calls to provide
the guarantee we're looking for, the first to ensure INT3 is visible,
the second to guarantee nobody is then still using the instruction
bytes after INT3.
Similar on unregister; the synchronize_rcu() between
__unregister_kprobe_top() and __unregister_kprobe_bottom() does not
guarantee all CPUs are free of the INT3 (and observe the old text).
Therefore, sprinkle some IPI-sync love around. This guarantees that
all CPUs agree on the text and RCU once again provides the required
guaranteed.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132458.162172862@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-10-10 03:15:28 +08:00
|
|
|
text_poke_sync();
|
2013-07-12 17:21:48 +08:00
|
|
|
}
|
|
|
|
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
/*
|
|
|
|
* Third step: replace the first byte (int3) by the first byte of
|
|
|
|
* replacing opcode.
|
|
|
|
*/
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
for (do_sync = 0, i = 0; i < nr_entries; i++) {
|
2023-01-24 04:59:17 +08:00
|
|
|
u8 byte = tp[i].text[0];
|
|
|
|
|
|
|
|
if (tp[i].len == 6)
|
|
|
|
byte = 0x0f;
|
|
|
|
|
|
|
|
if (byte == INT3_INSN_OPCODE)
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
continue;
|
|
|
|
|
2023-01-24 04:59:17 +08:00
|
|
|
text_poke(text_poke_addr(&tp[i]), &byte, INT3_INSN_SIZE);
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
do_sync++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (do_sync)
|
x86/kprobes: Fix ordering while text-patching
Kprobes does something like:
register:
arch_arm_kprobe()
text_poke(INT3)
/* guarantees nothing, INT3 will become visible at some point, maybe */
kprobe_optimizer()
/* guarantees the bytes after INT3 are unused */
synchronize_rcu_tasks();
text_poke_bp(JMP32);
/* implies IPI-sync, kprobe really is enabled */
unregister:
__disarm_kprobe()
unoptimize_kprobe()
text_poke_bp(INT3 + tail);
/* implies IPI-sync, so tail is guaranteed visible */
arch_disarm_kprobe()
text_poke(old);
/* guarantees nothing, old will maybe become visible */
synchronize_rcu()
free-stuff
Now the problem is that on register, the synchronize_rcu_tasks() does
not imply sufficient to guarantee all CPUs have already observed INT3
(although in practice this is exceedingly unlikely not to have
happened) (similar to how MEMBARRIER_CMD_PRIVATE_EXPEDITED does not
imply MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE).
Worse, even if it did, we'd have to do 2 synchronize calls to provide
the guarantee we're looking for, the first to ensure INT3 is visible,
the second to guarantee nobody is then still using the instruction
bytes after INT3.
Similar on unregister; the synchronize_rcu() between
__unregister_kprobe_top() and __unregister_kprobe_bottom() does not
guarantee all CPUs are free of the INT3 (and observe the old text).
Therefore, sprinkle some IPI-sync love around. This guarantees that
all CPUs agree on the text and RCU once again provides the required
guaranteed.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132458.162172862@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-10-10 03:15:28 +08:00
|
|
|
text_poke_sync();
|
2013-07-12 17:21:48 +08:00
|
|
|
|
2017-07-31 18:21:54 +08:00
|
|
|
/*
|
x86/alternative: Fix race in try_get_desc()
I encountered some occasional crashes of poke_int3_handler() when
kprobes are set, while accessing desc->vec.
The text poke mechanism claims to have an RCU-like behavior, but it
does not appear that there is any quiescent state to ensure that
nobody holds reference to desc. As a result, the following race
appears to be possible, which can lead to memory corruption.
CPU0 CPU1
---- ----
text_poke_bp_batch()
-> smp_store_release(&bp_desc, &desc)
[ notice that desc is on
the stack ]
poke_int3_handler()
[ int3 might be kprobe's
so sync events are do not
help ]
-> try_get_desc(descp=&bp_desc)
desc = __READ_ONCE(bp_desc)
if (!desc) [false, success]
WRITE_ONCE(bp_desc, NULL);
atomic_dec_and_test(&desc.refs)
[ success, desc space on the stack
is being reused and might have
non-zero value. ]
arch_atomic_inc_not_zero(&desc->refs)
[ might succeed since desc points to
stack memory that was freed and might
be reused. ]
Fix this issue with small backportable patch. Instead of trying to
make RCU-like behavior for bp_desc, just eliminate the unnecessary
level of indirection of bp_desc, and hold the whole descriptor as a
global. Anyhow, there is only a single descriptor at any given
moment.
Fixes: 1f676247f36a4 ("x86/alternatives: Implement a better poke_int3_handler() completion scheme")
Signed-off-by: Nadav Amit <namit@vmware.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@kernel.org
Link: https://lkml.kernel.org/r/20220920224743.3089-1-namit@vmware.com
2022-09-22 02:09:32 +08:00
|
|
|
* Remove and wait for refs to be zero.
|
2017-07-31 18:21:54 +08:00
|
|
|
*/
|
x86/alternative: Fix race in try_get_desc()
I encountered some occasional crashes of poke_int3_handler() when
kprobes are set, while accessing desc->vec.
The text poke mechanism claims to have an RCU-like behavior, but it
does not appear that there is any quiescent state to ensure that
nobody holds reference to desc. As a result, the following race
appears to be possible, which can lead to memory corruption.
CPU0 CPU1
---- ----
text_poke_bp_batch()
-> smp_store_release(&bp_desc, &desc)
[ notice that desc is on
the stack ]
poke_int3_handler()
[ int3 might be kprobe's
so sync events are do not
help ]
-> try_get_desc(descp=&bp_desc)
desc = __READ_ONCE(bp_desc)
if (!desc) [false, success]
WRITE_ONCE(bp_desc, NULL);
atomic_dec_and_test(&desc.refs)
[ success, desc space on the stack
is being reused and might have
non-zero value. ]
arch_atomic_inc_not_zero(&desc->refs)
[ might succeed since desc points to
stack memory that was freed and might
be reused. ]
Fix this issue with small backportable patch. Instead of trying to
make RCU-like behavior for bp_desc, just eliminate the unnecessary
level of indirection of bp_desc, and hold the whole descriptor as a
global. Anyhow, there is only a single descriptor at any given
moment.
Fixes: 1f676247f36a4 ("x86/alternatives: Implement a better poke_int3_handler() completion scheme")
Signed-off-by: Nadav Amit <namit@vmware.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@kernel.org
Link: https://lkml.kernel.org/r/20220920224743.3089-1-namit@vmware.com
2022-09-22 02:09:32 +08:00
|
|
|
if (!atomic_dec_and_test(&bp_desc.refs))
|
|
|
|
atomic_cond_read_acquire(&bp_desc.refs, !VAL);
|
2013-07-12 17:21:48 +08:00
|
|
|
}
|
|
|
|
|
2020-03-04 00:42:12 +08:00
|
|
|
static void text_poke_loc_init(struct text_poke_loc *tp, void *addr,
|
|
|
|
const void *opcode, size_t len, const void *emulate)
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
{
|
|
|
|
struct insn insn;
|
2023-01-24 04:59:17 +08:00
|
|
|
int ret, i = 0;
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
|
2023-01-24 04:59:17 +08:00
|
|
|
if (len == 6)
|
|
|
|
i = 1;
|
|
|
|
memcpy((void *)tp->text, opcode+i, len-i);
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
if (!emulate)
|
|
|
|
emulate = opcode;
|
|
|
|
|
2021-03-26 23:12:00 +08:00
|
|
|
ret = insn_decode_kernel(&insn, emulate);
|
2020-11-07 02:37:25 +08:00
|
|
|
BUG_ON(ret < 0);
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
|
2019-10-09 18:26:53 +08:00
|
|
|
tp->rel_addr = addr - (void *)_stext;
|
2021-12-04 21:43:43 +08:00
|
|
|
tp->len = len;
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
tp->opcode = insn.opcode.bytes[0];
|
|
|
|
|
2023-01-24 04:59:17 +08:00
|
|
|
if (is_jcc32(&insn)) {
|
|
|
|
/*
|
|
|
|
* Map Jcc.d32 onto Jcc.d8 and use len to distinguish.
|
|
|
|
*/
|
|
|
|
tp->opcode = insn.opcode.bytes[1] - 0x10;
|
|
|
|
}
|
|
|
|
|
2021-12-04 21:43:43 +08:00
|
|
|
switch (tp->opcode) {
|
|
|
|
case RET_INSN_OPCODE:
|
|
|
|
case JMP32_INSN_OPCODE:
|
|
|
|
case JMP8_INSN_OPCODE:
|
|
|
|
/*
|
|
|
|
* Control flow instructions without implied execution of the
|
|
|
|
* next instruction can be padded with INT3.
|
|
|
|
*/
|
|
|
|
for (i = insn.length; i < len; i++)
|
|
|
|
BUG_ON(tp->text[i] != INT3_INSN_OPCODE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
BUG_ON(len != insn.length);
|
2022-11-09 05:09:51 +08:00
|
|
|
}
|
2021-12-04 21:43:43 +08:00
|
|
|
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
switch (tp->opcode) {
|
|
|
|
case INT3_INSN_OPCODE:
|
2020-08-18 21:57:47 +08:00
|
|
|
case RET_INSN_OPCODE:
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CALL_INSN_OPCODE:
|
|
|
|
case JMP32_INSN_OPCODE:
|
|
|
|
case JMP8_INSN_OPCODE:
|
2023-01-24 04:59:17 +08:00
|
|
|
case 0x70 ... 0x7f: /* Jcc */
|
2021-12-04 21:43:43 +08:00
|
|
|
tp->disp = insn.immediate.value;
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default: /* assume NOP */
|
|
|
|
switch (len) {
|
|
|
|
case 2: /* NOP2 -- emulate as JMP8+0 */
|
x86: Remove dynamic NOP selection
This ensures that a NOP is a NOP and not a random other instruction that
is also a NOP. It allows simplification of dynamic code patching that
wants to verify existing code before writing new instructions (ftrace,
jump_label, static_call, etc..).
Differentiating on NOPs is not a feature.
This pessimises 32bit (DONTCARE) and 32bit on 64bit CPUs (CARELESS).
32bit is not a performance target.
Everything x86_64 since AMD K10 (2007) and Intel IvyBridge (2012) is
fine with using NOPL (as opposed to prefix NOP). And per FEATURE_NOPL
being required for x86_64, all x86_64 CPUs can use NOPL. So stop
caring about NOPs, simplify things and get on with life.
[ The problem seems to be that some uarchs can only decode NOPL on a
single front-end port while others have severe decode penalties for
excessive prefixes. All modern uarchs can handle both, except Atom,
which has prefix penalties. ]
[ Also, much doubt you can actually measure any of this on normal
workloads. ]
After this, FEATURE_NOPL is unused except for required-features for
x86_64. FEATURE_K8 is only used for PTI.
[ bp: Kernel build measurements showed ~0.3s slowdown on Sandybridge
which is hardly a slowdown. Get rid of X86_FEATURE_K7, while at it. ]
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Acked-by: Alexei Starovoitov <alexei.starovoitov@gmail.com> # bpf
Acked-by: Linus Torvalds <torvalds@linuxfoundation.org>
Link: https://lkml.kernel.org/r/20210312115749.065275711@infradead.org
2021-03-12 19:32:54 +08:00
|
|
|
BUG_ON(memcmp(emulate, x86_nops[len], len));
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
tp->opcode = JMP8_INSN_OPCODE;
|
2021-12-04 21:43:43 +08:00
|
|
|
tp->disp = 0;
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 5: /* NOP5 -- emulate as JMP32+0 */
|
x86: Remove dynamic NOP selection
This ensures that a NOP is a NOP and not a random other instruction that
is also a NOP. It allows simplification of dynamic code patching that
wants to verify existing code before writing new instructions (ftrace,
jump_label, static_call, etc..).
Differentiating on NOPs is not a feature.
This pessimises 32bit (DONTCARE) and 32bit on 64bit CPUs (CARELESS).
32bit is not a performance target.
Everything x86_64 since AMD K10 (2007) and Intel IvyBridge (2012) is
fine with using NOPL (as opposed to prefix NOP). And per FEATURE_NOPL
being required for x86_64, all x86_64 CPUs can use NOPL. So stop
caring about NOPs, simplify things and get on with life.
[ The problem seems to be that some uarchs can only decode NOPL on a
single front-end port while others have severe decode penalties for
excessive prefixes. All modern uarchs can handle both, except Atom,
which has prefix penalties. ]
[ Also, much doubt you can actually measure any of this on normal
workloads. ]
After this, FEATURE_NOPL is unused except for required-features for
x86_64. FEATURE_K8 is only used for PTI.
[ bp: Kernel build measurements showed ~0.3s slowdown on Sandybridge
which is hardly a slowdown. Get rid of X86_FEATURE_K7, while at it. ]
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Acked-by: Alexei Starovoitov <alexei.starovoitov@gmail.com> # bpf
Acked-by: Linus Torvalds <torvalds@linuxfoundation.org>
Link: https://lkml.kernel.org/r/20210312115749.065275711@infradead.org
2021-03-12 19:32:54 +08:00
|
|
|
BUG_ON(memcmp(emulate, x86_nops[len], len));
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
tp->opcode = JMP32_INSN_OPCODE;
|
2021-12-04 21:43:43 +08:00
|
|
|
tp->disp = 0;
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default: /* unknown instruction */
|
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-26 19:38:58 +08:00
|
|
|
/*
|
|
|
|
* We hard rely on the tp_vec being ordered; ensure this is so by flushing
|
|
|
|
* early if needed.
|
|
|
|
*/
|
|
|
|
static bool tp_order_fail(void *addr)
|
|
|
|
{
|
|
|
|
struct text_poke_loc *tp;
|
|
|
|
|
|
|
|
if (!tp_vec_nr)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!addr) /* force */
|
|
|
|
return true;
|
|
|
|
|
|
|
|
tp = &tp_vec[tp_vec_nr - 1];
|
2019-10-09 18:26:53 +08:00
|
|
|
if ((unsigned long)text_poke_addr(tp) > (unsigned long)addr)
|
2019-08-26 19:38:58 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void text_poke_flush(void *addr)
|
|
|
|
{
|
|
|
|
if (tp_vec_nr == TP_VEC_MAX || tp_order_fail(addr)) {
|
|
|
|
text_poke_bp_batch(tp_vec, tp_vec_nr);
|
|
|
|
tp_vec_nr = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void text_poke_finish(void)
|
|
|
|
{
|
|
|
|
text_poke_flush(NULL);
|
|
|
|
}
|
|
|
|
|
2019-08-26 20:48:23 +08:00
|
|
|
void __ref text_poke_queue(void *addr, const void *opcode, size_t len, const void *emulate)
|
2019-08-26 19:38:58 +08:00
|
|
|
{
|
|
|
|
struct text_poke_loc *tp;
|
|
|
|
|
|
|
|
text_poke_flush(addr);
|
|
|
|
|
|
|
|
tp = &tp_vec[tp_vec_nr++];
|
|
|
|
text_poke_loc_init(tp, addr, opcode, len, emulate);
|
|
|
|
}
|
|
|
|
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
/**
|
|
|
|
* text_poke_bp() -- update instructions on live kernel on SMP
|
|
|
|
* @addr: address to patch
|
|
|
|
* @opcode: opcode of new instruction
|
|
|
|
* @len: length to copy
|
2020-12-03 22:50:20 +08:00
|
|
|
* @emulate: instruction to be emulated
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
*
|
|
|
|
* Update a single instruction with the vector in the stack, avoiding
|
|
|
|
* dynamically allocated memory. This function should be used when it is
|
|
|
|
* not possible to allocate memory.
|
|
|
|
*/
|
2019-08-26 20:48:23 +08:00
|
|
|
void __ref text_poke_bp(void *addr, const void *opcode, size_t len, const void *emulate)
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
{
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
struct text_poke_loc tp;
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
|
x86/alternatives: Teach text_poke_bp() to emulate instructions
In preparation for static_call and variable size jump_label support,
teach text_poke_bp() to emulate instructions, namely:
JMP32, JMP8, CALL, NOP2, NOP_ATOMIC5, INT3
The current text_poke_bp() takes a @handler argument which is used as
a jump target when the temporary INT3 is hit by a different CPU.
When patching CALL instructions, this doesn't work because we'd miss
the PUSH of the return address. Instead, teach poke_int3_handler() to
emulate an instruction, typically the instruction we're patching in.
This fits almost all text_poke_bp() users, except
arch_unoptimize_kprobe() which restores random text, and for that site
we have to build an explicit emulate instruction.
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.529086974@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
(cherry picked from commit 8c7eebc10687af45ac8e40ad1bac0cf7893dba9f)
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-06-05 16:48:37 +08:00
|
|
|
text_poke_loc_init(&tp, addr, opcode, len, emulate);
|
x86/alternative: Batch of patch operations
Currently, the patch of an address is done in three steps:
-- Pseudo-code #1 - Current implementation ---
1) add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #1 ---
When a static key has more than one entry, these steps are called once for
each entry. The number of IPIs then is linear with regard to the number 'n' of
entries of a key: O(n*3), which is O(n).
This algorithm works fine for the update of a single key. But we think
it is possible to optimize the case in which a static key has more than
one entry. For instance, the sched_schedstats jump label has 56 entries
in my (updated) fedora kernel, resulting in 168 IPIs for each CPU in
which the thread that is enabling the key is _not_ running.
With this patch, rather than receiving a single patch to be processed, a vector
of patches is passed, enabling the rewrite of the pseudo-code #1 in this
way:
-- Pseudo-code #2 - This patch ---
1) for each patch in the vector:
add an int3 trap to the address that will be patched
sync cores (send IPI to all other CPUs)
2) for each patch in the vector:
update all but the first byte of the patched range
sync cores (send IPI to all other CPUs)
3) for each patch in the vector:
replace the first byte (int3) by the first byte of replacing opcode
sync cores (send IPI to all other CPUs)
-- Pseudo-code #2 - This patch ---
Doing the update in this way, the number of IPI becomes O(3) with regard
to the number of keys, which is O(1).
The batch mode is done with the function text_poke_bp_batch(), that receives
two arguments: a vector of "struct text_to_poke", and the number of entries
in the vector.
The vector must be sorted by the addr field of the text_to_poke structure,
enabling the binary search of a handler in the poke_int3_handler function
(a fast path).
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris von Recklinghausen <crecklin@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Scott Wood <swood@redhat.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/ca506ed52584c80f64de23f6f55ca288e5d079de.1560325897.git.bristot@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2019-06-12 17:57:29 +08:00
|
|
|
text_poke_bp_batch(&tp, 1);
|
|
|
|
}
|