Messages in this thread | | | From | Dawson Engler <> | Subject | [CHECKER] buffer overflows in net/core/filter.c? | Date | Sun, 16 Oct 2005 02:36:21 -0700 (PDT) |
| |
Hi,
it appears that bad filters in net/core/filter.c can read/write arbitrary kernel memory.
Given a filter created via:
struct sock_filter s[2]; memset(s, 0, sizeof s);
s[0].code = BPF_LD|BPF_B|BPF_ABS; s[0].k = 0x7fffffffUL; s[1].code = BPF_RET; s[1].k = 0xfffffff0UL;
or:
s[0].code = BPF_LD|BPF_B|BPF_IND; s[0].k = 0x7fffffffUL; s[1].code = BPF_RET; s[1].k = 0xfffffff0UL;
or
s[0].code = BPF_LD|BPF_H|BPF_IND; s[0].k = 0x7ffffffeUL; s[1].code = BPF_B|BPF_RET; s[1].k = 0xfffffff0UL;
or
s[0].code = BPF_LD|BPF_H|BPF_IND; s[0].k = 0x7ffffffeUL; s[1].code = BPF_B|BPF_RET; s[1].k = 0xfffffff0UL;
These pass check filter calls:
sk_chk_filter(s, 2)
But then blow up severely after calling:
static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer) { int hlen = skb_headlen(skb);
which increments the data pointer:
if (offset + len <= hlen) return skb->data + offset;
but does not check if (offset+len) could overflow.
Something gross along the lines of:
if((offset + len) < offset) { printf("ERROR: hit overflow!\n"); return NULL; }
seems to fix the problem, but most likely filter.c should do it.
If anyone could confirm or refute these I'd appreciate it. [We've been developing a tool to automatically generate test cases by running code partially symbolically and these were some of first errors it flagged.]
Dawson - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |