📄 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 staticunsigned int read_pc()TRUSTED { unsigned int pc; asm("movl %%ebp, %0" : "=r"(pc)); return *((unsigned int *)pc + 1);}extern void checkBitArrayAdd(unsigned int addr);#endifextern asmlinkage void deputy_fail_mayreturn(__LOCATION__FORMALS);extern asmlinkage noreturnvoid deputy_fail_noreturn(__LOCATION__FORMALS);extern asmlinkage noreturnvoid deputy_fail_noreturn_fast(void);/* Search for a NULL starting at e and return its index */extern asmlinkageint deputy_findnull(const void *e1, unsigned int sz);//Define deputy_memset, which we use to initialize locals//FIXME: We should set __deputy_memset = __builtin_memset to take advantage //of optimizations. How do we do that in a portable way?#if defined(memset) && !defined(IN_DEPUTY_LIBRARY)#define __deputy_memset memset#elseextern asmlinkagevoid *__deputy_memset(void *s, int c, unsigned int n);#endif#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 asmlinkageint 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)#endifINLINE 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 + -