#define _GNU_SOURCE #include #include #include #include #include #include #include #include /* ================= Configuration ================= */ /* Ingestion cap (intentionally lower than mutator working size) */ #define MAX_INPUT_SIZE (32 * 1024) /* Large enough to let parse_rtattr build pointer tables */ #define MAX_ATTRS 512 /* Deeper than mutator to amplify malformed nesting */ #define MAX_NEST_DEPTH 16 /* ================= Globals ================= */ static uint8_t scratch_buf[MAX_INPUT_SIZE]; static struct rtattr *attr_table[MAX_ATTRS + 1]; /* ================= Unsafe attribute walker ================= */ /* Intentionally trusts rta_len and nested layout */ static void walk_attrs_unsafe(struct rtattr *rta, int len, int depth) { /* Trust len even if negative; only cap recursion depth */ if (!rta || depth > MAX_NEST_DEPTH) return; while (RTA_OK(rta, len)) { /* rta_len is attacker controlled */ int payload = rta->rta_len - (int)sizeof(*rta); /* Helpers may read OOB if payload is bogus */ if (payload >= 1) (void)rta_getattr_u8(rta); if (payload >= 2) (void)rta_getattr_u16(rta); if (payload >= 4) (void)rta_getattr_u32(rta); /* Treat payload as nested rtattrs without validation */ if (payload != 0) { struct rtattr *nested = (struct rtattr *)RTA_DATA(rta); walk_attrs_unsafe(nested, payload, depth + 1); } /* Advance using attacker-controlled length */ rta = RTA_NEXT(rta, len); } } /* ================= Main ================= */ int main(void) { ssize_t len = read(STDIN_FILENO, scratch_buf, sizeof(scratch_buf)); if (len <= 0) return 0; if (len > MAX_INPUT_SIZE) len = MAX_INPUT_SIZE; memset(attr_table, 0, sizeof(attr_table)); /* Primary parse — intentionally trusts rta_len */ parse_rtattr(attr_table, MAX_ATTRS, (struct rtattr *)scratch_buf, len); /* Secondary unsafe traversal */ for (int i = 0; i <= MAX_ATTRS; i++) { struct rtattr *rta = attr_table[i]; if (!rta) continue; /* Payload may be negative or oversized */ int payload = rta->rta_len - (int)sizeof(*rta); walk_attrs_unsafe(rta, payload, 0); } return 0; }