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>
This commit is contained in:
		
							parent
							
								
									45acd3a0a1
								
							
						
					
					
						commit
						3b58908a92
					
				| @ -1,6 +1,6 @@ | ||||
| /* 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 | ||||
|  * 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) | ||||
| #define CHOOSE_LOAD_FUNC(K, func) \ | ||||
| 	((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) | ||||
| { | ||||
| 	u8 temp[64]; | ||||
| @ -216,6 +236,7 @@ void bpf_jit_compile(struct sk_filter *fp) | ||||
| 		case BPF_S_ANC_VLAN_TAG: | ||||
| 		case BPF_S_ANC_VLAN_TAG_PRESENT: | ||||
| 		case BPF_S_ANC_QUEUE: | ||||
| 		case BPF_S_ANC_PKTTYPE: | ||||
| 		case BPF_S_LD_W_ABS: | ||||
| 		case BPF_S_LD_H_ABS: | ||||
| 		case BPF_S_LD_B_ABS: | ||||
| @ -536,6 +557,23 @@ void bpf_jit_compile(struct sk_filter *fp) | ||||
| 					EMIT3(0x83, 0xe0, 0x01); /* and    $0x1,%eax */ | ||||
| 				} | ||||
| 				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: | ||||
| 				func = CHOOSE_LOAD_FUNC(K, sk_load_word); | ||||
| common_load:			seen |= SEEN_DATAREF; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user