aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/inet_diag.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/inet_diag.c')
-rw-r--r--net/ipv4/inet_diag.c45
1 files changed, 24 insertions, 21 deletions
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index e5fa2ddce320..3267d3898437 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -124,7 +124,7 @@ static int inet_csk_diag_fill(struct sock *sk,
124 124
125#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) 125#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
126 if (r->idiag_family == AF_INET6) { 126 if (r->idiag_family == AF_INET6) {
127 struct ipv6_pinfo *np = inet6_sk(sk); 127 const struct ipv6_pinfo *np = inet6_sk(sk);
128 128
129 ipv6_addr_copy((struct in6_addr *)r->id.idiag_src, 129 ipv6_addr_copy((struct in6_addr *)r->id.idiag_src,
130 &np->rcv_saddr); 130 &np->rcv_saddr);
@@ -425,7 +425,7 @@ static int inet_diag_bc_run(const void *bc, int len,
425 bc += op->no; 425 bc += op->no;
426 } 426 }
427 } 427 }
428 return (len == 0); 428 return len == 0;
429} 429}
430 430
431static int valid_cc(const void *bc, int len, int cc) 431static int valid_cc(const void *bc, int len, int cc)
@@ -437,7 +437,7 @@ static int valid_cc(const void *bc, int len, int cc)
437 return 0; 437 return 0;
438 if (cc == len) 438 if (cc == len)
439 return 1; 439 return 1;
440 if (op->yes < 4) 440 if (op->yes < 4 || op->yes & 3)
441 return 0; 441 return 0;
442 len -= op->yes; 442 len -= op->yes;
443 bc += op->yes; 443 bc += op->yes;
@@ -447,11 +447,11 @@ static int valid_cc(const void *bc, int len, int cc)
447 447
448static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) 448static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
449{ 449{
450 const unsigned char *bc = bytecode; 450 const void *bc = bytecode;
451 int len = bytecode_len; 451 int len = bytecode_len;
452 452
453 while (len > 0) { 453 while (len > 0) {
454 struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)bc; 454 const struct inet_diag_bc_op *op = bc;
455 455
456//printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len); 456//printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len);
457 switch (op->code) { 457 switch (op->code) {
@@ -462,22 +462,20 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
462 case INET_DIAG_BC_S_LE: 462 case INET_DIAG_BC_S_LE:
463 case INET_DIAG_BC_D_GE: 463 case INET_DIAG_BC_D_GE:
464 case INET_DIAG_BC_D_LE: 464 case INET_DIAG_BC_D_LE:
465 if (op->yes < 4 || op->yes > len + 4)
466 return -EINVAL;
467 case INET_DIAG_BC_JMP: 465 case INET_DIAG_BC_JMP:
468 if (op->no < 4 || op->no > len + 4) 466 if (op->no < 4 || op->no > len + 4 || op->no & 3)
469 return -EINVAL; 467 return -EINVAL;
470 if (op->no < len && 468 if (op->no < len &&
471 !valid_cc(bytecode, bytecode_len, len - op->no)) 469 !valid_cc(bytecode, bytecode_len, len - op->no))
472 return -EINVAL; 470 return -EINVAL;
473 break; 471 break;
474 case INET_DIAG_BC_NOP: 472 case INET_DIAG_BC_NOP:
475 if (op->yes < 4 || op->yes > len + 4)
476 return -EINVAL;
477 break; 473 break;
478 default: 474 default:
479 return -EINVAL; 475 return -EINVAL;
480 } 476 }
477 if (op->yes < 4 || op->yes > len + 4 || op->yes & 3)
478 return -EINVAL;
481 bc += op->yes; 479 bc += op->yes;
482 len -= op->yes; 480 len -= op->yes;
483 } 481 }
@@ -490,9 +488,11 @@ static int inet_csk_diag_dump(struct sock *sk,
490{ 488{
491 struct inet_diag_req *r = NLMSG_DATA(cb->nlh); 489 struct inet_diag_req *r = NLMSG_DATA(cb->nlh);
492 490
493 if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) { 491 if (nlmsg_attrlen(cb->nlh, sizeof(*r))) {
494 struct inet_diag_entry entry; 492 struct inet_diag_entry entry;
495 struct rtattr *bc = (struct rtattr *)(r + 1); 493 const struct nlattr *bc = nlmsg_find_attr(cb->nlh,
494 sizeof(*r),
495 INET_DIAG_REQ_BYTECODE);
496 struct inet_sock *inet = inet_sk(sk); 496 struct inet_sock *inet = inet_sk(sk);
497 497
498 entry.family = sk->sk_family; 498 entry.family = sk->sk_family;
@@ -512,7 +512,7 @@ static int inet_csk_diag_dump(struct sock *sk,
512 entry.dport = ntohs(inet->inet_dport); 512 entry.dport = ntohs(inet->inet_dport);
513 entry.userlocks = sk->sk_userlocks; 513 entry.userlocks = sk->sk_userlocks;
514 514
515 if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry)) 515 if (!inet_diag_bc_run(nla_data(bc), nla_len(bc), &entry))
516 return 0; 516 return 0;
517 } 517 }
518 518
@@ -527,9 +527,11 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw,
527{ 527{
528 struct inet_diag_req *r = NLMSG_DATA(cb->nlh); 528 struct inet_diag_req *r = NLMSG_DATA(cb->nlh);
529 529
530 if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) { 530 if (nlmsg_attrlen(cb->nlh, sizeof(*r))) {
531 struct inet_diag_entry entry; 531 struct inet_diag_entry entry;
532 struct rtattr *bc = (struct rtattr *)(r + 1); 532 const struct nlattr *bc = nlmsg_find_attr(cb->nlh,
533 sizeof(*r),
534 INET_DIAG_REQ_BYTECODE);
533 535
534 entry.family = tw->tw_family; 536 entry.family = tw->tw_family;
535#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) 537#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
@@ -548,7 +550,7 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw,
548 entry.dport = ntohs(tw->tw_dport); 550 entry.dport = ntohs(tw->tw_dport);
549 entry.userlocks = 0; 551 entry.userlocks = 0;
550 552
551 if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry)) 553 if (!inet_diag_bc_run(nla_data(bc), nla_len(bc), &entry))
552 return 0; 554 return 0;
553 } 555 }
554 556
@@ -618,7 +620,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
618 struct inet_diag_req *r = NLMSG_DATA(cb->nlh); 620 struct inet_diag_req *r = NLMSG_DATA(cb->nlh);
619 struct inet_connection_sock *icsk = inet_csk(sk); 621 struct inet_connection_sock *icsk = inet_csk(sk);
620 struct listen_sock *lopt; 622 struct listen_sock *lopt;
621 struct rtattr *bc = NULL; 623 const struct nlattr *bc = NULL;
622 struct inet_sock *inet = inet_sk(sk); 624 struct inet_sock *inet = inet_sk(sk);
623 int j, s_j; 625 int j, s_j;
624 int reqnum, s_reqnum; 626 int reqnum, s_reqnum;
@@ -638,8 +640,9 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
638 if (!lopt || !lopt->qlen) 640 if (!lopt || !lopt->qlen)
639 goto out; 641 goto out;
640 642
641 if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) { 643 if (nlmsg_attrlen(cb->nlh, sizeof(*r))) {
642 bc = (struct rtattr *)(r + 1); 644 bc = nlmsg_find_attr(cb->nlh, sizeof(*r),
645 INET_DIAG_REQ_BYTECODE);
643 entry.sport = inet->inet_num; 646 entry.sport = inet->inet_num;
644 entry.userlocks = sk->sk_userlocks; 647 entry.userlocks = sk->sk_userlocks;
645 } 648 }
@@ -672,8 +675,8 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
672 &ireq->rmt_addr; 675 &ireq->rmt_addr;
673 entry.dport = ntohs(ireq->rmt_port); 676 entry.dport = ntohs(ireq->rmt_port);
674 677
675 if (!inet_diag_bc_run(RTA_DATA(bc), 678 if (!inet_diag_bc_run(nla_data(bc),
676 RTA_PAYLOAD(bc), &entry)) 679 nla_len(bc), &entry))
677 continue; 680 continue;
678 } 681 }
679 682