aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/inet_timewait_sock.c1
-rw-r--r--net/ipv4/netfilter/arp_tables.c48
-rw-r--r--net/ipv4/netfilter/ip_tables.c144
-rw-r--r--net/ipv4/route.c2
-rw-r--r--net/ipv4/tcp_input.c4
-rw-r--r--net/ipv4/xfrm4_policy.c2
6 files changed, 104 insertions, 97 deletions
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index e28330aa4139..9f414e35c488 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -178,7 +178,6 @@ void inet_twdr_hangman(unsigned long data)
178 need_timer = 0; 178 need_timer = 0;
179 if (inet_twdr_do_twkill_work(twdr, twdr->slot)) { 179 if (inet_twdr_do_twkill_work(twdr, twdr->slot)) {
180 twdr->thread_slots |= (1 << twdr->slot); 180 twdr->thread_slots |= (1 << twdr->slot);
181 mb();
182 schedule_work(&twdr->twkill_work); 181 schedule_work(&twdr->twkill_work);
183 need_timer = 1; 182 need_timer = 1;
184 } else { 183 } else {
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 413c2d0a1f3d..71b76ade00e1 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -375,6 +375,13 @@ static int mark_source_chains(struct xt_table_info *newinfo,
375 && unconditional(&e->arp)) { 375 && unconditional(&e->arp)) {
376 unsigned int oldpos, size; 376 unsigned int oldpos, size;
377 377
378 if (t->verdict < -NF_MAX_VERDICT - 1) {
379 duprintf("mark_source_chains: bad "
380 "negative verdict (%i)\n",
381 t->verdict);
382 return 0;
383 }
384
378 /* Return: backtrack through the last 385 /* Return: backtrack through the last
379 * big jump. 386 * big jump.
380 */ 387 */
@@ -404,6 +411,14 @@ static int mark_source_chains(struct xt_table_info *newinfo,
404 if (strcmp(t->target.u.user.name, 411 if (strcmp(t->target.u.user.name,
405 ARPT_STANDARD_TARGET) == 0 412 ARPT_STANDARD_TARGET) == 0
406 && newpos >= 0) { 413 && newpos >= 0) {
414 if (newpos > newinfo->size -
415 sizeof(struct arpt_entry)) {
416 duprintf("mark_source_chains: "
417 "bad verdict (%i)\n",
418 newpos);
419 return 0;
420 }
421
407 /* This a jump; chase it. */ 422 /* This a jump; chase it. */
408 duprintf("Jump rule %u -> %u\n", 423 duprintf("Jump rule %u -> %u\n",
409 pos, newpos); 424 pos, newpos);
@@ -426,8 +441,6 @@ static int mark_source_chains(struct xt_table_info *newinfo,
426static inline int standard_check(const struct arpt_entry_target *t, 441static inline int standard_check(const struct arpt_entry_target *t,
427 unsigned int max_offset) 442 unsigned int max_offset)
428{ 443{
429 struct arpt_standard_target *targ = (void *)t;
430
431 /* Check standard info. */ 444 /* Check standard info. */
432 if (t->u.target_size 445 if (t->u.target_size
433 != ARPT_ALIGN(sizeof(struct arpt_standard_target))) { 446 != ARPT_ALIGN(sizeof(struct arpt_standard_target))) {
@@ -437,18 +450,6 @@ static inline int standard_check(const struct arpt_entry_target *t,
437 return 0; 450 return 0;
438 } 451 }
439 452
440 if (targ->verdict >= 0
441 && targ->verdict > max_offset - sizeof(struct arpt_entry)) {
442 duprintf("arpt_standard_check: bad verdict (%i)\n",
443 targ->verdict);
444 return 0;
445 }
446
447 if (targ->verdict < -NF_MAX_VERDICT - 1) {
448 duprintf("arpt_standard_check: bad negative verdict (%i)\n",
449 targ->verdict);
450 return 0;
451 }
452 return 1; 453 return 1;
453} 454}
454 455
@@ -627,18 +628,20 @@ static int translate_table(const char *name,
627 } 628 }
628 } 629 }
629 630
631 if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
632 duprintf("Looping hook\n");
633 return -ELOOP;
634 }
635
630 /* Finally, each sanity check must pass */ 636 /* Finally, each sanity check must pass */
631 i = 0; 637 i = 0;
632 ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size, 638 ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size,
633 check_entry, name, size, &i); 639 check_entry, name, size, &i);
634 640
635 if (ret != 0) 641 if (ret != 0) {
636 goto cleanup; 642 ARPT_ENTRY_ITERATE(entry0, newinfo->size,
637 643 cleanup_entry, &i);
638 ret = -ELOOP; 644 return ret;
639 if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
640 duprintf("Looping hook\n");
641 goto cleanup;
642 } 645 }
643 646
644 /* And one copy for every other CPU */ 647 /* And one copy for every other CPU */
@@ -647,9 +650,6 @@ static int translate_table(const char *name,
647 memcpy(newinfo->entries[i], entry0, newinfo->size); 650 memcpy(newinfo->entries[i], entry0, newinfo->size);
648 } 651 }
649 652
650 return 0;
651cleanup:
652 ARPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
653 return ret; 653 return ret;
654} 654}
655 655
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 8a455439b128..0ff2956d35e5 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -401,6 +401,13 @@ mark_source_chains(struct xt_table_info *newinfo,
401 && unconditional(&e->ip)) { 401 && unconditional(&e->ip)) {
402 unsigned int oldpos, size; 402 unsigned int oldpos, size;
403 403
404 if (t->verdict < -NF_MAX_VERDICT - 1) {
405 duprintf("mark_source_chains: bad "
406 "negative verdict (%i)\n",
407 t->verdict);
408 return 0;
409 }
410
404 /* Return: backtrack through the last 411 /* Return: backtrack through the last
405 big jump. */ 412 big jump. */
406 do { 413 do {
@@ -438,6 +445,13 @@ mark_source_chains(struct xt_table_info *newinfo,
438 if (strcmp(t->target.u.user.name, 445 if (strcmp(t->target.u.user.name,
439 IPT_STANDARD_TARGET) == 0 446 IPT_STANDARD_TARGET) == 0
440 && newpos >= 0) { 447 && newpos >= 0) {
448 if (newpos > newinfo->size -
449 sizeof(struct ipt_entry)) {
450 duprintf("mark_source_chains: "
451 "bad verdict (%i)\n",
452 newpos);
453 return 0;
454 }
441 /* This a jump; chase it. */ 455 /* This a jump; chase it. */
442 duprintf("Jump rule %u -> %u\n", 456 duprintf("Jump rule %u -> %u\n",
443 pos, newpos); 457 pos, newpos);
@@ -470,27 +484,6 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i)
470} 484}
471 485
472static inline int 486static inline int
473standard_check(const struct ipt_entry_target *t,
474 unsigned int max_offset)
475{
476 struct ipt_standard_target *targ = (void *)t;
477
478 /* Check standard info. */
479 if (targ->verdict >= 0
480 && targ->verdict > max_offset - sizeof(struct ipt_entry)) {
481 duprintf("ipt_standard_check: bad verdict (%i)\n",
482 targ->verdict);
483 return 0;
484 }
485 if (targ->verdict < -NF_MAX_VERDICT - 1) {
486 duprintf("ipt_standard_check: bad negative verdict (%i)\n",
487 targ->verdict);
488 return 0;
489 }
490 return 1;
491}
492
493static inline int
494check_match(struct ipt_entry_match *m, 487check_match(struct ipt_entry_match *m,
495 const char *name, 488 const char *name,
496 const struct ipt_ip *ip, 489 const struct ipt_ip *ip,
@@ -576,12 +569,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
576 if (ret) 569 if (ret)
577 goto err; 570 goto err;
578 571
579 if (t->u.kernel.target == &ipt_standard_target) { 572 if (t->u.kernel.target->checkentry
580 if (!standard_check(t, size)) {
581 ret = -EINVAL;
582 goto err;
583 }
584 } else if (t->u.kernel.target->checkentry
585 && !t->u.kernel.target->checkentry(name, e, target, t->data, 573 && !t->u.kernel.target->checkentry(name, e, target, t->data,
586 e->comefrom)) { 574 e->comefrom)) {
587 duprintf("ip_tables: check failed for `%s'.\n", 575 duprintf("ip_tables: check failed for `%s'.\n",
@@ -718,17 +706,19 @@ translate_table(const char *name,
718 } 706 }
719 } 707 }
720 708
709 if (!mark_source_chains(newinfo, valid_hooks, entry0))
710 return -ELOOP;
711
721 /* Finally, each sanity check must pass */ 712 /* Finally, each sanity check must pass */
722 i = 0; 713 i = 0;
723 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, 714 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
724 check_entry, name, size, &i); 715 check_entry, name, size, &i);
725 716
726 if (ret != 0) 717 if (ret != 0) {
727 goto cleanup; 718 IPT_ENTRY_ITERATE(entry0, newinfo->size,
728 719 cleanup_entry, &i);
729 ret = -ELOOP; 720 return ret;
730 if (!mark_source_chains(newinfo, valid_hooks, entry0)) 721 }
731 goto cleanup;
732 722
733 /* And one copy for every other CPU */ 723 /* And one copy for every other CPU */
734 for_each_possible_cpu(i) { 724 for_each_possible_cpu(i) {
@@ -736,9 +726,6 @@ translate_table(const char *name,
736 memcpy(newinfo->entries[i], entry0, newinfo->size); 726 memcpy(newinfo->entries[i], entry0, newinfo->size);
737 } 727 }
738 728
739 return 0;
740cleanup:
741 IPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
742 return ret; 729 return ret;
743} 730}
744 731
@@ -1529,25 +1516,8 @@ static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
1529 void **dstptr, compat_uint_t *size, const char *name, 1516 void **dstptr, compat_uint_t *size, const char *name,
1530 const struct ipt_ip *ip, unsigned int hookmask) 1517 const struct ipt_ip *ip, unsigned int hookmask)
1531{ 1518{
1532 struct ipt_entry_match *dm;
1533 struct ipt_match *match;
1534 int ret;
1535
1536 dm = (struct ipt_entry_match *)*dstptr;
1537 match = m->u.kernel.match;
1538 xt_compat_match_from_user(m, dstptr, size); 1519 xt_compat_match_from_user(m, dstptr, size);
1539 1520 return 0;
1540 ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
1541 name, hookmask, ip->proto,
1542 ip->invflags & IPT_INV_PROTO);
1543 if (!ret && m->u.kernel.match->checkentry
1544 && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
1545 hookmask)) {
1546 duprintf("ip_tables: check failed for `%s'.\n",
1547 m->u.kernel.match->name);
1548 ret = -EINVAL;
1549 }
1550 return ret;
1551} 1521}
1552 1522
1553static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, 1523static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
@@ -1569,7 +1539,7 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
1569 ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size, 1539 ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
1570 name, &de->ip, de->comefrom); 1540 name, &de->ip, de->comefrom);
1571 if (ret) 1541 if (ret)
1572 goto err; 1542 return ret;
1573 de->target_offset = e->target_offset - (origsize - *size); 1543 de->target_offset = e->target_offset - (origsize - *size);
1574 t = ipt_get_target(e); 1544 t = ipt_get_target(e);
1575 target = t->u.kernel.target; 1545 target = t->u.kernel.target;
@@ -1582,31 +1552,62 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
1582 if ((unsigned char *)de - base < newinfo->underflow[h]) 1552 if ((unsigned char *)de - base < newinfo->underflow[h])
1583 newinfo->underflow[h] -= origsize - *size; 1553 newinfo->underflow[h] -= origsize - *size;
1584 } 1554 }
1555 return ret;
1556}
1557
1558static inline int compat_check_match(struct ipt_entry_match *m, const char *name,
1559 const struct ipt_ip *ip, unsigned int hookmask)
1560{
1561 struct ipt_match *match;
1562 int ret;
1563
1564 match = m->u.kernel.match;
1565 ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
1566 name, hookmask, ip->proto,
1567 ip->invflags & IPT_INV_PROTO);
1568 if (!ret && m->u.kernel.match->checkentry
1569 && !m->u.kernel.match->checkentry(name, ip, match, m->data,
1570 hookmask)) {
1571 duprintf("ip_tables: compat: check failed for `%s'.\n",
1572 m->u.kernel.match->name);
1573 ret = -EINVAL;
1574 }
1575 return ret;
1576}
1577
1578static inline int compat_check_target(struct ipt_entry *e, const char *name)
1579{
1580 struct ipt_entry_target *t;
1581 struct ipt_target *target;
1582 int ret;
1585 1583
1586 t = ipt_get_target(de); 1584 t = ipt_get_target(e);
1587 target = t->u.kernel.target; 1585 target = t->u.kernel.target;
1588 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), 1586 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
1589 name, e->comefrom, e->ip.proto, 1587 name, e->comefrom, e->ip.proto,
1590 e->ip.invflags & IPT_INV_PROTO); 1588 e->ip.invflags & IPT_INV_PROTO);
1591 if (ret) 1589 if (!ret && t->u.kernel.target->checkentry
1592 goto err; 1590 && !t->u.kernel.target->checkentry(name, e, target,
1593 1591 t->data, e->comefrom)) {
1594 ret = -EINVAL;
1595 if (t->u.kernel.target == &ipt_standard_target) {
1596 if (!standard_check(t, *size))
1597 goto err;
1598 } else if (t->u.kernel.target->checkentry
1599 && !t->u.kernel.target->checkentry(name, de, target,
1600 t->data, de->comefrom)) {
1601 duprintf("ip_tables: compat: check failed for `%s'.\n", 1592 duprintf("ip_tables: compat: check failed for `%s'.\n",
1602 t->u.kernel.target->name); 1593 t->u.kernel.target->name);
1603 goto err; 1594 ret = -EINVAL;
1604 } 1595 }
1605 ret = 0;
1606err:
1607 return ret; 1596 return ret;
1608} 1597}
1609 1598
1599static inline int compat_check_entry(struct ipt_entry *e, const char *name)
1600{
1601 int ret;
1602
1603 ret = IPT_MATCH_ITERATE(e, compat_check_match, name, &e->ip,
1604 e->comefrom);
1605 if (ret)
1606 return ret;
1607
1608 return compat_check_target(e, name);
1609}
1610
1610static int 1611static int
1611translate_compat_table(const char *name, 1612translate_compat_table(const char *name,
1612 unsigned int valid_hooks, 1613 unsigned int valid_hooks,
@@ -1695,6 +1696,11 @@ translate_compat_table(const char *name,
1695 if (!mark_source_chains(newinfo, valid_hooks, entry1)) 1696 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1696 goto free_newinfo; 1697 goto free_newinfo;
1697 1698
1699 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1700 name);
1701 if (ret)
1702 goto free_newinfo;
1703
1698 /* And one copy for every other CPU */ 1704 /* And one copy for every other CPU */
1699 for_each_possible_cpu(i) 1705 for_each_possible_cpu(i)
1700 if (newinfo->entries[i] && newinfo->entries[i] != entry1) 1706 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 9f3924c4905e..11c167118e87 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1780,7 +1780,7 @@ static inline int __mkroute_input(struct sk_buff *skb,
1780#endif 1780#endif
1781 if (in_dev->cnf.no_policy) 1781 if (in_dev->cnf.no_policy)
1782 rth->u.dst.flags |= DST_NOPOLICY; 1782 rth->u.dst.flags |= DST_NOPOLICY;
1783 if (in_dev->cnf.no_xfrm) 1783 if (out_dev->cnf.no_xfrm)
1784 rth->u.dst.flags |= DST_NOXFRM; 1784 rth->u.dst.flags |= DST_NOXFRM;
1785 rth->fl.fl4_dst = daddr; 1785 rth->fl.fl4_dst = daddr;
1786 rth->rt_dst = daddr; 1786 rth->rt_dst = daddr;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 9304034c0c47..c701f6abbfc1 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4235,7 +4235,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
4235 * Change state from SYN-SENT only after copied_seq 4235 * Change state from SYN-SENT only after copied_seq
4236 * is initialized. */ 4236 * is initialized. */
4237 tp->copied_seq = tp->rcv_nxt; 4237 tp->copied_seq = tp->rcv_nxt;
4238 mb(); 4238 smp_mb();
4239 tcp_set_state(sk, TCP_ESTABLISHED); 4239 tcp_set_state(sk, TCP_ESTABLISHED);
4240 4240
4241 security_inet_conn_established(sk, skb); 4241 security_inet_conn_established(sk, skb);
@@ -4483,7 +4483,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
4483 case TCP_SYN_RECV: 4483 case TCP_SYN_RECV:
4484 if (acceptable) { 4484 if (acceptable) {
4485 tp->copied_seq = tp->rcv_nxt; 4485 tp->copied_seq = tp->rcv_nxt;
4486 mb(); 4486 smp_mb();
4487 tcp_set_state(sk, TCP_ESTABLISHED); 4487 tcp_set_state(sk, TCP_ESTABLISHED);
4488 sk->sk_state_change(sk); 4488 sk->sk_state_change(sk);
4489 4489
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index d4107bb701b5..fb9f69c616f5 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -274,6 +274,8 @@ static void xfrm4_dst_destroy(struct dst_entry *dst)
274 274
275 if (likely(xdst->u.rt.idev)) 275 if (likely(xdst->u.rt.idev))
276 in_dev_put(xdst->u.rt.idev); 276 in_dev_put(xdst->u.rt.idev);
277 if (likely(xdst->u.rt.peer))
278 inet_putpeer(xdst->u.rt.peer);
277 xfrm_dst_destroy(xdst); 279 xfrm_dst_destroy(xdst);
278} 280}
279 281