Loading net/core/filter.c +33 −57 Original line number Diff line number Diff line Loading @@ -36,7 +36,7 @@ #include <linux/filter.h> /* No hurry in this branch */ static u8 *load_pointer(struct sk_buff *skb, int k) static void *__load_pointer(struct sk_buff *skb, int k) { u8 *ptr = NULL; Loading @@ -50,6 +50,18 @@ static u8 *load_pointer(struct sk_buff *skb, int k) return NULL; } static inline void *load_pointer(struct sk_buff *skb, int k, unsigned int size, void *buffer) { if (k >= 0) return skb_header_pointer(skb, k, size, buffer); else { if (k >= SKF_AD_OFF) return NULL; return __load_pointer(skb, k); } } /** * sk_run_filter - run a filter on a socket * @skb: buffer to run the filter on Loading @@ -64,15 +76,16 @@ static u8 *load_pointer(struct sk_buff *skb, int k) int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen) { unsigned char *data = skb->data; /* len is UNSIGNED. Byte wide insns relies only on implicit type casts to prevent reading arbitrary memory locations. */ unsigned int len = skb->len-skb->data_len; struct sock_filter *fentry; /* We walk down these */ void *ptr; u32 A = 0; /* Accumulator */ u32 X = 0; /* Index Register */ u32 mem[BPF_MEMWORDS]; /* Scratch Memory Store */ u32 tmp; int k; int pc; Loading Loading @@ -168,68 +181,29 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen) case BPF_LD|BPF_W|BPF_ABS: k = fentry->k; load_w: if (k < 0) { u8 *ptr; if (k >= SKF_AD_OFF) break; ptr = load_pointer(skb, k); if (ptr) { ptr = load_pointer(skb, k, 4, &tmp); if (ptr != NULL) { A = ntohl(*(u32 *)ptr); continue; } } else { u32 _tmp, *p; p = skb_header_pointer(skb, k, 4, &_tmp); if (p != NULL) { A = ntohl(*p); continue; } } return 0; case BPF_LD|BPF_H|BPF_ABS: k = fentry->k; load_h: if (k < 0) { u8 *ptr; if (k >= SKF_AD_OFF) break; ptr = load_pointer(skb, k); if (ptr) { ptr = load_pointer(skb, k, 2, &tmp); if (ptr != NULL) { A = ntohs(*(u16 *)ptr); continue; } } else { u16 _tmp, *p; p = skb_header_pointer(skb, k, 2, &_tmp); if (p != NULL) { A = ntohs(*p); continue; } } return 0; case BPF_LD|BPF_B|BPF_ABS: k = fentry->k; load_b: if (k < 0) { u8 *ptr; if (k >= SKF_AD_OFF) break; ptr = load_pointer(skb, k); if (ptr) { A = *ptr; ptr = load_pointer(skb, k, 1, &tmp); if (ptr != NULL) { A = *(u8 *)ptr; continue; } } else { u8 _tmp, *p; p = skb_header_pointer(skb, k, 1, &_tmp); if (p != NULL) { A = *p; continue; } } return 0; case BPF_LD|BPF_W|BPF_LEN: A = len; Loading @@ -247,10 +221,12 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen) k = X + fentry->k; goto load_b; case BPF_LDX|BPF_B|BPF_MSH: if (fentry->k >= len) return 0; X = (data[fentry->k] & 0xf) << 2; ptr = load_pointer(skb, fentry->k, 1, &tmp); if (ptr != NULL) { X = (*(u8 *)ptr & 0xf) << 2; continue; } return 0; case BPF_LD|BPF_IMM: A = fentry->k; continue; Loading Loading
net/core/filter.c +33 −57 Original line number Diff line number Diff line Loading @@ -36,7 +36,7 @@ #include <linux/filter.h> /* No hurry in this branch */ static u8 *load_pointer(struct sk_buff *skb, int k) static void *__load_pointer(struct sk_buff *skb, int k) { u8 *ptr = NULL; Loading @@ -50,6 +50,18 @@ static u8 *load_pointer(struct sk_buff *skb, int k) return NULL; } static inline void *load_pointer(struct sk_buff *skb, int k, unsigned int size, void *buffer) { if (k >= 0) return skb_header_pointer(skb, k, size, buffer); else { if (k >= SKF_AD_OFF) return NULL; return __load_pointer(skb, k); } } /** * sk_run_filter - run a filter on a socket * @skb: buffer to run the filter on Loading @@ -64,15 +76,16 @@ static u8 *load_pointer(struct sk_buff *skb, int k) int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen) { unsigned char *data = skb->data; /* len is UNSIGNED. Byte wide insns relies only on implicit type casts to prevent reading arbitrary memory locations. */ unsigned int len = skb->len-skb->data_len; struct sock_filter *fentry; /* We walk down these */ void *ptr; u32 A = 0; /* Accumulator */ u32 X = 0; /* Index Register */ u32 mem[BPF_MEMWORDS]; /* Scratch Memory Store */ u32 tmp; int k; int pc; Loading Loading @@ -168,68 +181,29 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen) case BPF_LD|BPF_W|BPF_ABS: k = fentry->k; load_w: if (k < 0) { u8 *ptr; if (k >= SKF_AD_OFF) break; ptr = load_pointer(skb, k); if (ptr) { ptr = load_pointer(skb, k, 4, &tmp); if (ptr != NULL) { A = ntohl(*(u32 *)ptr); continue; } } else { u32 _tmp, *p; p = skb_header_pointer(skb, k, 4, &_tmp); if (p != NULL) { A = ntohl(*p); continue; } } return 0; case BPF_LD|BPF_H|BPF_ABS: k = fentry->k; load_h: if (k < 0) { u8 *ptr; if (k >= SKF_AD_OFF) break; ptr = load_pointer(skb, k); if (ptr) { ptr = load_pointer(skb, k, 2, &tmp); if (ptr != NULL) { A = ntohs(*(u16 *)ptr); continue; } } else { u16 _tmp, *p; p = skb_header_pointer(skb, k, 2, &_tmp); if (p != NULL) { A = ntohs(*p); continue; } } return 0; case BPF_LD|BPF_B|BPF_ABS: k = fentry->k; load_b: if (k < 0) { u8 *ptr; if (k >= SKF_AD_OFF) break; ptr = load_pointer(skb, k); if (ptr) { A = *ptr; ptr = load_pointer(skb, k, 1, &tmp); if (ptr != NULL) { A = *(u8 *)ptr; continue; } } else { u8 _tmp, *p; p = skb_header_pointer(skb, k, 1, &_tmp); if (p != NULL) { A = *p; continue; } } return 0; case BPF_LD|BPF_W|BPF_LEN: A = len; Loading @@ -247,10 +221,12 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen) k = X + fentry->k; goto load_b; case BPF_LDX|BPF_B|BPF_MSH: if (fentry->k >= len) return 0; X = (data[fentry->k] & 0xf) << 2; ptr = load_pointer(skb, fentry->k, 1, &tmp); if (ptr != NULL) { X = (*(u8 *)ptr & 0xf) << 2; continue; } return 0; case BPF_LD|BPF_IMM: A = fentry->k; continue; Loading