diff mbox series

[v22,8/8] x86/vdso: Add ENDBR64 to __vdso_sgx_enter_enclave

Message ID 20210310220519.16811-9-yu-cheng.yu@intel.com (mailing list archive)
State New, archived
Headers show
Series Control-flow Enforcement: Indirect Branch Tracking | expand

Commit Message

Yu-cheng Yu March 10, 2021, 10:05 p.m. UTC
When CET is enabled, __vdso_sgx_enter_enclave() needs an endbr64
in the beginning of the function.

Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Jarkko Sakkinen <jarkko@kernel.org>
---
 arch/x86/entry/vdso/vsgx.S | 3 +++
 1 file changed, 3 insertions(+)

Comments

Jarkko Sakkinen March 10, 2021, 10:39 p.m. UTC | #1
On Wed, Mar 10, 2021 at 02:05:19PM -0800, Yu-cheng Yu wrote:
> When CET is enabled, __vdso_sgx_enter_enclave() needs an endbr64
> in the beginning of the function.

OK.

What you should do is to explain what it does and why it's needed.

> 
> Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: Jarkko Sakkinen <jarkko@kernel.org>
> ---
>  arch/x86/entry/vdso/vsgx.S | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/x86/entry/vdso/vsgx.S b/arch/x86/entry/vdso/vsgx.S
> index 86a0e94f68df..a70d4d09f713 100644
> --- a/arch/x86/entry/vdso/vsgx.S
> +++ b/arch/x86/entry/vdso/vsgx.S
> @@ -27,6 +27,9 @@
>  SYM_FUNC_START(__vdso_sgx_enter_enclave)
>  	/* Prolog */
>  	.cfi_startproc
> +#ifdef CONFIG_X86_CET
> +	endbr64
> +#endif
>  	push	%rbp
>  	.cfi_adjust_cfa_offset	8
>  	.cfi_rel_offset		%rbp, 0
> -- 
> 2.21.0
> 
> 

/Jarkko
Yu-cheng Yu March 10, 2021, 10:55 p.m. UTC | #2
On 3/10/2021 2:39 PM, Jarkko Sakkinen wrote:
> On Wed, Mar 10, 2021 at 02:05:19PM -0800, Yu-cheng Yu wrote:
>> When CET is enabled, __vdso_sgx_enter_enclave() needs an endbr64
>> in the beginning of the function.
> 
> OK.
> 
> What you should do is to explain what it does and why it's needed.
> 

The endbr marks a branch target.  Without the "no-track" prefix, if an 
indirect call/jmp reaches a non-endbr opcode, a control-protection fault 
is raised.  Usually endbr's are inserted by the compiler.  For assembly, 
these have to be put in manually.  I will add this in the commit log if 
there is another revision.  Thanks!

--
Yu-cheng

>>
>> Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
>> Cc: Andy Lutomirski <luto@kernel.org>
>> Cc: Dave Hansen <dave.hansen@linux.intel.com>
>> Cc: Jarkko Sakkinen <jarkko@kernel.org>
>> ---
>>   arch/x86/entry/vdso/vsgx.S | 3 +++
>>   1 file changed, 3 insertions(+)
>>
>> diff --git a/arch/x86/entry/vdso/vsgx.S b/arch/x86/entry/vdso/vsgx.S
>> index 86a0e94f68df..a70d4d09f713 100644
>> --- a/arch/x86/entry/vdso/vsgx.S
>> +++ b/arch/x86/entry/vdso/vsgx.S
>> @@ -27,6 +27,9 @@
>>   SYM_FUNC_START(__vdso_sgx_enter_enclave)
>>   	/* Prolog */
>>   	.cfi_startproc
>> +#ifdef CONFIG_X86_CET
>> +	endbr64
>> +#endif
>>   	push	%rbp
>>   	.cfi_adjust_cfa_offset	8
>>   	.cfi_rel_offset		%rbp, 0
>> -- 
>> 2.21.0
>>
>>
> 
> /Jarkko
>
Borislav Petkov March 10, 2021, 11:17 p.m. UTC | #3
On Wed, Mar 10, 2021 at 02:55:55PM -0800, Yu, Yu-cheng wrote:
> > > @@ -27,6 +27,9 @@
> > >   SYM_FUNC_START(__vdso_sgx_enter_enclave)
> > >   	/* Prolog */
> > >   	.cfi_startproc
> > > +#ifdef CONFIG_X86_CET
> > > +	endbr64
> > > +#endif

