aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/filter.h48
-rw-r--r--net/core/filter.c212
2 files changed, 209 insertions, 51 deletions
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 151f5d703b7e..69b43dbea6c6 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -91,6 +91,54 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
91#define BPF_TAX 0x00 91#define BPF_TAX 0x00
92#define BPF_TXA 0x80 92#define BPF_TXA 0x80
93 93
94enum {
95 BPF_S_RET_K = 0,
96 BPF_S_RET_A,
97 BPF_S_ALU_ADD_K,
98 BPF_S_ALU_ADD_X,
99 BPF_S_ALU_SUB_K,
100 BPF_S_ALU_SUB_X,
101 BPF_S_ALU_MUL_K,
102 BPF_S_ALU_MUL_X,
103 BPF_S_ALU_DIV_X,
104 BPF_S_ALU_AND_K,
105 BPF_S_ALU_AND_X,
106 BPF_S_ALU_OR_K,
107 BPF_S_ALU_OR_X,
108 BPF_S_ALU_LSH_K,
109 BPF_S_ALU_LSH_X,
110 BPF_S_ALU_RSH_K,
111 BPF_S_ALU_RSH_X,
112 BPF_S_ALU_NEG,
113 BPF_S_LD_W_ABS,
114 BPF_S_LD_H_ABS,
115 BPF_S_LD_B_ABS,
116 BPF_S_LD_W_LEN,
117 BPF_S_LD_W_IND,
118 BPF_S_LD_H_IND,
119 BPF_S_LD_B_IND,
120 BPF_S_LD_IMM,
121 BPF_S_LDX_W_LEN,
122 BPF_S_LDX_B_MSH,
123 BPF_S_LDX_IMM,
124 BPF_S_MISC_TAX,
125 BPF_S_MISC_TXA,
126 BPF_S_ALU_DIV_K,
127 BPF_S_LD_MEM,
128 BPF_S_LDX_MEM,
129 BPF_S_ST,
130 BPF_S_STX,
131 BPF_S_JMP_JA,
132 BPF_S_JMP_JEQ_K,
133 BPF_S_JMP_JEQ_X,
134 BPF_S_JMP_JGE_K,
135 BPF_S_JMP_JGE_X,
136 BPF_S_JMP_JGT_K,
137 BPF_S_JMP_JGT_X,
138 BPF_S_JMP_JSET_K,
139 BPF_S_JMP_JSET_X,
140};
141
94#ifndef BPF_MAXINSNS 142#ifndef BPF_MAXINSNS
95#define BPF_MAXINSNS 4096 143#define BPF_MAXINSNS 4096
96#endif 144#endif
diff --git a/net/core/filter.c b/net/core/filter.c
index da69fb728d32..52b051f82a01 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -128,87 +128,87 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int
128 fentry = &filter[pc]; 128 fentry = &filter[pc];
129 129
130 switch (fentry->code) { 130 switch (fentry->code) {
131 case BPF_ALU|BPF_ADD|BPF_X: 131 case BPF_S_ALU_ADD_X:
132 A += X; 132 A += X;
133 continue; 133 continue;
134 case BPF_ALU|BPF_ADD|BPF_K: 134 case BPF_S_ALU_ADD_K:
135 A += fentry->k; 135 A += fentry->k;
136 continue; 136 continue;
137 case BPF_ALU|BPF_SUB|BPF_X: 137 case BPF_S_ALU_SUB_X:
138 A -= X; 138 A -= X;
139 continue; 139 continue;
140 case BPF_ALU|BPF_SUB|BPF_K: 140 case BPF_S_ALU_SUB_K:
141 A -= fentry->k; 141 A -= fentry->k;
142 continue; 142 continue;
143 case BPF_ALU|BPF_MUL|BPF_X: 143 case BPF_S_ALU_MUL_X:
144 A *= X; 144 A *= X;
145 continue; 145 continue;
146 case BPF_ALU|BPF_MUL|BPF_K: 146 case BPF_S_ALU_MUL_K:
147 A *= fentry->k; 147 A *= fentry->k;
148 continue; 148 continue;
149 case BPF_ALU|BPF_DIV|BPF_X: 149 case BPF_S_ALU_DIV_X:
150 if (X == 0) 150 if (X == 0)
151 return 0; 151 return 0;
152 A /= X; 152 A /= X;
153 continue; 153 continue;
154 case BPF_ALU|BPF_DIV|BPF_K: 154 case BPF_S_ALU_DIV_K:
155 A /= fentry->k; 155 A /= fentry->k;
156 continue; 156 continue;
157 case BPF_ALU|BPF_AND|BPF_X: 157 case BPF_S_ALU_AND_X:
158 A &= X; 158 A &= X;
159 continue; 159 continue;
160 case BPF_ALU|BPF_AND|BPF_K: 160 case BPF_S_ALU_AND_K:
161 A &= fentry->k; 161 A &= fentry->k;
162 continue; 162 continue;
163 case BPF_ALU|BPF_OR|BPF_X: 163 case BPF_S_ALU_OR_X:
164 A |= X; 164 A |= X;
165 continue; 165 continue;
166 case BPF_ALU|BPF_OR|BPF_K: 166 case BPF_S_ALU_OR_K:
167 A |= fentry->k; 167 A |= fentry->k;
168 continue; 168 continue;
169 case BPF_ALU|BPF_LSH|BPF_X: 169 case BPF_S_ALU_LSH_X:
170 A <<= X; 170 A <<= X;
171 continue; 171 continue;
172 case BPF_ALU|BPF_LSH|BPF_K: 172 case BPF_S_ALU_LSH_K:
173 A <<= fentry->k; 173 A <<= fentry->k;
174 continue; 174 continue;
175 case BPF_ALU|BPF_RSH|BPF_X: 175 case BPF_S_ALU_RSH_X:
176 A >>= X; 176 A >>= X;
177 continue; 177 continue;
178 case BPF_ALU|BPF_RSH|BPF_K: 178 case BPF_S_ALU_RSH_K:
179 A >>= fentry->k; 179 A >>= fentry->k;
180 continue; 180 continue;
181 case BPF_ALU|BPF_NEG: 181 case BPF_S_ALU_NEG:
182 A = -A; 182 A = -A;
183 continue; 183 continue;
184 case BPF_JMP|BPF_JA: 184 case BPF_S_JMP_JA:
185 pc += fentry->k; 185 pc += fentry->k;
186 continue; 186 continue;
187 case BPF_JMP|BPF_JGT|BPF_K: 187 case BPF_S_JMP_JGT_K:
188 pc += (A > fentry->k) ? fentry->jt : fentry->jf; 188 pc += (A > fentry->k) ? fentry->jt : fentry->jf;
189 continue; 189 continue;
190 case BPF_JMP|BPF_JGE|BPF_K: 190 case BPF_S_JMP_JGE_K:
191 pc += (A >= fentry->k) ? fentry->jt : fentry->jf; 191 pc += (A >= fentry->k) ? fentry->jt : fentry->jf;
192 continue; 192 continue;
193 case BPF_JMP|BPF_JEQ|BPF_K: 193 case BPF_S_JMP_JEQ_K:
194 pc += (A == fentry->k) ? fentry->jt : fentry->jf; 194 pc += (A == fentry->k) ? fentry->jt : fentry->jf;
195 continue; 195 continue;
196 case BPF_JMP|BPF_JSET|BPF_K: 196 case BPF_S_JMP_JSET_K:
197 pc += (A & fentry->k) ? fentry->jt : fentry->jf; 197 pc += (A & fentry->k) ? fentry->jt : fentry->jf;
198 continue; 198 continue;
199 case BPF_JMP|BPF_JGT|BPF_X: 199 case BPF_S_JMP_JGT_X:
200 pc += (A > X) ? fentry->jt : fentry->jf; 200 pc += (A > X) ? fentry->jt : fentry->jf;
201 continue; 201 continue;
202 case BPF_JMP|BPF_JGE|BPF_X: 202 case BPF_S_JMP_JGE_X:
203 pc += (A >= X) ? fentry->jt : fentry->jf; 203 pc += (A >= X) ? fentry->jt : fentry->jf;
204 continue; 204 continue;
205 case BPF_JMP|BPF_JEQ|BPF_X: 205 case BPF_S_JMP_JEQ_X:
206 pc += (A == X) ? fentry->jt : fentry->jf; 206 pc += (A == X) ? fentry->jt : fentry->jf;
207 continue; 207 continue;
208 case BPF_JMP|BPF_JSET|BPF_X: 208 case BPF_S_JMP_JSET_X:
209 pc += (A & X) ? fentry->jt : fentry->jf; 209 pc += (A & X) ? fentry->jt : fentry->jf;
210 continue; 210 continue;
211 case BPF_LD|BPF_W|BPF_ABS: 211 case BPF_S_LD_W_ABS:
212 k = fentry->k; 212 k = fentry->k;
213load_w: 213load_w:
214 ptr = load_pointer(skb, k, 4, &tmp); 214 ptr = load_pointer(skb, k, 4, &tmp);
@@ -217,7 +217,7 @@ load_w:
217 continue; 217 continue;
218 } 218 }
219 break; 219 break;
220 case BPF_LD|BPF_H|BPF_ABS: 220 case BPF_S_LD_H_ABS:
221 k = fentry->k; 221 k = fentry->k;
222load_h: 222load_h:
223 ptr = load_pointer(skb, k, 2, &tmp); 223 ptr = load_pointer(skb, k, 2, &tmp);
@@ -226,7 +226,7 @@ load_h:
226 continue; 226 continue;
227 } 227 }
228 break; 228 break;
229 case BPF_LD|BPF_B|BPF_ABS: 229 case BPF_S_LD_B_ABS:
230 k = fentry->k; 230 k = fentry->k;
231load_b: 231load_b:
232 ptr = load_pointer(skb, k, 1, &tmp); 232 ptr = load_pointer(skb, k, 1, &tmp);
@@ -235,54 +235,54 @@ load_b:
235 continue; 235 continue;
236 } 236 }
237 break; 237 break;
238 case BPF_LD|BPF_W|BPF_LEN: 238 case BPF_S_LD_W_LEN:
239 A = skb->len; 239 A = skb->len;
240 continue; 240 continue;
241 case BPF_LDX|BPF_W|BPF_LEN: 241 case BPF_S_LDX_W_LEN:
242 X = skb->len; 242 X = skb->len;
243 continue; 243 continue;
244 case BPF_LD|BPF_W|BPF_IND: 244 case BPF_S_LD_W_IND:
245 k = X + fentry->k; 245 k = X + fentry->k;
246 goto load_w; 246 goto load_w;
247 case BPF_LD|BPF_H|BPF_IND: 247 case BPF_S_LD_H_IND:
248 k = X + fentry->k; 248 k = X + fentry->k;
249 goto load_h; 249 goto load_h;
250 case BPF_LD|BPF_B|BPF_IND: 250 case BPF_S_LD_B_IND:
251 k = X + fentry->k; 251 k = X + fentry->k;
252 goto load_b; 252 goto load_b;
253 case BPF_LDX|BPF_B|BPF_MSH: 253 case BPF_S_LDX_B_MSH:
254 ptr = load_pointer(skb, fentry->k, 1, &tmp); 254 ptr = load_pointer(skb, fentry->k, 1, &tmp);
255 if (ptr != NULL) { 255 if (ptr != NULL) {
256 X = (*(u8 *)ptr & 0xf) << 2; 256 X = (*(u8 *)ptr & 0xf) << 2;
257 continue; 257 continue;
258 } 258 }
259 return 0; 259 return 0;
260 case BPF_LD|BPF_IMM: 260 case BPF_S_LD_IMM:
261 A = fentry->k; 261 A = fentry->k;
262 continue; 262 continue;
263 case BPF_LDX|BPF_IMM: 263 case BPF_S_LDX_IMM:
264 X = fentry->k; 264 X = fentry->k;
265 continue; 265 continue;
266 case BPF_LD|BPF_MEM: 266 case BPF_S_LD_MEM:
267 A = mem[fentry->k]; 267 A = mem[fentry->k];
268 continue; 268 continue;
269 case BPF_LDX|BPF_MEM: 269 case BPF_S_LDX_MEM:
270 X = mem[fentry->k]; 270 X = mem[fentry->k];
271 continue; 271 continue;
272 case BPF_MISC|BPF_TAX: 272 case BPF_S_MISC_TAX:
273 X = A; 273 X = A;
274 continue; 274 continue;
275 case BPF_MISC|BPF_TXA: 275 case BPF_S_MISC_TXA:
276 A = X; 276 A = X;
277 continue; 277 continue;
278 case BPF_RET|BPF_K: 278 case BPF_S_RET_K:
279 return fentry->k; 279 return fentry->k;
280 case BPF_RET|BPF_A: 280 case BPF_S_RET_A:
281 return A; 281 return A;
282 case BPF_ST: 282 case BPF_S_ST:
283 mem[fentry->k] = A; 283 mem[fentry->k] = A;
284 continue; 284 continue;
285 case BPF_STX: 285 case BPF_S_STX:
286 mem[fentry->k] = X; 286 mem[fentry->k] = X;
287 continue; 287 continue;
288 default: 288 default:
@@ -390,53 +390,128 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
390 /* Only allow valid instructions */ 390 /* Only allow valid instructions */
391 switch (ftest->code) { 391 switch (ftest->code) {
392 case BPF_ALU|BPF_ADD|BPF_K: 392 case BPF_ALU|BPF_ADD|BPF_K:
393 ftest->code = BPF_S_ALU_ADD_K;
394 break;
393 case BPF_ALU|BPF_ADD|BPF_X: 395 case BPF_ALU|BPF_ADD|BPF_X:
396 ftest->code = BPF_S_ALU_ADD_X;
397 break;
394 case BPF_ALU|BPF_SUB|BPF_K: 398 case BPF_ALU|BPF_SUB|BPF_K:
399 ftest->code = BPF_S_ALU_SUB_K;
400 break;
395 case BPF_ALU|BPF_SUB|BPF_X: 401 case BPF_ALU|BPF_SUB|BPF_X:
402 ftest->code = BPF_S_ALU_SUB_X;
403 break;
396 case BPF_ALU|BPF_MUL|BPF_K: 404 case BPF_ALU|BPF_MUL|BPF_K:
405 ftest->code = BPF_S_ALU_MUL_K;
406 break;
397 case BPF_ALU|BPF_MUL|BPF_X: 407 case BPF_ALU|BPF_MUL|BPF_X:
408 ftest->code = BPF_S_ALU_MUL_X;
409 break;
398 case BPF_ALU|BPF_DIV|BPF_X: 410 case BPF_ALU|BPF_DIV|BPF_X:
411 ftest->code = BPF_S_ALU_DIV_X;
412 break;
399 case BPF_ALU|BPF_AND|BPF_K: 413 case BPF_ALU|BPF_AND|BPF_K:
414 ftest->code = BPF_S_ALU_AND_K;
415 break;
400 case BPF_ALU|BPF_AND|BPF_X: 416 case BPF_ALU|BPF_AND|BPF_X:
417 ftest->code = BPF_S_ALU_AND_X;
418 break;
401 case BPF_ALU|BPF_OR|BPF_K: 419 case BPF_ALU|BPF_OR|BPF_K:
420 ftest->code = BPF_S_ALU_OR_K;
421 break;
402 case BPF_ALU|BPF_OR|BPF_X: 422 case BPF_ALU|BPF_OR|BPF_X:
423 ftest->code = BPF_S_ALU_OR_X;
424 break;
403 case BPF_ALU|BPF_LSH|BPF_K: 425 case BPF_ALU|BPF_LSH|BPF_K:
426 ftest->code = BPF_S_ALU_LSH_K;
427 break;
404 case BPF_ALU|BPF_LSH|BPF_X: 428 case BPF_ALU|BPF_LSH|BPF_X:
429 ftest->code = BPF_S_ALU_LSH_X;
430 break;
405 case BPF_ALU|BPF_RSH|BPF_K: 431 case BPF_ALU|BPF_RSH|BPF_K:
432 ftest->code = BPF_S_ALU_RSH_K;
433 break;
406 case BPF_ALU|BPF_RSH|BPF_X: 434 case BPF_ALU|BPF_RSH|BPF_X:
435 ftest->code = BPF_S_ALU_RSH_X;
436 break;
407 case BPF_ALU|BPF_NEG: 437 case BPF_ALU|BPF_NEG:
438 ftest->code = BPF_S_ALU_NEG;
439 break;
408 case BPF_LD|BPF_W|BPF_ABS: 440 case BPF_LD|BPF_W|BPF_ABS:
441 ftest->code = BPF_S_LD_W_ABS;
442 break;
409 case BPF_LD|BPF_H|BPF_ABS: 443 case BPF_LD|BPF_H|BPF_ABS:
444 ftest->code = BPF_S_LD_H_ABS;
445 break;
410 case BPF_LD|BPF_B|BPF_ABS: 446 case BPF_LD|BPF_B|BPF_ABS:
447 ftest->code = BPF_S_LD_B_ABS;
448 break;
411 case BPF_LD|BPF_W|BPF_LEN: 449 case BPF_LD|BPF_W|BPF_LEN:
450 ftest->code = BPF_S_LD_W_LEN;
451 break;
412 case BPF_LD|BPF_W|BPF_IND: 452 case BPF_LD|BPF_W|BPF_IND:
453 ftest->code = BPF_S_LD_W_IND;
454 break;
413 case BPF_LD|BPF_H|BPF_IND: 455 case BPF_LD|BPF_H|BPF_IND:
456 ftest->code = BPF_S_LD_H_IND;
457 break;
414 case BPF_LD|BPF_B|BPF_IND: 458 case BPF_LD|BPF_B|BPF_IND:
459 ftest->code = BPF_S_LD_B_IND;
460 break;
415 case BPF_LD|BPF_IMM: 461 case BPF_LD|BPF_IMM:
462 ftest->code = BPF_S_LD_IMM;
463 break;
416 case BPF_LDX|BPF_W|BPF_LEN: 464 case BPF_LDX|BPF_W|BPF_LEN:
465 ftest->code = BPF_S_LDX_W_LEN;
466 break;
417 case BPF_LDX|BPF_B|BPF_MSH: 467 case BPF_LDX|BPF_B|BPF_MSH:
468 ftest->code = BPF_S_LDX_B_MSH;
469 break;
418 case BPF_LDX|BPF_IMM: 470 case BPF_LDX|BPF_IMM:
471 ftest->code = BPF_S_LDX_IMM;
472 break;
419 case BPF_MISC|BPF_TAX: 473 case BPF_MISC|BPF_TAX:
474 ftest->code = BPF_S_MISC_TAX;
475 break;
420 case BPF_MISC|BPF_TXA: 476 case BPF_MISC|BPF_TXA:
477 ftest->code = BPF_S_MISC_TXA;
478 break;
421 case BPF_RET|BPF_K: 479 case BPF_RET|BPF_K:
480 ftest->code = BPF_S_RET_K;
481 break;
422 case BPF_RET|BPF_A: 482 case BPF_RET|BPF_A:
483 ftest->code = BPF_S_RET_A;
423 break; 484 break;
424 485
425 /* Some instructions need special checks */ 486 /* Some instructions need special checks */
426 487
427 case BPF_ALU|BPF_DIV|BPF_K:
428 /* check for division by zero */ 488 /* check for division by zero */
489 case BPF_ALU|BPF_DIV|BPF_K:
429 if (ftest->k == 0) 490 if (ftest->k == 0)
430 return -EINVAL; 491 return -EINVAL;
492 ftest->code = BPF_S_ALU_DIV_K;
431 break; 493 break;
432 494
495 /* check for invalid memory addresses */
433 case BPF_LD|BPF_MEM: 496 case BPF_LD|BPF_MEM:
497 if (ftest->k >= BPF_MEMWORDS)
498 return -EINVAL;
499 ftest->code = BPF_S_LD_MEM;
500 break;
434 case BPF_LDX|BPF_MEM: 501 case BPF_LDX|BPF_MEM:
502 if (ftest->k >= BPF_MEMWORDS)
503 return -EINVAL;
504 ftest->code = BPF_S_LDX_MEM;
505 break;
435 case BPF_ST: 506 case BPF_ST:
507 if (ftest->k >= BPF_MEMWORDS)
508 return -EINVAL;
509 ftest->code = BPF_S_ST;
510 break;
436 case BPF_STX: 511 case BPF_STX:
437 /* check for invalid memory addresses */
438 if (ftest->k >= BPF_MEMWORDS) 512 if (ftest->k >= BPF_MEMWORDS)
439 return -EINVAL; 513 return -EINVAL;
514 ftest->code = BPF_S_STX;
440 break; 515 break;
441 516
442 case BPF_JMP|BPF_JA: 517 case BPF_JMP|BPF_JA:
@@ -447,28 +522,63 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
447 */ 522 */
448 if (ftest->k >= (unsigned)(flen-pc-1)) 523 if (ftest->k >= (unsigned)(flen-pc-1))
449 return -EINVAL; 524 return -EINVAL;
525 ftest->code = BPF_S_JMP_JA;
450 break; 526 break;
451 527
452 case BPF_JMP|BPF_JEQ|BPF_K: 528 case BPF_JMP|BPF_JEQ|BPF_K:
529 ftest->code = BPF_S_JMP_JEQ_K;
530 break;
453 case BPF_JMP|BPF_JEQ|BPF_X: 531 case BPF_JMP|BPF_JEQ|BPF_X:
532 ftest->code = BPF_S_JMP_JEQ_X;
533 break;
454 case BPF_JMP|BPF_JGE|BPF_K: 534 case BPF_JMP|BPF_JGE|BPF_K:
535 ftest->code = BPF_S_JMP_JGE_K;
536 break;
455 case BPF_JMP|BPF_JGE|BPF_X: 537 case BPF_JMP|BPF_JGE|BPF_X:
538 ftest->code = BPF_S_JMP_JGE_X;
539 break;
456 case BPF_JMP|BPF_JGT|BPF_K: 540 case BPF_JMP|BPF_JGT|BPF_K:
541 ftest->code = BPF_S_JMP_JGT_K;
542 break;
457 case BPF_JMP|BPF_JGT|BPF_X: 543 case BPF_JMP|BPF_JGT|BPF_X:
544 ftest->code = BPF_S_JMP_JGT_X;
545 break;
458 case BPF_JMP|BPF_JSET|BPF_K: 546 case BPF_JMP|BPF_JSET|BPF_K:
547 ftest->code = BPF_S_JMP_JSET_K;
548 break;
459 case BPF_JMP|BPF_JSET|BPF_X: 549 case BPF_JMP|BPF_JSET|BPF_X:
550 ftest->code = BPF_S_JMP_JSET_X;
551 break;
552
553 default:
554 return -EINVAL;
555 }
556
460 /* for conditionals both must be safe */ 557 /* for conditionals both must be safe */
558 switch (ftest->code) {
559 case BPF_S_JMP_JEQ_K:
560 case BPF_S_JMP_JEQ_X:
561 case BPF_S_JMP_JGE_K:
562 case BPF_S_JMP_JGE_X:
563 case BPF_S_JMP_JGT_K:
564 case BPF_S_JMP_JGT_X:
565 case BPF_S_JMP_JSET_X:
566 case BPF_S_JMP_JSET_K:
461 if (pc + ftest->jt + 1 >= flen || 567 if (pc + ftest->jt + 1 >= flen ||
462 pc + ftest->jf + 1 >= flen) 568 pc + ftest->jf + 1 >= flen)
463 return -EINVAL; 569 return -EINVAL;
464 break; 570 }
571 }
465 572
573 /* last instruction must be a RET code */
574 switch (filter[flen - 1].code) {
575 case BPF_S_RET_K:
576 case BPF_S_RET_A:
577 return 0;
578 break;
466 default: 579 default:
467 return -EINVAL; 580 return -EINVAL;
468 } 581 }
469 }
470
471 return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL;
472} 582}
473EXPORT_SYMBOL(sk_chk_filter); 583EXPORT_SYMBOL(sk_chk_filter);
474 584