inet_diag.c (1c95df85ca49640576de2f0a850925957b547b84) | inet_diag.c (405c005949e47b6e91359159c24753519ded0c67) |
---|---|
1/* 2 * inet_diag.c Module for monitoring INET transport protocols sockets. 3 * 4 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version --- 499 unchanged lines hidden (view full) --- 508 if (op->yes < 4 || op->yes & 3) 509 return 0; 510 len -= op->yes; 511 bc += op->yes; 512 } 513 return 0; 514} 515 | 1/* 2 * inet_diag.c Module for monitoring INET transport protocols sockets. 3 * 4 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version --- 499 unchanged lines hidden (view full) --- 508 if (op->yes < 4 || op->yes & 3) 509 return 0; 510 len -= op->yes; 511 bc += op->yes; 512 } 513 return 0; 514} 515 |
516/* Validate an inet_diag_hostcond. */ 517static bool valid_hostcond(const struct inet_diag_bc_op *op, int len, 518 int *min_len) 519{ 520 int addr_len; 521 struct inet_diag_hostcond *cond; 522 523 /* Check hostcond space. */ 524 *min_len += sizeof(struct inet_diag_hostcond); 525 if (len < *min_len) 526 return false; 527 cond = (struct inet_diag_hostcond *)(op + 1); 528 529 /* Check address family and address length. */ 530 switch (cond->family) { 531 case AF_UNSPEC: 532 addr_len = 0; 533 break; 534 case AF_INET: 535 addr_len = sizeof(struct in_addr); 536 break; 537 case AF_INET6: 538 addr_len = sizeof(struct in6_addr); 539 break; 540 default: 541 return false; 542 } 543 *min_len += addr_len; 544 if (len < *min_len) 545 return false; 546 547 /* Check prefix length (in bits) vs address length (in bytes). */ 548 if (cond->prefix_len > 8 * addr_len) 549 return false; 550 551 return true; 552} 553 |
|
516static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) 517{ 518 const void *bc = bytecode; 519 int len = bytecode_len; 520 521 while (len > 0) { 522 const struct inet_diag_bc_op *op = bc; | 554static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) 555{ 556 const void *bc = bytecode; 557 int len = bytecode_len; 558 559 while (len > 0) { 560 const struct inet_diag_bc_op *op = bc; |
561 int min_len = sizeof(struct inet_diag_bc_op); |
|
523 524//printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len); 525 switch (op->code) { | 562 563//printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len); 564 switch (op->code) { |
526 case INET_DIAG_BC_AUTO: | |
527 case INET_DIAG_BC_S_COND: 528 case INET_DIAG_BC_D_COND: | 565 case INET_DIAG_BC_S_COND: 566 case INET_DIAG_BC_D_COND: |
567 if (!valid_hostcond(bc, len, &min_len)) 568 return -EINVAL; 569 /* fall through */ 570 case INET_DIAG_BC_AUTO: |
|
529 case INET_DIAG_BC_S_GE: 530 case INET_DIAG_BC_S_LE: 531 case INET_DIAG_BC_D_GE: 532 case INET_DIAG_BC_D_LE: 533 case INET_DIAG_BC_JMP: | 571 case INET_DIAG_BC_S_GE: 572 case INET_DIAG_BC_S_LE: 573 case INET_DIAG_BC_D_GE: 574 case INET_DIAG_BC_D_LE: 575 case INET_DIAG_BC_JMP: |
534 if (op->no < 4 || op->no > len + 4 || op->no & 3) | 576 if (op->no < min_len || op->no > len + 4 || op->no & 3) |
535 return -EINVAL; 536 if (op->no < len && 537 !valid_cc(bytecode, bytecode_len, len - op->no)) 538 return -EINVAL; 539 break; 540 case INET_DIAG_BC_NOP: 541 break; 542 default: 543 return -EINVAL; 544 } | 577 return -EINVAL; 578 if (op->no < len && 579 !valid_cc(bytecode, bytecode_len, len - op->no)) 580 return -EINVAL; 581 break; 582 case INET_DIAG_BC_NOP: 583 break; 584 default: 585 return -EINVAL; 586 } |
545 if (op->yes < 4 || op->yes > len + 4 || op->yes & 3) | 587 if (op->yes < min_len || op->yes > len + 4 || op->yes & 3) |
546 return -EINVAL; 547 bc += op->yes; 548 len -= op->yes; 549 } 550 return len == 0 ? 0 : -EINVAL; 551} 552 553static int inet_csk_diag_dump(struct sock *sk, --- 580 unchanged lines hidden --- | 588 return -EINVAL; 589 bc += op->yes; 590 len -= op->yes; 591 } 592 return len == 0 ? 0 : -EINVAL; 593} 594 595static int inet_csk_diag_dump(struct sock *sk, --- 580 unchanged lines hidden --- |