You can hide this ifdeffery in a macro and have

	ENDBR64

at the callsite and define

.macro ENDBR64
#ifdef CONFIG_X86_CET
	endbr64
#endif
.endm

or so, perhaps. Ditto for endbr32.

Thx.
Dave Hansen March 10, 2021, 11:20 p.m. UTC | #4
On 3/10/21 2:55 PM, Yu, Yu-cheng wrote:
> On 3/10/2021 2:39 PM, Jarkko Sakkinen wrote:
>> On Wed, Mar 10, 2021 at 02:05:19PM -0800, Yu-cheng Yu wrote:
>>> When CET is enabled, __vdso_sgx_enter_enclave() needs an endbr64
>>> in the beginning of the function.
>>
>> OK.
>>
>> What you should do is to explain what it does and why it's needed.
>>
> 
> The endbr marks a branch target.  Without the "no-track" prefix, if an
> indirect call/jmp reaches a non-endbr opcode, a control-protection fault
> is raised.  Usually endbr's are inserted by the compiler.  For assembly,
> these have to be put in manually.  I will add this in the commit log if
> there is another revision.  Thanks!

This is close, but it's missing a detail or two that I think is
important for someone like Jarkko trying to figure out what it means for
his subsystem or driver.

I'd probably say:

ENDBR is a special new instruction for the Indirect Branch Tracking
(IBR) component of CET.  IBT prevents attacks by ensuring that (most)
indirect branches and function calls may only land at ENDBR
instructions.  Branches that don't follow the rules will result in
control flow (#CF) exceptions.

ENDBR is a noop when IBT is unsupported or disabled.  Most ENDBR
instructions are inserted automatically by the compiler, but branch
targets written in assembly must have ENDBR added manually, like this one.
Yu-cheng Yu March 10, 2021, 11:22 p.m. UTC | #5
On 3/10/2021 3:20 PM, Dave Hansen wrote:
> On 3/10/21 2:55 PM, Yu, Yu-cheng wrote:
>> On 3/10/2021 2:39 PM, Jarkko Sakkinen wrote:
>>> On Wed, Mar 10, 2021 at 02:05:19PM -0800, Yu-cheng Yu wrote:
>>>> When CET is enabled, __vdso_sgx_enter_enclave() needs an endbr64
>>>> in the beginning of the function.
>>>
>>> OK.
>>>
>>> What you should do is to explain what it does and why it's needed.
>>>
>>
>> The endbr marks a branch target.  Without the "no-track" prefix, if an
>> indirect call/jmp reaches a non-endbr opcode, a control-protection fault
>> is raised.  Usually endbr's are inserted by the compiler.  For assembly,
>> these have to be put in manually.  I will add this in the commit log if
>> there is another revision.  Thanks!
> 
> This is close, but it's missing a detail or two that I think is
> important for someone like Jarkko trying to figure out what it means for
> his subsystem or driver.
> 
> I'd probably say:
> 
> ENDBR is a special new instruction for the Indirect Branch Tracking
> (IBR) component of CET.  IBT prevents attacks by ensuring that (most)
> indirect branches and function calls may only land at ENDBR
> instructions.  Branches that don't follow the rules will result in
> control flow (#CF) exceptions.
> 
> ENDBR is a noop when IBT is unsupported or disabled.  Most ENDBR
> instructions are inserted automatically by the compiler, but branch
> targets written in assembly must have ENDBR added manually, like this one.
> 

Ok, I will update.  Thanks!

--
Yu-cheng
Jarkko Sakkinen March 11, 2021, 3:36 a.m. UTC | #6
On Wed, Mar 10, 2021 at 02:55:55PM -0800, Yu, Yu-cheng wrote:
> On 3/10/2021 2:39 PM, Jarkko Sakkinen wrote:
> > On Wed, Mar 10, 2021 at 02:05:19PM -0800, Yu-cheng Yu wrote:
> > > When CET is enabled, __vdso_sgx_enter_enclave() needs an endbr64
> > > in the beginning of the function.
> > 
> > OK.
> > 
> > What you should do is to explain what it does and why it's needed.
> > 
> 
> The endbr marks a branch target.  Without the "no-track" prefix, if an
> indirect call/jmp reaches a non-endbr opcode, a control-protection fault is
> raised.  Usually endbr's are inserted by the compiler.  For assembly, these
> have to be put in manually.  I will add this in the commit log if there is
> another revision.  Thanks!

Thanks for the explanation. There is another revision, because this is
lacking from the commit message.

Does it do any harm to put it there unconditionally?

> 
> --
> Yu-cheng
> 
> > > 
> > > Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
> > > Cc: Andy Lutomirski <luto@kernel.org>
> > > Cc: Dave Hansen <dave.hansen@linux.intel.com>
> > > Cc: Jarkko Sakkinen <jarkko@kernel.org>
> > > ---
> > >   arch/x86/entry/vdso/vsgx.S | 3 +++
> > >   1 file changed, 3 insertions(+)
> > > 
> > > diff --git a/arch/x86/entry/vdso/vsgx.S b/arch/x86/entry/vdso/vsgx.S
> > > index 86a0e94f68df..a70d4d09f713 100644
> > > --- a/arch/x86/entry/vdso/vsgx.S
> > > +++ b/arch/x86/entry/vdso/vsgx.S
> > > @@ -27,6 +27,9 @@
> > >   SYM_FUNC_START(__vdso_sgx_enter_enclave)
> > >   	/* Prolog */
> > >   	.cfi_startproc
> > > +#ifdef CONFIG_X86_CET
> > > +	endbr64
> > > +#endif
> > >   	push	%rbp
> > >   	.cfi_adjust_cfa_offset	8
> > >   	.cfi_rel_offset		%rbp, 0
> > > -- 
> > > 2.21.0
> > > 
> > > 
> > 
> > /Jarkko
> > 
> 
> 

/Jarkko
Peter Zijlstra March 11, 2021, 8:42 a.m. UTC | #7
On Thu, Mar 11, 2021 at 05:36:06AM +0200, Jarkko Sakkinen wrote:
> Does it do any harm to put it there unconditionally?

Blows up your text footprint and I$ pressure. These instructions are 4
bytes each.

Aside from that, they're a NOP, so only consume front-end resources
(hopefully) on older CPUs and when IBT is disabled.
Yu-cheng Yu March 11, 2021, 3:44 p.m. UTC | #8
On 3/11/2021 12:42 AM, Peter Zijlstra wrote:
> On Thu, Mar 11, 2021 at 05:36:06AM +0200, Jarkko Sakkinen wrote:
>> Does it do any harm to put it there unconditionally?
> 
> Blows up your text footprint and I$ pressure. These instructions are 4
> bytes each.
> 
> Aside from that, they're a NOP, so only consume front-end resources
> (hopefully) on older CPUs and when IBT is disabled.
> 

Thanks Peter.  I think probably we'll do the macro Boris suggested. 
That takes care of the visual clutter, and eliminates the need of using 
.byte when the assembler is outdated.

--
Yu-cheng
Jarkko Sakkinen March 12, 2021, 4:55 p.m. UTC | #9
On Wed, Mar 10, 2021 at 03:20:20PM -0800, Dave Hansen wrote:
> On 3/10/21 2:55 PM, Yu, Yu-cheng wrote:
> > On 3/10/2021 2:39 PM, Jarkko Sakkinen wrote:
> >> On Wed, Mar 10, 2021 at 02:05:19PM -0800, Yu-cheng Yu wrote:
> >>> When CET is enabled, __vdso_sgx_enter_enclave() needs an endbr64
> >>> in the beginning of the function.
> >>
> >> OK.
> >>
> >> What you should do is to explain what it does and why it's needed.
> >>
> > 
> > The endbr marks a branch target.  Without the "no-track" prefix, if an
> > indirect call/jmp reaches a non-endbr opcode, a control-protection fault
> > is raised.  Usually endbr's are inserted by the compiler.  For assembly,
> > these have to be put in manually.  I will add this in the commit log if
> > there is another revision.  Thanks!
> 
> This is close, but it's missing a detail or two that I think is
> important for someone like Jarkko trying to figure out what it means for
> his subsystem or driver.
> 
> I'd probably say:
> 
> ENDBR is a special new instruction for the Indirect Branch Tracking
> (IBR) component of CET.  IBT prevents attacks by ensuring that (most)
> indirect branches and function calls may only land at ENDBR
> instructions.  Branches that don't follow the rules will result in
> control flow (#CF) exceptions.
> 
> ENDBR is a noop when IBT is unsupported or disabled.  Most ENDBR
> instructions are inserted automatically by the compiler, but branch
> targets written in assembly must have ENDBR added manually, like this one.

Thank you, this clears the whole thing a lot.

Doesn't this mean that it could be there just as well unconditionally?

/Jarkko
Jarkko Sakkinen March 12, 2021, 4:56 p.m. UTC | #10
On Thu, Mar 11, 2021 at 09:42:05AM +0100, Peter Zijlstra wrote:
> On Thu, Mar 11, 2021 at 05:36:06AM +0200, Jarkko Sakkinen wrote:
> > Does it do any harm to put it there unconditionally?
> 
> Blows up your text footprint and I$ pressure. These instructions are 4
> bytes each.
> 
> Aside from that, they're a NOP, so only consume front-end resources
> (hopefully) on older CPUs and when IBT is disabled.

OK, understood, thanks for the explanation.

/Jarkko
Jarkko Sakkinen March 12, 2021, 4:57 p.m. UTC | #11
On Fri, Mar 12, 2021 at 06:55:57PM +0200, Jarkko Sakkinen wrote:
> On Wed, Mar 10, 2021 at 03:20:20PM -0800, Dave Hansen wrote:
> > On 3/10/21 2:55 PM, Yu, Yu-cheng wrote:
> > > On 3/10/2021 2:39 PM, Jarkko Sakkinen wrote:
> > >> On Wed, Mar 10, 2021 at 02:05:19PM -0800, Yu-cheng Yu wrote:
> > >>> When CET is enabled, __vdso_sgx_enter_enclave() needs an endbr64
> > >>> in the beginning of the function.
> > >>
> > >> OK.
> > >>
> > >> What you should do is to explain what it does and why it's needed.
> > >>
> > > 
> > > The endbr marks a branch target.  Without the "no-track" prefix, if an
> > > indirect call/jmp reaches a non-endbr opcode, a control-protection fault
> > > is raised.  Usually endbr's are inserted by the compiler.  For assembly,
> > > these have to be put in manually.  I will add this in the commit log if
> > > there is another revision.  Thanks!
> > 
> > This is close, but it's missing a detail or two that I think is
> > important for someone like Jarkko trying to figure out what it means for
> > his subsystem or driver.
> > 
> > I'd probably say:
> > 
> > ENDBR is a special new instruction for the Indirect Branch Tracking
> > (IBR) component of CET.  IBT prevents attacks by ensuring that (most)
> > indirect branches and function calls may only land at ENDBR
> > instructions.  Branches that don't follow the rules will result in
> > control flow (#CF) exceptions.
> > 
> > ENDBR is a noop when IBT is unsupported or disabled.  Most ENDBR
> > instructions are inserted automatically by the compiler, but branch
> > targets written in assembly must have ENDBR added manually, like this one.
> 
> Thank you, this clears the whole thing a lot.
> 
> Doesn't this mean that it could be there just as well unconditionally?

Please, ignore the question (got the answer).

/Jarkko
Dave Hansen March 12, 2021, 4:59 p.m. UTC | #12
On 3/12/21 8:55 AM, Jarkko Sakkinen wrote:
>> ENDBR is a special new instruction for the Indirect Branch Tracking
>> (IBT) component of CET.  IBT prevents attacks by ensuring that (most)
>> indirect branches and function calls may only land at ENDBR
>> instructions.  Branches that don't follow the rules will result in
>> control flow (#CF) exceptions.
>>
>> ENDBR is a noop when IBT is unsupported or disabled.  Most ENDBR
>> instructions are inserted automatically by the compiler, but branch
>> targets written in assembly must have ENDBR added manually, like this one.
> Thank you, this clears the whole thing a lot.
> 
> Doesn't this mean that it could be there just as well unconditionally?

It could be there unconditionally.  But, I think it's still worth the
#ifdef just out of the principle of being as tidy as possible.  The
#ifdef is basically as low cost and low complexity as you get.  It is
also somewhat self-documenting: "This instruction is only necessary when
your CPU supports IBT".
diff mbox series

Patch

diff --git a/arch/x86/entry/vdso/vsgx.S b/arch/x86/entry/vdso/vsgx.S
index 86a0e94f68df..a70d4d09f713 100644
--- a/arch/x86/entry/vdso/vsgx.S
+++ b/arch/x86/entry/vdso/vsgx.S
@@ -27,6 +27,9 @@ 
 SYM_FUNC_START(__vdso_sgx_enter_enclave)
 	/* Prolog */
 	.cfi_startproc
+#ifdef CONFIG_X86_CET
+	endbr64
+#endif
 	push	%rbp
 	.cfi_adjust_cfa_offset	8
 	.cfi_rel_offset		%rbp, 0