diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-09-28 18:18:35 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-09-28 18:18:35 -0400 |
commit | f8ab18d2d987a59ccbf0495032b2aef05b730037 (patch) | |
tree | 7a24c79632c91e22235888875813950c6c30d929 | |
parent | e79ad711a0108475c1b3a03815527e7237020b08 (diff) |
[TCP]: Fix MD5 signature handling on big-endian.
Based upon a report and initial patch by Peter Lieven.
tcp4_md5sig_key and tcp6_md5sig_key need to start with
the exact same members as tcp_md5sig_key. Because they
are both cast to that type by tcp_v{4,6}_md5_do_lookup().
Unfortunately tcp{4,6}_md5sig_key use a u16 for the key
length instead of a u8, which is what tcp_md5sig_key
uses. This just so happens to work by accident on
little-endian, but on big-endian it doesn't.
Instead of casting, just place tcp_md5sig_key as the first member of
the address-family specific structures, adjust the access sites, and
kill off the ugly casts.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/tcp.h | 6 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 19 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 18 |
3 files changed, 20 insertions, 23 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index 185c7ecce4c..54053de0bdd 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -1059,14 +1059,12 @@ struct tcp_md5sig_key { | |||
1059 | }; | 1059 | }; |
1060 | 1060 | ||
1061 | struct tcp4_md5sig_key { | 1061 | struct tcp4_md5sig_key { |
1062 | u8 *key; | 1062 | struct tcp_md5sig_key base; |
1063 | u16 keylen; | ||
1064 | __be32 addr; | 1063 | __be32 addr; |
1065 | }; | 1064 | }; |
1066 | 1065 | ||
1067 | struct tcp6_md5sig_key { | 1066 | struct tcp6_md5sig_key { |
1068 | u8 *key; | 1067 | struct tcp_md5sig_key base; |
1069 | u16 keylen; | ||
1070 | #if 0 | 1068 | #if 0 |
1071 | u32 scope_id; /* XXX */ | 1069 | u32 scope_id; /* XXX */ |
1072 | #endif | 1070 | #endif |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 9c94627c8c7..e089a978e12 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -833,8 +833,7 @@ static struct tcp_md5sig_key * | |||
833 | return NULL; | 833 | return NULL; |
834 | for (i = 0; i < tp->md5sig_info->entries4; i++) { | 834 | for (i = 0; i < tp->md5sig_info->entries4; i++) { |
835 | if (tp->md5sig_info->keys4[i].addr == addr) | 835 | if (tp->md5sig_info->keys4[i].addr == addr) |
836 | return (struct tcp_md5sig_key *) | 836 | return &tp->md5sig_info->keys4[i].base; |
837 | &tp->md5sig_info->keys4[i]; | ||
838 | } | 837 | } |
839 | return NULL; | 838 | return NULL; |
840 | } | 839 | } |
@@ -865,9 +864,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, | |||
865 | key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr); | 864 | key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr); |
866 | if (key) { | 865 | if (key) { |
867 | /* Pre-existing entry - just update that one. */ | 866 | /* Pre-existing entry - just update that one. */ |
868 | kfree(key->key); | 867 | kfree(key->base.key); |
869 | key->key = newkey; | 868 | key->base.key = newkey; |
870 | key->keylen = newkeylen; | 869 | key->base.keylen = newkeylen; |
871 | } else { | 870 | } else { |
872 | struct tcp_md5sig_info *md5sig; | 871 | struct tcp_md5sig_info *md5sig; |
873 | 872 | ||
@@ -906,9 +905,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, | |||
906 | md5sig->alloced4++; | 905 | md5sig->alloced4++; |
907 | } | 906 | } |
908 | md5sig->entries4++; | 907 | md5sig->entries4++; |
909 | md5sig->keys4[md5sig->entries4 - 1].addr = addr; | 908 | md5sig->keys4[md5sig->entries4 - 1].addr = addr; |
910 | md5sig->keys4[md5sig->entries4 - 1].key = newkey; | 909 | md5sig->keys4[md5sig->entries4 - 1].base.key = newkey; |
911 | md5sig->keys4[md5sig->entries4 - 1].keylen = newkeylen; | 910 | md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen; |
912 | } | 911 | } |
913 | return 0; | 912 | return 0; |
914 | } | 913 | } |
@@ -930,7 +929,7 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) | |||
930 | for (i = 0; i < tp->md5sig_info->entries4; i++) { | 929 | for (i = 0; i < tp->md5sig_info->entries4; i++) { |
931 | if (tp->md5sig_info->keys4[i].addr == addr) { | 930 | if (tp->md5sig_info->keys4[i].addr == addr) { |
932 | /* Free the key */ | 931 | /* Free the key */ |
933 | kfree(tp->md5sig_info->keys4[i].key); | 932 | kfree(tp->md5sig_info->keys4[i].base.key); |
934 | tp->md5sig_info->entries4--; | 933 | tp->md5sig_info->entries4--; |
935 | 934 | ||
936 | if (tp->md5sig_info->entries4 == 0) { | 935 | if (tp->md5sig_info->entries4 == 0) { |
@@ -964,7 +963,7 @@ static void tcp_v4_clear_md5_list(struct sock *sk) | |||
964 | if (tp->md5sig_info->entries4) { | 963 | if (tp->md5sig_info->entries4) { |
965 | int i; | 964 | int i; |
966 | for (i = 0; i < tp->md5sig_info->entries4; i++) | 965 | for (i = 0; i < tp->md5sig_info->entries4; i++) |
967 | kfree(tp->md5sig_info->keys4[i].key); | 966 | kfree(tp->md5sig_info->keys4[i].base.key); |
968 | tp->md5sig_info->entries4 = 0; | 967 | tp->md5sig_info->entries4 = 0; |
969 | tcp_free_md5sig_pool(); | 968 | tcp_free_md5sig_pool(); |
970 | } | 969 | } |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0f7defb482e..3e06799b37a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -539,7 +539,7 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | |||
539 | 539 | ||
540 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | 540 | for (i = 0; i < tp->md5sig_info->entries6; i++) { |
541 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0) | 541 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0) |
542 | return (struct tcp_md5sig_key *)&tp->md5sig_info->keys6[i]; | 542 | return &tp->md5sig_info->keys6[i].base; |
543 | } | 543 | } |
544 | return NULL; | 544 | return NULL; |
545 | } | 545 | } |
@@ -567,9 +567,9 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, | |||
567 | key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer); | 567 | key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer); |
568 | if (key) { | 568 | if (key) { |
569 | /* modify existing entry - just update that one */ | 569 | /* modify existing entry - just update that one */ |
570 | kfree(key->key); | 570 | kfree(key->base.key); |
571 | key->key = newkey; | 571 | key->base.key = newkey; |
572 | key->keylen = newkeylen; | 572 | key->base.keylen = newkeylen; |
573 | } else { | 573 | } else { |
574 | /* reallocate new list if current one is full. */ | 574 | /* reallocate new list if current one is full. */ |
575 | if (!tp->md5sig_info) { | 575 | if (!tp->md5sig_info) { |
@@ -603,8 +603,8 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, | |||
603 | 603 | ||
604 | ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr, | 604 | ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr, |
605 | peer); | 605 | peer); |
606 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].key = newkey; | 606 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.key = newkey; |
607 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].keylen = newkeylen; | 607 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.keylen = newkeylen; |
608 | 608 | ||
609 | tp->md5sig_info->entries6++; | 609 | tp->md5sig_info->entries6++; |
610 | } | 610 | } |
@@ -626,7 +626,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) | |||
626 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | 626 | for (i = 0; i < tp->md5sig_info->entries6; i++) { |
627 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) { | 627 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) { |
628 | /* Free the key */ | 628 | /* Free the key */ |
629 | kfree(tp->md5sig_info->keys6[i].key); | 629 | kfree(tp->md5sig_info->keys6[i].base.key); |
630 | tp->md5sig_info->entries6--; | 630 | tp->md5sig_info->entries6--; |
631 | 631 | ||
632 | if (tp->md5sig_info->entries6 == 0) { | 632 | if (tp->md5sig_info->entries6 == 0) { |
@@ -657,7 +657,7 @@ static void tcp_v6_clear_md5_list (struct sock *sk) | |||
657 | 657 | ||
658 | if (tp->md5sig_info->entries6) { | 658 | if (tp->md5sig_info->entries6) { |
659 | for (i = 0; i < tp->md5sig_info->entries6; i++) | 659 | for (i = 0; i < tp->md5sig_info->entries6; i++) |
660 | kfree(tp->md5sig_info->keys6[i].key); | 660 | kfree(tp->md5sig_info->keys6[i].base.key); |
661 | tp->md5sig_info->entries6 = 0; | 661 | tp->md5sig_info->entries6 = 0; |
662 | tcp_free_md5sig_pool(); | 662 | tcp_free_md5sig_pool(); |
663 | } | 663 | } |
@@ -668,7 +668,7 @@ static void tcp_v6_clear_md5_list (struct sock *sk) | |||
668 | 668 | ||
669 | if (tp->md5sig_info->entries4) { | 669 | if (tp->md5sig_info->entries4) { |
670 | for (i = 0; i < tp->md5sig_info->entries4; i++) | 670 | for (i = 0; i < tp->md5sig_info->entries4; i++) |
671 | kfree(tp->md5sig_info->keys4[i].key); | 671 | kfree(tp->md5sig_info->keys4[i].base.key); |
672 | tp->md5sig_info->entries4 = 0; | 672 | tp->md5sig_info->entries4 = 0; |
673 | tcp_free_md5sig_pool(); | 673 | tcp_free_md5sig_pool(); |
674 | } | 674 | } |