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 ---