aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorKris Katterjohn <kjak@users.sourceforge.net>2006-01-04 16:58:36 -0500
committerDavid S. Miller <davem@davemloft.net>2006-01-04 16:58:36 -0500
commit9369986306d4692f37b61302d4e1ce3054d8833e (patch)
tree104133156ada1b78fbfc8d3d84a4c8ae9ee9060a /net
parent181a46a56e9f852060c54247209e93740329b6eb (diff)
[NET]: More instruction checks fornet/core/filter.c
Signed-off-by: Kris Katterjohn <kjak@users.sourceforge.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/filter.c112
1 files changed, 80 insertions, 32 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index 3a10e0bc90e8..8964d3445588 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -13,6 +13,7 @@
13 * 2 of the License, or (at your option) any later version. 13 * 2 of the License, or (at your option) any later version.
14 * 14 *
15 * Andi Kleen - Fix a few bad bugs and races. 15 * Andi Kleen - Fix a few bad bugs and races.
16 * Kris Katterjohn - Added many additional checks in sk_chk_filter()
16 */ 17 */
17 18
18#include <linux/module.h> 19#include <linux/module.h>
@@ -250,7 +251,7 @@ load_b:
250 mem[fentry->k] = X; 251 mem[fentry->k] = X;
251 continue; 252 continue;
252 default: 253 default:
253 /* Invalid instruction counts as RET */ 254 WARN_ON(1);
254 return 0; 255 return 0;
255 } 256 }
256 257
@@ -283,8 +284,8 @@ load_b:
283 * 284 *
284 * Check the user's filter code. If we let some ugly 285 * Check the user's filter code. If we let some ugly
285 * filter code slip through kaboom! The filter must contain 286 * filter code slip through kaboom! The filter must contain
286 * no references or jumps that are out of range, no illegal instructions 287 * no references or jumps that are out of range, no illegal
287 * and no backward jumps. It must end with a RET instruction 288 * instructions, and must end with a RET instruction.
288 * 289 *
289 * Returns 0 if the rule set is legal or a negative errno code if not. 290 * Returns 0 if the rule set is legal or a negative errno code if not.
290 */ 291 */
@@ -300,38 +301,85 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
300 for (pc = 0; pc < flen; pc++) { 301 for (pc = 0; pc < flen; pc++) {
301 /* all jumps are forward as they are not signed */ 302 /* all jumps are forward as they are not signed */
302 ftest = &filter[pc]; 303 ftest = &filter[pc];
303 if (BPF_CLASS(ftest->code) == BPF_JMP) {
304 /* but they mustn't jump off the end */
305 if (BPF_OP(ftest->code) == BPF_JA) {
306 /*
307 * Note, the large ftest->k might cause loops.
308 * Compare this with conditional jumps below,
309 * where offsets are limited. --ANK (981016)
310 */
311 if (ftest->k >= (unsigned)(flen-pc-1))
312 return -EINVAL;
313 } else {
314 /* for conditionals both must be safe */
315 if (pc + ftest->jt +1 >= flen ||
316 pc + ftest->jf +1 >= flen)
317 return -EINVAL;
318 }
319 }
320 304
321 /* check for division by zero -Kris Katterjohn 2005-10-30 */ 305 /* Only allow valid instructions */
322 if (ftest->code == (BPF_ALU|BPF_DIV|BPF_K) && ftest->k == 0) 306 switch (ftest->code) {
323 return -EINVAL; 307 case BPF_ALU|BPF_ADD|BPF_K:
308 case BPF_ALU|BPF_ADD|BPF_X:
309 case BPF_ALU|BPF_SUB|BPF_K:
310 case BPF_ALU|BPF_SUB|BPF_X:
311 case BPF_ALU|BPF_MUL|BPF_K:
312 case BPF_ALU|BPF_MUL|BPF_X:
313 case BPF_ALU|BPF_DIV|BPF_X:
314 case BPF_ALU|BPF_AND|BPF_K:
315 case BPF_ALU|BPF_AND|BPF_X:
316 case BPF_ALU|BPF_OR|BPF_K:
317 case BPF_ALU|BPF_OR|BPF_X:
318 case BPF_ALU|BPF_LSH|BPF_K:
319 case BPF_ALU|BPF_LSH|BPF_X:
320 case BPF_ALU|BPF_RSH|BPF_K:
321 case BPF_ALU|BPF_RSH|BPF_X:
322 case BPF_ALU|BPF_NEG:
323 case BPF_LD|BPF_W|BPF_ABS:
324 case BPF_LD|BPF_H|BPF_ABS:
325 case BPF_LD|BPF_B|BPF_ABS:
326 case BPF_LD|BPF_W|BPF_LEN:
327 case BPF_LD|BPF_W|BPF_IND:
328 case BPF_LD|BPF_H|BPF_IND:
329 case BPF_LD|BPF_B|BPF_IND:
330 case BPF_LD|BPF_IMM:
331 case BPF_LDX|BPF_W|BPF_LEN:
332 case BPF_LDX|BPF_B|BPF_MSH:
333 case BPF_LDX|BPF_IMM:
334 case BPF_MISC|BPF_TAX:
335 case BPF_MISC|BPF_TXA:
336 case BPF_RET|BPF_K:
337 case BPF_RET|BPF_A:
338 break;
339
340 /* Some instructions need special checks */
324 341
325 /* check that memory operations use valid addresses. */ 342 case BPF_ALU|BPF_DIV|BPF_K:
326 if (ftest->k >= BPF_MEMWORDS) { 343 /* check for division by zero */
327 /* but it might not be a memory operation... */ 344 if (ftest->k == 0)
328 switch (ftest->code) {
329 case BPF_ST:
330 case BPF_STX:
331 case BPF_LD|BPF_MEM:
332 case BPF_LDX|BPF_MEM:
333 return -EINVAL; 345 return -EINVAL;
334 } 346 break;
347
348 case BPF_LD|BPF_MEM:
349 case BPF_LDX|BPF_MEM:
350 case BPF_ST:
351 case BPF_STX:
352 /* check for invalid memory addresses */
353 if (ftest->k >= BPF_MEMWORDS)
354 return -EINVAL;
355 break;
356
357 case BPF_JMP|BPF_JA:
358 /*
359 * Note, the large ftest->k might cause loops.
360 * Compare this with conditional jumps below,
361 * where offsets are limited. --ANK (981016)
362 */
363 if (ftest->k >= (unsigned)(flen-pc-1))
364 return -EINVAL;
365 break;
366
367 case BPF_JMP|BPF_JEQ|BPF_K:
368 case BPF_JMP|BPF_JEQ|BPF_X:
369 case BPF_JMP|BPF_JGE|BPF_K:
370 case BPF_JMP|BPF_JGE|BPF_X:
371 case BPF_JMP|BPF_JGT|BPF_K:
372 case BPF_JMP|BPF_JGT|BPF_X:
373 case BPF_JMP|BPF_JSET|BPF_K:
374 case BPF_JMP|BPF_JSET|BPF_X:
375 /* for conditionals both must be safe */
376 if (pc + ftest->jt + 1 >= flen ||
377 pc + ftest->jf + 1 >= flen)
378 return -EINVAL;
379 break;
380
381 default:
382 return -EINVAL;
335 } 383 }
336 } 384 }
337 385