lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 9 Nov 2020 18:16:10 -0500
From:   Steven Rostedt <rostedt@...dmis.org>
To:     Peter Zijlstra <peterz@...radead.org>
Cc:     linux-kernel@...r.kernel.org, Ingo Molnar <mingo@...nel.org>,
        Andrew Morton <akpm@...ux-foundation.org>,
        Miroslav Benes <mbenes@...e.cz>,
        Thomas Gleixner <tglx@...utronix.de>,
        Masami Hiramatsu <mhiramat@...nel.org>
Subject: Re: [PATCH 2/3 v4] ftrace/x86: Allow for arguments to be passed in
 to ftrace_regs by default

On Mon, 9 Nov 2020 12:10:43 +0100
Peter Zijlstra <peterz@...radead.org> wrote:

> >  SYM_INNER_LABEL(ftrace_caller_op_ptr, SYM_L_GLOBAL)
> >  	/* Load the ftrace_ops into the 3rd parameter */
> >  	movq function_trace_op(%rip), %rdx
> >  
> > -	/* regs go into 4th parameter (but make it NULL) */
> > -	movq $0, %rcx
> > +	/* regs go into 4th parameter */
> > +	leaq (%rsp), %rcx
> > +
> > +	/* Only ops with REGS flag set should have CS register set */
> > +	movq $0, CS(%rsp)
> >  
> >  SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
> >  	call ftrace_stub  
> 
> You now seem to be relying on save_mcount_regs() resulting in a cleared
> CS, however, AFAICT CS is uninitialized stack garbage.

We have two trampolines that are also used to copy for other
trampolines that are dynamically created. There's this one
(ftrace_caller) and then there's the regs one (ftrace_regs_caller).
This one clears the CS in pt_regs to let the arch code know that the
ftrace_regs is not a full pt_regs and anyone trying to get it with
ftrace_get_regs() will get a NULL pointer. But the ftrace_regs_caller
loads the CS register with __KERNEL_CS, which is non zero, and the
ftrace_get_regs() will return the full pt_regs if it is set.

ftrace_caller:
	[..]
	movq $0, CS(%rsp) <- loads zero into pt_regs->cs for internal use only.
	[..]
	call callback

ftrace_regs_caller:
	[..]
	movq $__KERNEL_CS, %rcx
	movq %rcx, CS(%rsp)
	[..]
	call callback


Then in the callback we have:


callback(..., struct ftrace_regs *fregs)
{
	struct pt_regs *regs = ftrace_get_regs(fregs);
}

Where ftrace_get_regs is arch specific and returns for x86_64:

static __always_inline struct pt_regs *
arch_ftrace_get_regs(struct ftrace_regs *fregs)
{
	/* Only when FL_SAVE_REGS is set, cs will be non zero */
	if (!fregs->regs.cs)
		return NULL;
	return &fregs->regs;
}

What am I missing?

-- Steve

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