diff options
author | Eric Dumazet <edumazet@google.com> | 2013-01-30 20:51:44 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-30 22:38:34 -0500 |
commit | 3b58908a92e00840bcd9050808f3dc86fd547029 (patch) | |
tree | 3d3a2f97da69a5681a83cebf46e816e40670e34b /arch/x86/net | |
parent | 45acd3a0a18c5692b34ee9091858c6f6c7b5d4a8 (diff) |
x86: bpf_jit_comp: add pkt_type support
Supporting access to skb->pkt_type is a bit tricky if we want
to have a generic code, allowing pkt_type to be moved in struct sk_buff
pkt_type is a bit field, so compiler cannot really help us to find
its offset. Let's use a helper for this : It will throw a one time
message if pkt_type no longer starts at a byte boundary or is
no longer a 3bit field.
Reported-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Maciej Żenczykowski <maze@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/x86/net')
-rw-r--r-- | arch/x86/net/bpf_jit_comp.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index d11a47099d33..3cbe45381bbb 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* bpf_jit_comp.c : BPF JIT compiler | 1 | /* bpf_jit_comp.c : BPF JIT compiler |
2 | * | 2 | * |
3 | * Copyright (C) 2011 Eric Dumazet (eric.dumazet@gmail.com) | 3 | * Copyright (C) 2011-2013 Eric Dumazet (eric.dumazet@gmail.com) |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU General Public License | 6 | * modify it under the terms of the GNU General Public License |
@@ -124,6 +124,26 @@ static inline void bpf_flush_icache(void *start, void *end) | |||
124 | #define CHOOSE_LOAD_FUNC(K, func) \ | 124 | #define CHOOSE_LOAD_FUNC(K, func) \ |
125 | ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset) | 125 | ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset) |
126 | 126 | ||
127 | /* Helper to find the offset of pkt_type in sk_buff | ||
128 | * We want to make sure its still a 3bit field starting at a byte boundary. | ||
129 | */ | ||
130 | #define PKT_TYPE_MAX 7 | ||
131 | static int pkt_type_offset(void) | ||
132 | { | ||
133 | struct sk_buff skb_probe = { | ||
134 | .pkt_type = ~0, | ||
135 | }; | ||
136 | char *ct = (char *)&skb_probe; | ||
137 | unsigned int off; | ||
138 | |||
139 | for (off = 0; off < sizeof(struct sk_buff); off++) { | ||
140 | if (ct[off] == PKT_TYPE_MAX) | ||
141 | return off; | ||
142 | } | ||
143 | pr_err_once("Please fix pkt_type_offset(), as pkt_type couldn't be found\n"); | ||
144 | return -1; | ||
145 | } | ||
146 | |||
127 | void bpf_jit_compile(struct sk_filter *fp) | 147 | void bpf_jit_compile(struct sk_filter *fp) |
128 | { | 148 | { |
129 | u8 temp[64]; | 149 | u8 temp[64]; |
@@ -216,6 +236,7 @@ void bpf_jit_compile(struct sk_filter *fp) | |||
216 | case BPF_S_ANC_VLAN_TAG: | 236 | case BPF_S_ANC_VLAN_TAG: |
217 | case BPF_S_ANC_VLAN_TAG_PRESENT: | 237 | case BPF_S_ANC_VLAN_TAG_PRESENT: |
218 | case BPF_S_ANC_QUEUE: | 238 | case BPF_S_ANC_QUEUE: |
239 | case BPF_S_ANC_PKTTYPE: | ||
219 | case BPF_S_LD_W_ABS: | 240 | case BPF_S_LD_W_ABS: |
220 | case BPF_S_LD_H_ABS: | 241 | case BPF_S_LD_H_ABS: |
221 | case BPF_S_LD_B_ABS: | 242 | case BPF_S_LD_B_ABS: |
@@ -536,6 +557,23 @@ void bpf_jit_compile(struct sk_filter *fp) | |||
536 | EMIT3(0x83, 0xe0, 0x01); /* and $0x1,%eax */ | 557 | EMIT3(0x83, 0xe0, 0x01); /* and $0x1,%eax */ |
537 | } | 558 | } |
538 | break; | 559 | break; |
560 | case BPF_S_ANC_PKTTYPE: | ||
561 | { | ||
562 | int off = pkt_type_offset(); | ||
563 | |||
564 | if (off < 0) | ||
565 | goto out; | ||
566 | if (is_imm8(off)) { | ||
567 | /* movzbl off8(%rdi),%eax */ | ||
568 | EMIT4(0x0f, 0xb6, 0x47, off); | ||
569 | } else { | ||
570 | /* movbl off32(%rdi),%eax */ | ||
571 | EMIT3(0x0f, 0xb6, 0x87); | ||
572 | EMIT(off, 4); | ||
573 | } | ||
574 | EMIT3(0x83, 0xe0, PKT_TYPE_MAX); /* and $0x7,%eax */ | ||
575 | break; | ||
576 | } | ||
539 | case BPF_S_LD_W_ABS: | 577 | case BPF_S_LD_W_ABS: |
540 | func = CHOOSE_LOAD_FUNC(K, sk_load_word); | 578 | func = CHOOSE_LOAD_FUNC(K, sk_load_word); |
541 | common_load: seen |= SEEN_DATAREF; | 579 | common_load: seen |= SEEN_DATAREF; |