When an indirect CALL/JMP instruction is executed and before it reaches
the target, it is in 'WAIT_ENDBR' status, which can be read from
MSR_IA32_U_CET. The status is part of a task's status before a signal is
raised and preserved in the signal frame. It is restored for sigreturn.
IBT state machine is described in Intel SDM Vol. 1, Sec. 18.3.
Signed-off-by: Yu-cheng Yu <redacted>
Reviewed-by: Kees Cook <redacted>
---
arch/x86/kernel/cet.c | 26 ++++++++++++++++++++++++--
arch/x86/kernel/fpu/signal.c | 8 +++++---
2 files changed, 29 insertions(+), 5 deletions(-)
@@ -577,7 +579,7 @@ static unsigned long fpu__alloc_sigcontext_ext(unsigned long sp)*sigcontext_extisat:fpu+fpu_user_xstate_size+*FP_XSTATE_MAGIC2_SIZE,thenalignedto8.*/-if(cet->shstk_size)+if(cet->shstk_size||cet->ibt_enabled)sp-=(sizeof(structsc_ext)+8);returnsp;
From: "H.J. Lu" <redacted>
When Indirect Branch Tracking (IBT) is enabled, vDSO functions may be
called indirectly, and must have ENDBR32 or ENDBR64 as the first
instruction. The compiler must support -fcf-protection=branch so that it
can be used to compile vDSO.
Signed-off-by: H.J. Lu <redacted>
Signed-off-by: Yu-cheng Yu <redacted>
Acked-by: Andy Lutomirski <luto@kernel.org>
Reviewed-by: Kees Cook <redacted>
---
arch/x86/entry/vdso/Makefile | 4 ++++
1 file changed, 4 insertions(+)
Indirect branch tracking is a hardware security feature that verifies near
indirect call/jump instructions arrive at intended targets, which are
labeled by the compiler with ENDBR opcodes. If such instructions reach
unlabeled locations, the processor raises control-protection faults.
Check the compiler is up-to-date at config time.
Signed-off-by: Yu-cheng Yu <redacted>
Reviewed-by: Kees Cook <redacted>
---
arch/x86/Kconfig | 1 +
1 file changed, 1 insertion(+)
An ELF file's .note.gnu.property indicates features the file supports.
The property is parsed at loading time and passed to arch_setup_elf_
property(). Update it for Indirect Branch Tracking.
Signed-off-by: Yu-cheng Yu <redacted>
Reviewed-by: Kees Cook <redacted>
---
arch/x86/kernel/process_64.c | 8 ++++++++
1 file changed, 8 insertions(+)
When CET is enabled, __vdso_sgx_enter_enclave() needs an endbr64
in the beginning of the function.
Signed-off-by: Yu-cheng Yu <redacted>
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(+)
On Wed, Mar 10, 2021 at 02:05:19PM -0800, Yu-cheng Yu wrote:
quoted
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
quoted
Signed-off-by: Yu-cheng Yu <redacted>
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(+)
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.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
From: Dave Hansen <hidden> Date: 2021-03-10 23:21:17
On 3/10/21 2:55 PM, Yu, Yu-cheng wrote:
On 3/10/2021 2:39 PM, Jarkko Sakkinen wrote:
quoted
On Wed, Mar 10, 2021 at 02:05:19PM -0800, Yu-cheng Yu wrote:
quoted
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.
On Wed, Mar 10, 2021 at 02:05:19PM -0800, Yu-cheng Yu wrote:
quoted
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.
From: Jarkko Sakkinen <jarkko@kernel.org> Date: 2021-03-11 03:37:13
On Wed, Mar 10, 2021 at 02:55:55PM -0800, Yu, Yu-cheng wrote:
On 3/10/2021 2:39 PM, Jarkko Sakkinen wrote:
quoted
On Wed, Mar 10, 2021 at 02:05:19PM -0800, Yu-cheng Yu wrote:
quoted
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
quoted
quoted
Signed-off-by: Yu-cheng Yu <redacted>
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(+)
From: Peter Zijlstra <peterz@infradead.org> Date: 2021-03-11 08:43:24
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.
On Thu, Mar 11, 2021 at 05:36:06AM +0200, Jarkko Sakkinen wrote:
quoted
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
From: Jarkko Sakkinen <jarkko@kernel.org> Date: 2021-03-12 16:57:12
On Wed, Mar 10, 2021 at 03:20:20PM -0800, Dave Hansen wrote:
On 3/10/21 2:55 PM, Yu, Yu-cheng wrote:
quoted
On 3/10/2021 2:39 PM, Jarkko Sakkinen wrote:
quoted
On Wed, Mar 10, 2021 at 02:05:19PM -0800, Yu-cheng Yu wrote:
quoted
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
From: Jarkko Sakkinen <jarkko@kernel.org> Date: 2021-03-12 16:57:44
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:
quoted
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
From: Jarkko Sakkinen <jarkko@kernel.org> Date: 2021-03-12 16:58:48
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:
quoted
On 3/10/21 2:55 PM, Yu, Yu-cheng wrote:
quoted
On 3/10/2021 2:39 PM, Jarkko Sakkinen wrote:
quoted
On Wed, Mar 10, 2021 at 02:05:19PM -0800, Yu-cheng Yu wrote:
quoted
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
From: Dave Hansen <hidden> Date: 2021-03-12 17:00:57
On 3/12/21 8:55 AM, Jarkko Sakkinen wrote:
quoted
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".