diff options
-rw-r--r-- | Documentation/networking/filter.txt | 13 | ||||
-rw-r--r-- | include/linux/filter.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/filter.h | 3 | ||||
-rw-r--r-- | net/core/filter.c | 12 | ||||
-rw-r--r-- | tools/net/bpf_exp.l | 1 | ||||
-rw-r--r-- | tools/net/bpf_exp.y | 11 |
6 files changed, 39 insertions, 2 deletions
diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt index 81f940f4e884..82e1cb0b3da8 100644 --- a/Documentation/networking/filter.txt +++ b/Documentation/networking/filter.txt | |||
@@ -281,6 +281,7 @@ Possible BPF extensions are shown in the following table: | |||
281 | cpu raw_smp_processor_id() | 281 | cpu raw_smp_processor_id() |
282 | vlan_tci vlan_tx_tag_get(skb) | 282 | vlan_tci vlan_tx_tag_get(skb) |
283 | vlan_pr vlan_tx_tag_present(skb) | 283 | vlan_pr vlan_tx_tag_present(skb) |
284 | rand prandom_u32() | ||
284 | 285 | ||
285 | These extensions can also be prefixed with '#'. | 286 | These extensions can also be prefixed with '#'. |
286 | Examples for low-level BPF: | 287 | Examples for low-level BPF: |
@@ -308,6 +309,18 @@ Examples for low-level BPF: | |||
308 | ret #-1 | 309 | ret #-1 |
309 | drop: ret #0 | 310 | drop: ret #0 |
310 | 311 | ||
312 | ** icmp random packet sampling, 1 in 4 | ||
313 | ldh [12] | ||
314 | jne #0x800, drop | ||
315 | ldb [23] | ||
316 | jneq #1, drop | ||
317 | # get a random uint32 number | ||
318 | ld rand | ||
319 | mod #4 | ||
320 | jneq #1, drop | ||
321 | ret #-1 | ||
322 | drop: ret #0 | ||
323 | |||
311 | ** SECCOMP filter example: | 324 | ** SECCOMP filter example: |
312 | 325 | ||
313 | ld [4] /* offsetof(struct seccomp_data, arch) */ | 326 | ld [4] /* offsetof(struct seccomp_data, arch) */ |
diff --git a/include/linux/filter.h b/include/linux/filter.h index 024fd03e5d18..759abf78dd61 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h | |||
@@ -223,6 +223,7 @@ enum { | |||
223 | BPF_S_ANC_VLAN_TAG, | 223 | BPF_S_ANC_VLAN_TAG, |
224 | BPF_S_ANC_VLAN_TAG_PRESENT, | 224 | BPF_S_ANC_VLAN_TAG_PRESENT, |
225 | BPF_S_ANC_PAY_OFFSET, | 225 | BPF_S_ANC_PAY_OFFSET, |
226 | BPF_S_ANC_RANDOM, | ||
226 | }; | 227 | }; |
227 | 228 | ||
228 | #endif /* __LINUX_FILTER_H__ */ | 229 | #endif /* __LINUX_FILTER_H__ */ |
diff --git a/include/uapi/linux/filter.h b/include/uapi/linux/filter.h index 8eb9ccaa5b48..253b4d42cf2b 100644 --- a/include/uapi/linux/filter.h +++ b/include/uapi/linux/filter.h | |||
@@ -130,7 +130,8 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */ | |||
130 | #define SKF_AD_VLAN_TAG 44 | 130 | #define SKF_AD_VLAN_TAG 44 |
131 | #define SKF_AD_VLAN_TAG_PRESENT 48 | 131 | #define SKF_AD_VLAN_TAG_PRESENT 48 |
132 | #define SKF_AD_PAY_OFFSET 52 | 132 | #define SKF_AD_PAY_OFFSET 52 |
133 | #define SKF_AD_MAX 56 | 133 | #define SKF_AD_RANDOM 56 |
134 | #define SKF_AD_MAX 60 | ||
134 | #define SKF_NET_OFF (-0x100000) | 135 | #define SKF_NET_OFF (-0x100000) |
135 | #define SKF_LL_OFF (-0x200000) | 136 | #define SKF_LL_OFF (-0x200000) |
136 | 137 | ||
diff --git a/net/core/filter.c b/net/core/filter.c index cd58614660cf..78a636e60a0b 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -643,6 +643,12 @@ static u64 __get_raw_cpu_id(u64 ctx, u64 A, u64 X, u64 r4, u64 r5) | |||
643 | return raw_smp_processor_id(); | 643 | return raw_smp_processor_id(); |
644 | } | 644 | } |
645 | 645 | ||
646 | /* note that this only generates 32-bit random numbers */ | ||
647 | static u64 __get_random_u32(u64 ctx, u64 A, u64 X, u64 r4, u64 r5) | ||
648 | { | ||
649 | return (u64)prandom_u32(); | ||
650 | } | ||
651 | |||
646 | /* Register mappings for user programs. */ | 652 | /* Register mappings for user programs. */ |
647 | #define A_REG 0 | 653 | #define A_REG 0 |
648 | #define X_REG 7 | 654 | #define X_REG 7 |
@@ -779,6 +785,7 @@ static bool convert_bpf_extensions(struct sock_filter *fp, | |||
779 | case SKF_AD_OFF + SKF_AD_NLATTR: | 785 | case SKF_AD_OFF + SKF_AD_NLATTR: |
780 | case SKF_AD_OFF + SKF_AD_NLATTR_NEST: | 786 | case SKF_AD_OFF + SKF_AD_NLATTR_NEST: |
781 | case SKF_AD_OFF + SKF_AD_CPU: | 787 | case SKF_AD_OFF + SKF_AD_CPU: |
788 | case SKF_AD_OFF + SKF_AD_RANDOM: | ||
782 | /* arg1 = ctx */ | 789 | /* arg1 = ctx */ |
783 | insn->code = BPF_ALU64 | BPF_MOV | BPF_X; | 790 | insn->code = BPF_ALU64 | BPF_MOV | BPF_X; |
784 | insn->a_reg = ARG1_REG; | 791 | insn->a_reg = ARG1_REG; |
@@ -812,6 +819,9 @@ static bool convert_bpf_extensions(struct sock_filter *fp, | |||
812 | case SKF_AD_OFF + SKF_AD_CPU: | 819 | case SKF_AD_OFF + SKF_AD_CPU: |
813 | insn->imm = __get_raw_cpu_id - __bpf_call_base; | 820 | insn->imm = __get_raw_cpu_id - __bpf_call_base; |
814 | break; | 821 | break; |
822 | case SKF_AD_OFF + SKF_AD_RANDOM: | ||
823 | insn->imm = __get_random_u32 - __bpf_call_base; | ||
824 | break; | ||
815 | } | 825 | } |
816 | break; | 826 | break; |
817 | 827 | ||
@@ -1362,6 +1372,7 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen) | |||
1362 | ANCILLARY(VLAN_TAG); | 1372 | ANCILLARY(VLAN_TAG); |
1363 | ANCILLARY(VLAN_TAG_PRESENT); | 1373 | ANCILLARY(VLAN_TAG_PRESENT); |
1364 | ANCILLARY(PAY_OFFSET); | 1374 | ANCILLARY(PAY_OFFSET); |
1375 | ANCILLARY(RANDOM); | ||
1365 | } | 1376 | } |
1366 | 1377 | ||
1367 | /* ancillary operation unknown or unsupported */ | 1378 | /* ancillary operation unknown or unsupported */ |
@@ -1746,6 +1757,7 @@ void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to) | |||
1746 | [BPF_S_ANC_VLAN_TAG] = BPF_LD|BPF_B|BPF_ABS, | 1757 | [BPF_S_ANC_VLAN_TAG] = BPF_LD|BPF_B|BPF_ABS, |
1747 | [BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS, | 1758 | [BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS, |
1748 | [BPF_S_ANC_PAY_OFFSET] = BPF_LD|BPF_B|BPF_ABS, | 1759 | [BPF_S_ANC_PAY_OFFSET] = BPF_LD|BPF_B|BPF_ABS, |
1760 | [BPF_S_ANC_RANDOM] = BPF_LD|BPF_B|BPF_ABS, | ||
1749 | [BPF_S_LD_W_LEN] = BPF_LD|BPF_W|BPF_LEN, | 1761 | [BPF_S_LD_W_LEN] = BPF_LD|BPF_W|BPF_LEN, |
1750 | [BPF_S_LD_W_IND] = BPF_LD|BPF_W|BPF_IND, | 1762 | [BPF_S_LD_W_IND] = BPF_LD|BPF_W|BPF_IND, |
1751 | [BPF_S_LD_H_IND] = BPF_LD|BPF_H|BPF_IND, | 1763 | [BPF_S_LD_H_IND] = BPF_LD|BPF_H|BPF_IND, |
diff --git a/tools/net/bpf_exp.l b/tools/net/bpf_exp.l index bf7be77ddd62..833a96611da6 100644 --- a/tools/net/bpf_exp.l +++ b/tools/net/bpf_exp.l | |||
@@ -92,6 +92,7 @@ extern void yyerror(const char *str); | |||
92 | "#"?("cpu") { return K_CPU; } | 92 | "#"?("cpu") { return K_CPU; } |
93 | "#"?("vlan_tci") { return K_VLANT; } | 93 | "#"?("vlan_tci") { return K_VLANT; } |
94 | "#"?("vlan_pr") { return K_VLANP; } | 94 | "#"?("vlan_pr") { return K_VLANP; } |
95 | "#"?("rand") { return K_RAND; } | ||
95 | 96 | ||
96 | ":" { return ':'; } | 97 | ":" { return ':'; } |
97 | "," { return ','; } | 98 | "," { return ','; } |
diff --git a/tools/net/bpf_exp.y b/tools/net/bpf_exp.y index d15efc989ef5..e6306c51c26f 100644 --- a/tools/net/bpf_exp.y +++ b/tools/net/bpf_exp.y | |||
@@ -56,7 +56,7 @@ static void bpf_set_jmp_label(char *label, enum jmp_type type); | |||
56 | %token OP_LDXI | 56 | %token OP_LDXI |
57 | 57 | ||
58 | %token K_PKT_LEN K_PROTO K_TYPE K_NLATTR K_NLATTR_NEST K_MARK K_QUEUE K_HATYPE | 58 | %token K_PKT_LEN K_PROTO K_TYPE K_NLATTR K_NLATTR_NEST K_MARK K_QUEUE K_HATYPE |
59 | %token K_RXHASH K_CPU K_IFIDX K_VLANT K_VLANP K_POFF | 59 | %token K_RXHASH K_CPU K_IFIDX K_VLANT K_VLANP K_POFF K_RAND |
60 | 60 | ||
61 | %token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%' | 61 | %token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%' |
62 | 62 | ||
@@ -164,6 +164,9 @@ ldb | |||
164 | | OP_LDB K_POFF { | 164 | | OP_LDB K_POFF { |
165 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | 165 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, |
166 | SKF_AD_OFF + SKF_AD_PAY_OFFSET); } | 166 | SKF_AD_OFF + SKF_AD_PAY_OFFSET); } |
167 | | OP_LDB K_RAND { | ||
168 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
169 | SKF_AD_OFF + SKF_AD_RANDOM); } | ||
167 | ; | 170 | ; |
168 | 171 | ||
169 | ldh | 172 | ldh |
@@ -212,6 +215,9 @@ ldh | |||
212 | | OP_LDH K_POFF { | 215 | | OP_LDH K_POFF { |
213 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | 216 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, |
214 | SKF_AD_OFF + SKF_AD_PAY_OFFSET); } | 217 | SKF_AD_OFF + SKF_AD_PAY_OFFSET); } |
218 | | OP_LDH K_RAND { | ||
219 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
220 | SKF_AD_OFF + SKF_AD_RANDOM); } | ||
215 | ; | 221 | ; |
216 | 222 | ||
217 | ldi | 223 | ldi |
@@ -265,6 +271,9 @@ ld | |||
265 | | OP_LD K_POFF { | 271 | | OP_LD K_POFF { |
266 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | 272 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, |
267 | SKF_AD_OFF + SKF_AD_PAY_OFFSET); } | 273 | SKF_AD_OFF + SKF_AD_PAY_OFFSET); } |
274 | | OP_LD K_RAND { | ||
275 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
276 | SKF_AD_OFF + SKF_AD_RANDOM); } | ||
268 | | OP_LD 'M' '[' number ']' { | 277 | | OP_LD 'M' '[' number ']' { |
269 | bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); } | 278 | bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); } |
270 | | OP_LD '[' 'x' '+' number ']' { | 279 | | OP_LD '[' 'x' '+' number ']' { |