📄 checks.h
字号:
// Runtime checks for Deputy programs.
// This file is included in deputy_lib and also at the start of every
// Deputy output file. Before this file is included you must define
// DEPUTY_ALWAYS_STOP_ON_ERROR if you want to optimize the checks.
// Note "volatile": We currently use volatile everywhere so that these
// checks work on any kind of pointer. In the future, we may want to
// investigate the performance impact of this annotation in the common
// (non-volatile) case.
// Use inline even when not optimizing for speed, since it prevents
// warnings that would occur due to unused static functions.
#ifdef DEPUTY_ALWAYS_STOP_ON_ERROR
#define INLINE inline __attribute__((always_inline))
#else
#define INLINE inline
#endif
#define __LOCATION__ 0
#define __LOCATION__FORMALS int flid
#define __LOCATION__ACTUALS flid
#ifndef asmlinkage
#define asmlinkage
#endif
#ifndef noreturn
#define noreturn __attribute__((noreturn))
#endif
#if defined(__KERNEL__) && defined(DEPUTY_KERNEL_COVERAGE)
INLINE static
unsigned int read_pc()
TRUSTED {
unsigned int pc;
asm("movl %%ebp, %0" : "=r"(pc));
return *((unsigned int *)pc + 1);
}
extern void checkBitArrayAdd(unsigned int addr);
#endif
extern asmlinkage
void deputy_fail_mayreturn(__LOCATION__FORMALS);
extern asmlinkage noreturn
void deputy_fail_noreturn(__LOCATION__FORMALS);
extern asmlinkage noreturn
void deputy_fail_noreturn_fast(__LOCATION__FORMALS);
/* Search for a NULL starting at e and return its index */
extern asmlinkage
int deputy_findnull(const void *e1, unsigned int sz);
#define __deputy_memset memset
#if defined(DEPUTY_FAST_CHECKS)
#define deputy_fail deputy_fail_noreturn_fast
#elif defined(DEPUTY_ALWAYS_STOP_ON_ERROR)
#define deputy_fail deputy_fail_noreturn
#else
#define deputy_fail deputy_fail_mayreturn
#endif
/* Check that there is no NULL between e .. e+len-1. "bytes" is the size of
* an element */
INLINE static asmlinkage
int deputy_nullcheck(const volatile void *e, unsigned int len,
unsigned int bytes) {
#define NULLCHECK(type) \
do { \
type *p1 = (type*) e; \
type *p2 = ((type*) e) + len; \
while (p1 < p2 && *p1 != 0) { \
p1++; \
} \
success = (p1 >= p2); \
} while (0)
int success = 0;
switch (bytes) {
case 1:
NULLCHECK(char);
break;
case 2:
NULLCHECK(short);
break;
case 4:
NULLCHECK(long);
break;
default:
deputy_fail(__LOCATION__);
}
return success;
#undef NULLCHECK
}
#if defined(__KERNEL__) && defined(KRECOVER) && !defined(NO_INJECTION)
extern int kr_failure_injected(void);
#define INJECTED_FAILURE() (kr_failure_injected())
#else
#define INJECTED_FAILURE() 0
#endif
// what : a boolean that ought to be true
// checkName: the name of the check
// checkWhat: a string that explains what goes wrong
#if defined(__KERNEL__) && defined(DEPUTY_KERNEL_COVERAGE)
#define DEPUTY_ASSERT_TEXT(what,text,checkName)\
checkBitArrayAdd(read_pc());\
if (!(what) || INJECTED_FAILURE()) { \
deputy_fail(__LOCATION__ACTUALS); \
}
#define DEPUTY_ASSERT(what, checkName) \
checkBitArrayAdd(read_pc());\
DEPUTY_ASSERT_TEXT(what, text, checkName)
#else
#define DEPUTY_ASSERT_TEXT(what, text, checkName) \
if (!(what) || INJECTED_FAILURE()) { \
deputy_fail(__LOCATION__ACTUALS); \
}
#define DEPUTY_ASSERT(what, checkName) \
DEPUTY_ASSERT_TEXT(what, text, checkName)
#endif
INLINE static void CNonNull(const volatile void* p, __LOCATION__FORMALS) {
DEPUTY_ASSERT(p != 0, "non-null check");
}
INLINE static void CEq(const volatile void* e1, const volatile void* e2,
__LOCATION__FORMALS) {
DEPUTY_ASSERT(e1 == e2, why);
}
INLINE static void CMult(int i1, int i2, __LOCATION__FORMALS) {
DEPUTY_ASSERT((i2 % i1) == 0, "alignment check");
}
/* Check that p + sz * e does not overflow that remains within [lo..hi). It
* is guaranteed on input that lo <= p <= hi, with p and h aligned w.r.t. lo
* and size sz. */
INLINE static void CPtrArith(const volatile void* lo, const volatile void* hi,
const volatile void* p, int e, unsigned int sz,
__LOCATION__FORMALS) {
if (e >= 0) {
DEPUTY_ASSERT_TEXT(e <= (hi - p) / sz, texthi, "upper bound check");
} else {
DEPUTY_ASSERT_TEXT(-e <= (p - lo) / sz, textlo, "lower bound check");
}
}
INLINE static void CPtrArithNT(const volatile void* lo, const volatile void* hi,
const volatile void* p, int e, unsigned int sz,
__LOCATION__FORMALS) {
if (e >= 0) {
unsigned int len = (hi - p) / sz;
if (e > len) {
DEPUTY_ASSERT_TEXT(deputy_nullcheck(hi, e - len, sz),
texthi, "nullterm upper bound check");
}
} else {
DEPUTY_ASSERT_TEXT(-e <= (p - lo) / sz, textlo, "lower bound check");
}
}
INLINE static void CPtrArithAccess(const volatile void* lo,
const volatile void* hi,
const volatile void* p,
int e, unsigned int sz,
__LOCATION__FORMALS) {
if (e >= 0) {
DEPUTY_ASSERT_TEXT(e + 1 <= (hi - p) / sz, texthi, "upper bound check");
} else {
DEPUTY_ASSERT_TEXT(-e <= (p - lo) / sz, textlo, "lower bound check");
}
}
INLINE static void CLeqInt(unsigned int e1, unsigned int e2,
__LOCATION__FORMALS) {
DEPUTY_ASSERT(e1 <= e2, why);
}
INLINE static void CLeq(const volatile void* e1, const volatile void* e2,
__LOCATION__FORMALS) {
DEPUTY_ASSERT(e1 <= e2, why);
}
/* Used to set the upped bounds of an NT string to e1, when we know that e2
* is a safe upper bound. Test that e1 <= e2 OR there is no NULL between
* e2...e1-1. */
INLINE static void CLeqNT(const volatile void* e1, const volatile void* e2,
unsigned int sz, __LOCATION__FORMALS) {
if (e1 > e2) {
DEPUTY_ASSERT(deputy_nullcheck(e2, (e1 - e2) / sz, sz), why);
}
}
INLINE static void CNullOrLeq(const volatile void* e,
const volatile void* e1, const volatile void* e2,
__LOCATION__FORMALS) {
if (e) {
DEPUTY_ASSERT(e1 <= e2, why);
}
}
/* Check that e is NULL, or e1 <= e2, or there is no NULL from e2 to e1 */
INLINE static void CNullOrLeqNT(const volatile void* e,
const volatile void* e1,
const volatile void* e2,
unsigned int sz, __LOCATION__FORMALS) {
if (e && e1 > e2) {
DEPUTY_ASSERT(deputy_nullcheck(e2, (e1 - e2) / sz, sz), why);
}
}
INLINE static void CWriteNT(const volatile void* p,
const volatile void* hi,
int what, unsigned int sz,
__LOCATION__FORMALS) {
if (p == hi) {
int isNull = 0;
switch (sz) {
case 1: isNull = (*((const volatile char *) p) == 0); break;
case 2: isNull = (*((const volatile short *) p) == 0); break;
case 4: isNull = (*((const volatile int *) p) == 0); break;
}
DEPUTY_ASSERT(!isNull || what == 0, "nullterm write check");
}
}
INLINE static void CNullUnionOrSelected(const volatile void* p,
unsigned int size,
int sameFieldSelected,
__LOCATION__FORMALS) {
if (!sameFieldSelected) {
const volatile char* pp = (const volatile char*)p;
const volatile char* pend = pp + size;
while (pp < pend) {
DEPUTY_ASSERT(0 == *pp++, "null union check");
}
}
}
INLINE static void CSelected(int what, __LOCATION__FORMALS) {
if (!(what)) {
deputy_fail(__LOCATION__ACTUALS); }
}
INLINE static void CNotSelected(int what, __LOCATION__FORMALS) {
if ((what)) {
deputy_fail(__LOCATION__ACTUALS); }
}
#define deputy_max(x, y) ((x) > (y) ? (x) : (y))
#undef DEPUTY_ASSERT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -