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)

Reply via email to