+static void
+add_blacklist_entry(const char *kext, const char *func, access_t type)
+{
+ assert(kext || func);
+ struct blacklist_entry *ble = &blacklist[blacklist_entries++];
+
+ if (blacklist_entries > blacklist_max_entries) {
+ panic("KASan: dynamic blacklist entries exhausted\n");
+ }
+
+ if (kext) {
+ size_t sz = __nosan_strlen(kext) + 1;
+ if (sz > 1) {
+ char *s = kalloc(sz);
+ __nosan_strlcpy(s, kext, sz);
+ ble->kext_name = s;
+ }
+ }
+
+ if (func) {
+ size_t sz = __nosan_strlen(func) + 1;
+ if (sz > 1) {
+ char *s = kalloc(sz);
+ __nosan_strlcpy(s, func, sz);
+ ble->func_name = s;
+ }
+ }
+
+ ble->type_mask = type;
+}
+
+#define TS(x) { .type = TYPE_##x, .str = #x }
+
+static const struct {
+ const access_t type;
+ const char * const str;
+} typemap[] = {
+ TS(LOAD),
+ TS(STORE),
+ TS(MEMR),
+ TS(MEMW),
+ TS(STRR),
+ TS(STRW),
+ TS(KFREE),
+ TS(ZFREE),
+ TS(FSFREE),
+ TS(UAF),
+ TS(POISON_GLOBAL),
+ TS(POISON_HEAP),
+ TS(MEM),
+ TS(STR),
+ TS(READ),
+ TS(WRITE),
+ TS(RW),
+ TS(FREE),
+ TS(NORMAL),
+ TS(DYNAMIC),
+ TS(POISON),
+ TS(ALL),
+
+ /* convenience aliases */
+ { .type = TYPE_POISON_GLOBAL, .str = "GLOB" },
+ { .type = TYPE_POISON_HEAP, .str = "HEAP" },
+};
+static size_t typemap_sz = sizeof(typemap)/sizeof(typemap[0]);
+
+static inline access_t
+map_type(const char *str)
+{
+ if (strlen(str) == 0) {
+ return TYPE_NORMAL;
+ }
+
+ /* convert type string to integer ID */
+ for (size_t i = 0; i < typemap_sz; i++) {
+ if (strcasecmp(str, typemap[i].str) == 0) {
+ return typemap[i].type;
+ }
+ }
+
+ printf("KASan: unknown blacklist type `%s', assuming `normal'\n", str);
+ return TYPE_NORMAL;
+}
+