On Mon, Jun 29, 2026 at 06:40:07PM +0200, Oleg Nesterov wrote:
> On 06/29, Jiri Olsa wrote:
> >
> > --- a/arch/x86/kernel/uprobes.c
> > +++ b/arch/x86/kernel/uprobes.c
> > @@ -265,6 +265,10 @@ static bool is_prefix_bad(struct insn *insn)
> >
> > attr = inat_get_opcode_attribute(p);
> > switch (attr) {
> > + case INAT_MAKE_PREFIX(INAT_PFX_CS):
> > + if (insn->x86_64)
> > + break;
> > + fallthrough;
> > case INAT_MAKE_PREFIX(INAT_PFX_ES):
> > case INAT_MAKE_PREFIX(INAT_PFX_DS):
> > case INAT_MAKE_PREFIX(INAT_PFX_SS):
> >
> > or we could just skip it for nop10.. maybe that's better
>
> Well, if you ask me I'd agree with the "maybe that's better" plan ;)
> I mean... I don't think that INAT_PFX_CS should be "special" in is_prefix_bad.
>
> But, whatever you do - I agree, feel free to keep my r-b.
I ended up with the bigger change below, wdyt?
jirka
---
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index 92626fce06a9..521a120a0c78 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -266,6 +266,7 @@ static bool is_prefix_bad(struct insn *insn)
attr = inat_get_opcode_attribute(p);
switch (attr) {
case INAT_MAKE_PREFIX(INAT_PFX_ES):
+ case INAT_MAKE_PREFIX(INAT_PFX_CS):
case INAT_MAKE_PREFIX(INAT_PFX_DS):
case INAT_MAKE_PREFIX(INAT_PFX_SS):
case INAT_MAKE_PREFIX(INAT_PFX_LOCK):
@@ -275,15 +276,9 @@ static bool is_prefix_bad(struct insn *insn)
return false;
}
-static int uprobe_init_insn(struct arch_uprobe *auprobe, struct insn *insn,
bool x86_64)
+static int uprobe_init_insn(struct arch_uprobe *auprobe, struct insn *insn)
{
- enum insn_mode m = x86_64 ? INSN_MODE_64 : INSN_MODE_32;
u32 volatile *good_insns;
- int ret;
-
- ret = insn_decode(insn, auprobe->insn, sizeof(auprobe->insn), m);
- if (ret < 0)
- return -ENOEXEC;
if (is_prefix_bad(insn))
return -ENOTSUPP;
@@ -292,7 +287,7 @@ static int uprobe_init_insn(struct arch_uprobe *auprobe,
struct insn *insn, bool
if (insn_masking_exception(insn))
return -ENOTSUPP;
- if (x86_64)
+ if (insn->x86_64)
good_insns = good_insns_64;
else
good_insns = good_insns_32;
@@ -1620,16 +1615,26 @@ static int push_setup_xol_ops(struct arch_uprobe
*auprobe, struct insn *insn)
*/
int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct
*mm, unsigned long addr)
{
+ enum insn_mode m = is_64bit_mm(mm) ? INSN_MODE_64 : INSN_MODE_32;
u8 fix_ip_or_call = UPROBE_FIX_IP;
struct insn insn;
int ret;
- ret = uprobe_init_insn(auprobe, &insn, is_64bit_mm(mm));
- if (ret)
- return ret;
+ ret = insn_decode(&insn, auprobe->insn, sizeof(auprobe->insn), m);
+ if (ret < 0)
+ return -ENOEXEC;
- if (can_optimize(&insn, addr))
+ /*
+ * No need to check instruction in uprobe_init_insn in case we
+ * are on top of optimizable nop10.
+ */
+ if (can_optimize(&insn, addr)) {
set_bit(ARCH_UPROBE_FLAG_CAN_OPTIMIZE, &auprobe->flags);
+ } else {
+ ret = uprobe_init_insn(auprobe, &insn);
+ if (ret)
+ return ret;
+ }
ret = branch_setup_xol_ops(auprobe, &insn);
if (ret != -ENOSYS)