2020-03-24 17:32:51 +08:00
|
|
|
// RUN: %clang_cc1 -triple thumbv8m.base-none-eabi -mcmse -verify %s
|
|
|
|
|
|
|
|
typedef void (*callback_ns_1t)() __attribute__((cmse_nonsecure_call));
|
|
|
|
typedef void (*callback_1t)();
|
|
|
|
typedef void (*callback_ns_2t)() __attribute__((cmse_nonsecure_call));
|
|
|
|
typedef void (*callback_2t)();
|
|
|
|
|
|
|
|
void foo(callback_ns_1t nsfptr, // expected-error{{functions may not be declared with 'cmse_nonsecure_call' attribute}}
|
|
|
|
callback_1t fptr) __attribute__((cmse_nonsecure_call))
|
|
|
|
{
|
|
|
|
callback_1t fp1 = nsfptr; // expected-warning{{incompatible function pointer types initializing 'callback_1t'}}
|
|
|
|
callback_ns_1t fp2 = fptr; // expected-warning{{incompatible function pointer types initializing 'callback_ns_1t'}}
|
|
|
|
callback_2t fp3 = fptr;
|
|
|
|
callback_ns_2t fp4 = nsfptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bar() __attribute__((cmse_nonsecure_entry)) // expected-warning{{'cmse_nonsecure_entry' cannot be applied to functions with internal linkage}}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef void nonsecure_fn_t(int) __attribute__((cmse_nonsecure_call));
|
|
|
|
extern nonsecure_fn_t baz; // expected-error{{functions may not be declared with 'cmse_nonsecure_call' attribute}}
|
|
|
|
|
|
|
|
int v0 __attribute__((cmse_nonsecure_call)); // expected-warning {{'cmse_nonsecure_call' only applies to function types; type here is 'int'}}
|
|
|
|
int v1 __attribute__((cmse_nonsecure_entry)); // expected-warning {{'cmse_nonsecure_entry' attribute only applies to functions}}
|
|
|
|
|
|
|
|
void fn0() __attribute__((cmse_nonsecure_entry));
|
|
|
|
void fn1() __attribute__((cmse_nonsecure_entry(1))); // expected-error {{'cmse_nonsecure_entry' attribute takes no arguments}}
|
|
|
|
|
|
|
|
typedef void (*fn2_t)() __attribute__((cmse_nonsecure_call("abc"))); // expected-error {{'cmse_nonsecure_call' attribute takes no argument}}
|
[CMSE] Clear padding bits of struct/unions/fp16 passed by value
When passing a value of a struct/union type from secure to non-secure
state (that is returning from a CMSE entry function or passing an
argument to CMSE-non-secure call), there is a potential sensitive
information leak via the padding bits in the structure. It is not
possible in the general case to ensure those bits are cleared by using
Standard C/C++.
This patch makes the compiler emit code to clear such padding
bits. Since type information is lost in LLVM IR, the code generation
is done by Clang.
For each interesting record type, we build a bitmask, in which all the
bits, corresponding to user declared members, are set. Values of
record types are returned by coercing them to an integer. After the
coercion, the coerced value is masked (with bitwise AND) and then
returned by the function. In a similar manner, values of record types
are passed as arguments by coercing them to an array of integers, and
the coerced values themselves are masked.
For union types, we effectively clear only bits, which aren't part of
any member, since we don't know which is the currently active one.
The compiler will issue a warning, whenever a union is passed to
non-secure state.
Values of half-precision floating-point types are passed in the least
significant bits of a 32-bit register (GPR or FPR) with the most
significant bits unspecified. Since this is also a potential leak of
sensitive information, this patch also clears those unspecified bits.
Differential Revision: https://reviews.llvm.org/D76369
2020-04-28 23:27:52 +08:00
|
|
|
|
|
|
|
union U { unsigned n; char b[4]; } u;
|
|
|
|
|
|
|
|
union U xyzzy() __attribute__((cmse_nonsecure_entry)) {
|
|
|
|
return u; // expected-warning {{passing union across security boundary via return value may leak information}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void (*fn2)(int, union U) __attribute__((cmse_nonsecure_call));
|
|
|
|
void (*fn3)() __attribute__ ((cmse_nonsecure_call));
|
|
|
|
|
|
|
|
struct S {
|
|
|
|
int t;
|
|
|
|
union {
|
|
|
|
char b[4];
|
|
|
|
unsigned w;
|
|
|
|
};
|
|
|
|
} s;
|
|
|
|
|
|
|
|
void qux() {
|
|
|
|
fn2(1,
|
|
|
|
u); // expected-warning {{passing union across security boundary via parameter 1 may leak information}}
|
|
|
|
|
|
|
|
fn3(
|
|
|
|
u, // expected-warning {{passing union across security boundary via parameter 0 may leak information}}
|
|
|
|
1,
|
|
|
|
s); // expected-warning {{passing union across security boundary via parameter 2 may leak information}}
|
|
|
|
}
|