sanitize_helper.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2020. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. *
  31. * The following software/firmware and/or related documentation ("MediaTek Software")
  32. * have been modified by MediaTek Inc. All revisions are subject to any receiver\'s
  33. * applicable license agreements with MediaTek Inc.
  34. */
  35. #include <printf.h>
  36. #include <stdlib.h>
  37. #define SANI_SHOW(fmt, ...) dprintf(CRITICAL, fmt, ##__VA_ARGS__)
  38. #define SANI_ABORT() panic("sanitizer")
  39. typedef struct _type_desc
  40. {
  41. #define UB_SIGNED(type) ((type)->info&1)
  42. #define UB_BITS(type) (1U << ((type)->info >> 1))
  43. #define UB_VAL(type, val) (sizeof(long) * 8 >= UB_BITS(type) ? (unsigned long)(val) : *(unsigned long long *)(val))
  44. unsigned short kind, info;
  45. char name[1];
  46. } type_desc;
  47. typedef struct _src_loc
  48. {
  49. const char *file;
  50. unsigned line, col;
  51. } src_loc;
  52. static bool ub_skip(src_loc *loc)
  53. {
  54. #define UB_SKIP_VAL (1U << 31)
  55. if ((loc->line&UB_SKIP_VAL)
  56. || !strncmp(loc->file, "lib/", sizeof("lib/") - 1)
  57. || !strncmp(loc->file, "kernel/", sizeof("kernel/") - 1)
  58. || !strncmp(loc->file, "arch/", sizeof("arch/") - 1)
  59. || !strncmp(loc->file, "platform/common/avb/libavb/", sizeof("platform/common/avb/libavb/") - 1))
  60. return true;
  61. SANI_SHOW("UBSAN detect at <%s:%u:%u>\n", loc->file, loc->line, loc->col);
  62. loc->line |= UB_SKIP_VAL;
  63. return false;
  64. }
  65. static void ub_val2str(char *str, unsigned size, type_desc *type, void *val)
  66. {
  67. unsigned long long x;
  68. int extra_bits;
  69. long long ll_x;
  70. if (size < 2)
  71. return;
  72. str[0] = '\0';
  73. if (type->kind)
  74. return;
  75. if (UB_SIGNED(type)) {
  76. extra_bits = sizeof(long) * 8 - UB_BITS(type);
  77. ll_x = (extra_bits >= 0 ? ((long)((unsigned long)val << extra_bits)) >> extra_bits : *(long long *)val);
  78. snprintf(str, size, "%lld", ll_x);
  79. } else {
  80. x = UB_VAL(type, val);
  81. snprintf(str, size, "%llu", x);
  82. }
  83. }
  84. static void ub_handle_type_mismatch(src_loc *loc, type_desc *type, unsigned long align, unsigned kind, void *ptr)
  85. {
  86. static const char * const kinds[] =
  87. {
  88. "load of","store to","reference binding to","member access within",
  89. "member call on","constructor call on","downcast of","downcast of",
  90. };
  91. if (ub_skip(loc))
  92. return;
  93. if (!ptr)
  94. SANI_SHOW("%s null ptr(type: %s)\n", kinds[kind], type->name);
  95. else if (align && ((unsigned long)ptr&(align - 1)))
  96. SANI_SHOW("%s misaligned address %p(type: %s, align: %luB)\n", kinds[kind], ptr, type->name, align);
  97. else
  98. SANI_SHOW("%s address %p(type: %s) with insufficient space\n", kinds[kind], ptr, type->name);
  99. SANI_ABORT();
  100. }
  101. static void ub_handle_int_overflow(void *data, void *lval, void *rval, char op)
  102. {
  103. struct
  104. {
  105. src_loc loc;
  106. type_desc *type;
  107. } *inf = data;
  108. char lstr[24], rstr[24];
  109. if (ub_skip(&inf->loc))
  110. return;
  111. ub_val2str(lstr, sizeof(lstr), inf->type, lval);
  112. ub_val2str(rstr, sizeof(rstr), inf->type, rval);
  113. SANI_SHOW("int overflow: %s %c %s can't be represented in type %s\n", lstr, op, rstr, inf->type->name);
  114. SANI_ABORT();
  115. }
  116. /* === compiler interface === */
  117. void __ubsan_handle_add_overflow(void *data, void *lval, void *rval)
  118. {
  119. ub_handle_int_overflow(data, lval, rval, '+');
  120. }
  121. void __ubsan_handle_sub_overflow(void *data, void *lval, void *rval)
  122. {
  123. ub_handle_int_overflow(data, lval, rval, '-');
  124. }
  125. void __ubsan_handle_mul_overflow(void *data, void *lval, void *rval)
  126. {
  127. ub_handle_int_overflow(data, lval, rval, '*');
  128. }
  129. void __ubsan_handle_divrem_overflow(void *data, void *lval, void *rval)
  130. {
  131. ub_handle_int_overflow(data, lval, rval, '/');
  132. }
  133. void __ubsan_handle_negate_overflow(void *data, void *val)
  134. {
  135. struct
  136. {
  137. src_loc loc;
  138. type_desc *type;
  139. } *inf = data;
  140. char str[24];
  141. if (ub_skip(&inf->loc))
  142. return;
  143. ub_val2str(str, sizeof(str), inf->type, val);
  144. SANI_SHOW("neg of %s can't be represented in type %s\n", str, inf->type->name);
  145. SANI_ABORT();
  146. }
  147. void __ubsan_handle_type_mismatch_v1(void *data, void *ptr)
  148. {
  149. struct
  150. {
  151. src_loc loc;
  152. type_desc *type;
  153. unsigned char log_align, kind;
  154. } *inf = data;
  155. ub_handle_type_mismatch(&inf->loc, inf->type, 1UL << inf->log_align, inf->kind, ptr);
  156. }
  157. void __ubsan_handle_type_mismatch(void *data, void *ptr)
  158. {
  159. struct
  160. {
  161. src_loc loc;
  162. type_desc *type;
  163. unsigned long align;
  164. unsigned char kind;
  165. } *inf = data;
  166. ub_handle_type_mismatch(&inf->loc, inf->type, inf->align, inf->kind, ptr);
  167. }
  168. void __ubsan_handle_nonnull_return(void *data)
  169. {
  170. struct
  171. {
  172. src_loc loc, attr_loc;
  173. } *inf = data;
  174. if (ub_skip(&inf->loc))
  175. return;
  176. SANI_SHOW("func return null ptr\n");
  177. if (inf->attr_loc.file)
  178. SANI_SHOW("returns_nonnull attribute specified in <%s:%u:%u>\n", inf->attr_loc.file
  179. , inf->attr_loc.line&0x7FFFFFFF, inf->attr_loc.col);
  180. SANI_ABORT();
  181. }
  182. void __ubsan_handle_shift_out_of_bounds(void *data, void *lval, void *rval)
  183. {
  184. struct
  185. {
  186. src_loc loc;
  187. type_desc *ltype, *rtype;
  188. } *inf = data;
  189. const unsigned lbits = UB_BITS(inf->ltype);
  190. char lstr[24], rstr[24];
  191. if (ub_skip(&inf->loc))
  192. return;
  193. ub_val2str(lstr, sizeof(lstr), inf->ltype, lval);
  194. ub_val2str(rstr, sizeof(rstr), inf->rtype, rval);
  195. if (rstr[0] == '-')
  196. SANI_SHOW("shift exponent %s is neg\n", rstr);
  197. else if (UB_VAL(inf->rtype, rval) >= lbits)
  198. SANI_SHOW("shift exponent %s is too large for %ubit type %s\n", rstr, lbits, inf->ltype->name);
  199. else if (lstr[0] == '-')
  200. SANI_SHOW("left shift of neg value %s\n", lstr);
  201. else
  202. SANI_SHOW("left shift of %s by %s places can't be represented in type %s\n", lstr, rstr, inf->ltype->name);
  203. SANI_ABORT();
  204. }
  205. void __ubsan_handle_out_of_bounds(void *data, void *index)
  206. {
  207. struct
  208. {
  209. src_loc loc;
  210. type_desc *type, *idx_type;
  211. } *inf = data;
  212. char str[24];
  213. if (ub_skip(&inf->loc))
  214. return;
  215. ub_val2str(str, sizeof(str), inf->idx_type, index);
  216. SANI_SHOW("index %s(type: %s) is out of range\n", str, inf->type->name);
  217. SANI_ABORT();
  218. }
  219. void __ubsan_handle_builtin_unreachable(src_loc *loc)
  220. {
  221. if (ub_skip(loc))
  222. return;
  223. SANI_SHOW("calling __builtin_unreachable()\n");
  224. SANI_ABORT();
  225. }
  226. void __ubsan_handle_load_invalid_value(void *data, void *val)
  227. {
  228. struct
  229. {
  230. src_loc loc;
  231. type_desc *type;
  232. } *inf = data;
  233. char str[24];
  234. if (ub_skip(&inf->loc))
  235. return;
  236. ub_val2str(str, sizeof(str), inf->type, val);
  237. SANI_SHOW("%s(type: %s) is not a valid load value\n", str, inf->type->name);
  238. SANI_ABORT();
  239. }