On Fri, Apr 11, 2025 at 06:32:43PM +0200, Oleg Nesterov wrote:
> On 04/11, Andrii Nakryiko wrote:
> >
> > > --- a/arch/x86/kernel/uprobes.c
> > > +++ b/arch/x86/kernel/uprobes.c
> > > @@ -840,6 +840,12 @@ static int branch_setup_xol_ops(struct arch_uprobe 
> > > *auprobe, struct insn *insn)
> > >         insn_byte_t p;
> > >         int i;
> > >
> > > +       /* x86_nops[i]; same as jmp with .offs = 0 */
> > > +       for (i = 1; i <= ASM_NOP_MAX; ++i) {
> >
> > i <= ASM_NOP_MAX && i <= insn->length
> >
> > ?
> >
> > otherwise what prevents us from reading past the actual instruction bytes?
> 
> Well, copy_insn() just copies MAX_UINSN_BYTES into arch_uprobe.insn[].
> If, say, the 1st 11 bytes of arch_uprobe.insn (or insn->kaddr) match
> x86_nops[11] then insn->length must be 11, or insn_decode() is buggy?
> 
> > or, actually, shouldn't we just check memcmp(x86_nops[insn->length])
> > if insn->length < ASM_NOP_MAX ?

nice, did not think of that

> 
> Hmm... agreed.
> 
> Either way this check can't (doesn't even try to) detect, say,
> "rep; BYTES_NOP5", so we do not care if insn->length == 6 in this case.
> 
> Good point!

I'll run tests and send formal patch for change below

thanks,
jirka


---
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index 9194695662b2..6d383839e839 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -840,6 +840,11 @@ static int branch_setup_xol_ops(struct arch_uprobe 
*auprobe, struct insn *insn)
        insn_byte_t p;
        int i;
 
+       /* x86_nops[insn->length]; same as jmp with .offs = 0 */
+       if (insn->length <= ASM_NOP_MAX &&
+           !memcmp(insn->kaddr, x86_nops[insn->length], insn->length))
+               goto setup;
+
        switch (opc1) {
        case 0xeb:      /* jmp 8 */
        case 0xe9:      /* jmp 32 */

Reply via email to