On Mon, Jul 14, 2025 at 11:28:01AM +0200, Peter Zijlstra wrote:
> On Mon, Jul 14, 2025 at 05:39:15PM +0900, Masami Hiramatsu wrote:
> 
> > > +SYSCALL_DEFINE0(uprobe)
> > > +{
> > > + struct pt_regs *regs = task_pt_regs(current);
> > > + unsigned long ip, sp, ax_r11_cx_ip[4];
> > > + int err;
> > > +
> > > + /* Allow execution only from uprobe trampolines. */
> > > + if (!in_uprobe_trampoline(regs->ip))
> > > +         goto sigill;
> > > +
> > 
> > /*
> >  * When syscall from the trampoline, including a call to the trampoline
> >  * the stack will be shown as;
> >  *  regs->sp[0]: [rax]
> >  *          [1]: [r11]
> >  *          [2]: [rcx]
> >  *          [3]: [return-address] (probed address + 
> > sizeof(call-instruction))
> >  *
> >  * And the `&regs->sp[4]` should be the `sp` value when probe is hit.
> >  */
> > 
> > > + err = copy_from_user(ax_r11_cx_ip, (void __user *)regs->sp, 
> > > sizeof(ax_r11_cx_ip));
> > > + if (err)
> > > +         goto sigill;
> > > +
> > > + ip = regs->ip;
> > > +
> > > + /*
> > > +  * expose the "right" values of ax/r11/cx/ip/sp to uprobe_consumer/s, 
> > > plus:
> > > +  * - adjust ip to the probe address, call saved next instruction address
> > > +  * - adjust sp to the probe's stack frame (check trampoline code)
> > > +  */
> > > + regs->ax  = ax_r11_cx_ip[0];
> > > + regs->r11 = ax_r11_cx_ip[1];
> > > + regs->cx  = ax_r11_cx_ip[2];
> > > + regs->ip  = ax_r11_cx_ip[3] - 5;
> > > + regs->sp += sizeof(ax_r11_cx_ip);
> > > + regs->orig_ax = -1;
> > > +
> 
> Would not a structure be more natural?
> 
> /*
>  * See uprobe syscall trampoline; the call to the trampoline will push
>  * the return address on the stack, the trampoline itself then pushes
>  * cx, r11 and ax.
>  */
> struct uprobe_syscall_args {
>       unsigned long ax;
>       unsigned long r11;
>       unsigned long cx;
>       unsigned long retaddr;
> };
> 
>       err = copy_from_user(sys_args, (void __user *)regs->sp, 
> sizeof(sys_args));
>       if (err)
>               goto sigill;
> 
>       ip = regs->ip;
> 
>       regs->ax  = sys_args->ax;
>       regs->r11 = sys_args->r11;
>       regs->cx  = sys_args->cx;
>       regs->ip  = sys_args->retaddr - CALL_INSN_SIZE;
>       regs->sp += sizeof(sys_args);
> 
> etc.. ?

I was mimicking sys_uretprobe, but using struct does seem better

thanks,
jirka

Reply via email to