Commit 3b58908a authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

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: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Cc: Maciej Żenczykowski <maze@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 45acd3a0
/* bpf_jit_comp.c : BPF JIT compiler /* bpf_jit_comp.c : BPF JIT compiler
* *
* Copyright (C) 2011 Eric Dumazet (eric.dumazet@gmail.com) * Copyright (C) 2011-2013 Eric Dumazet (eric.dumazet@gmail.com)
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * 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,6 +124,26 @@ static inline void bpf_flush_icache(void *start, void *end)
#define CHOOSE_LOAD_FUNC(K, func) \ #define CHOOSE_LOAD_FUNC(K, func) \
((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset) ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
/* Helper to find the offset of pkt_type in sk_buff
* We want to make sure its still a 3bit field starting at a byte boundary.
*/
#define PKT_TYPE_MAX 7
static int pkt_type_offset(void)
{
struct sk_buff skb_probe = {
.pkt_type = ~0,
};
char *ct = (char *)&skb_probe;
unsigned int off;
for (off = 0; off < sizeof(struct sk_buff); off++) {
if (ct[off] == PKT_TYPE_MAX)
return off;
}
pr_err_once("Please fix pkt_type_offset(), as pkt_type couldn't be found\n");
return -1;
}
void bpf_jit_compile(struct sk_filter *fp) void bpf_jit_compile(struct sk_filter *fp)
{ {
u8 temp[64]; u8 temp[64];
...@@ -216,6 +236,7 @@ void bpf_jit_compile(struct sk_filter *fp) ...@@ -216,6 +236,7 @@ void bpf_jit_compile(struct sk_filter *fp)
case BPF_S_ANC_VLAN_TAG: case BPF_S_ANC_VLAN_TAG:
case BPF_S_ANC_VLAN_TAG_PRESENT: case BPF_S_ANC_VLAN_TAG_PRESENT:
case BPF_S_ANC_QUEUE: case BPF_S_ANC_QUEUE:
case BPF_S_ANC_PKTTYPE:
case BPF_S_LD_W_ABS: case BPF_S_LD_W_ABS:
case BPF_S_LD_H_ABS: case BPF_S_LD_H_ABS:
case BPF_S_LD_B_ABS: case BPF_S_LD_B_ABS:
...@@ -536,6 +557,23 @@ void bpf_jit_compile(struct sk_filter *fp) ...@@ -536,6 +557,23 @@ void bpf_jit_compile(struct sk_filter *fp)
EMIT3(0x83, 0xe0, 0x01); /* and $0x1,%eax */ EMIT3(0x83, 0xe0, 0x01); /* and $0x1,%eax */
} }
break; break;
case BPF_S_ANC_PKTTYPE:
{
int off = pkt_type_offset();
if (off < 0)
goto out;
if (is_imm8(off)) {
/* movzbl off8(%rdi),%eax */
EMIT4(0x0f, 0xb6, 0x47, off);
} else {
/* movbl off32(%rdi),%eax */
EMIT3(0x0f, 0xb6, 0x87);
EMIT(off, 4);
}
EMIT3(0x83, 0xe0, PKT_TYPE_MAX); /* and $0x7,%eax */
break;
}
case BPF_S_LD_W_ABS: case BPF_S_LD_W_ABS:
func = CHOOSE_LOAD_FUNC(K, sk_load_word); func = CHOOSE_LOAD_FUNC(K, sk_load_word);
common_load: seen |= SEEN_DATAREF; common_load: seen |= SEEN_DATAREF;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment