llvm-project/llvm/test/CodeGen/X86/nocf_check.ll
Joao Moreira e0b89df2e0 [X86] Check if call is indirect before emitting NT_CALL
The notrack prefix is a relaxation of CET policies which makes it possible to indirectly call targets which do not have an ENDBR instruction in the landing address. To emit a call with this prefix, the special attribute "nocf_check" is used. When used as a function attribute, a CallInst targeting the respective function will return true for the method "doesNoCfCheck()", no matter if it is a direct call (and such should remain like this, as the information that the to-be-called function won't perform control-flow checks is useful in other contexts). Yet, when emitting an X86ISD::NT_CALL, the respective CallInst should be verified for its indirection, allowing that the prefixed calls are only emitted in the right situations.

Update the respective testing unit to also verify for direct calls to functions with ''nocf_check'' attributes.

The bug can also be reproduced through compiling the following C code using the -fcf-protection=full flag.

int __attribute__((nocf_check)) foo(int a) {};

int main() {
  foo(42);
}

Differential Revision: https://reviews.llvm.org/D87320
2020-10-09 15:54:23 -07:00

53 lines
3.2 KiB
LLVM

; RUN: llc -mtriple=x86_64-unknown-unknown -x86-indirect-branch-tracking < %s | FileCheck %s
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; This test verify the handling of ''nocf_check'' attribute by the backend. ;;
;; The file was generated using the following C code: ;;
;; ;;
;; void __attribute__((nocf_check)) NoCfCheckFunc(void) {} ;;
;; ;;
;; typedef void(*FuncPointer)(void); ;;
;; void NoCfCheckCall(FuncPointer f) { ;;
;; __attribute__((nocf_check)) FuncPointer p = f; ;;
;; (*p)(); ;;
;; NoCfCheckFunc(); ;;
;; } ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Make sure that a function with ''nocf_check'' attribute is not instrumented
; with endbr instruction at the beginning.
define void @NoCfCheckFunc() #0 {
; CHECK-LABEL: NoCfCheckFunc
; CHECK-NOT: endbr64
; CHECK: retq
entry:
ret void
}
; Ensure the notrack prefix is added before an indirect call using a pointer
; with ''nocf_check'' attribute. Also ensure a direct call to a function with
; the ''nocf_check'' attribute is correctly generated without notrack prefix.
define void @NoCfCheckCall(void ()* %f) #1 {
; CHECK-LABEL: NoCfCheckCall
; CHECK: notrack call
; CHECK: callq NoCfCheckFunc
entry:
%f.addr = alloca void ()*, align 4
%p = alloca void ()*, align 4
store void ()* %f, void ()** %f.addr, align 4
%0 = load void ()*, void ()** %f.addr, align 4
store void ()* %0, void ()** %p, align 4
%1 = load void ()*, void ()** %p, align 4
call void %1() #2
call void @NoCfCheckFunc() #2
ret void
}
attributes #0 = { nocf_check noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { nocf_check }
!llvm.module.flags = !{!0}
!0 = !{i32 4, !"cf-protection-branch", i32 1}