Commit f8ab18d2 authored by David S. Miller's avatar David S. Miller

[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: default avatarDavid S. Miller <davem@davemloft.net>
parent e79ad711
...@@ -1059,14 +1059,12 @@ struct tcp_md5sig_key { ...@@ -1059,14 +1059,12 @@ struct tcp_md5sig_key {
}; };
struct tcp4_md5sig_key { struct tcp4_md5sig_key {
u8 *key; struct tcp_md5sig_key base;
u16 keylen;
__be32 addr; __be32 addr;
}; };
struct tcp6_md5sig_key { struct tcp6_md5sig_key {
u8 *key; struct tcp_md5sig_key base;
u16 keylen;
#if 0 #if 0
u32 scope_id; /* XXX */ u32 scope_id; /* XXX */
#endif #endif
......
...@@ -833,8 +833,7 @@ static struct tcp_md5sig_key * ...@@ -833,8 +833,7 @@ static struct tcp_md5sig_key *
return NULL; return NULL;
for (i = 0; i < tp->md5sig_info->entries4; i++) { for (i = 0; i < tp->md5sig_info->entries4; i++) {
if (tp->md5sig_info->keys4[i].addr == addr) if (tp->md5sig_info->keys4[i].addr == addr)
return (struct tcp_md5sig_key *) return &tp->md5sig_info->keys4[i].base;
&tp->md5sig_info->keys4[i];
} }
return NULL; return NULL;
} }
...@@ -865,9 +864,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, ...@@ -865,9 +864,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr); key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr);
if (key) { if (key) {
/* Pre-existing entry - just update that one. */ /* Pre-existing entry - just update that one. */
kfree(key->key); kfree(key->base.key);
key->key = newkey; key->base.key = newkey;
key->keylen = newkeylen; key->base.keylen = newkeylen;
} else { } else {
struct tcp_md5sig_info *md5sig; struct tcp_md5sig_info *md5sig;
...@@ -906,9 +905,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, ...@@ -906,9 +905,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
md5sig->alloced4++; md5sig->alloced4++;
} }
md5sig->entries4++; md5sig->entries4++;
md5sig->keys4[md5sig->entries4 - 1].addr = addr; md5sig->keys4[md5sig->entries4 - 1].addr = addr;
md5sig->keys4[md5sig->entries4 - 1].key = newkey; md5sig->keys4[md5sig->entries4 - 1].base.key = newkey;
md5sig->keys4[md5sig->entries4 - 1].keylen = newkeylen; md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen;
} }
return 0; return 0;
} }
...@@ -930,7 +929,7 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) ...@@ -930,7 +929,7 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr)
for (i = 0; i < tp->md5sig_info->entries4; i++) { for (i = 0; i < tp->md5sig_info->entries4; i++) {
if (tp->md5sig_info->keys4[i].addr == addr) { if (tp->md5sig_info->keys4[i].addr == addr) {
/* Free the key */ /* Free the key */
kfree(tp->md5sig_info->keys4[i].key); kfree(tp->md5sig_info->keys4[i].base.key);
tp->md5sig_info->entries4--; tp->md5sig_info->entries4--;
if (tp->md5sig_info->entries4 == 0) { if (tp->md5sig_info->entries4 == 0) {
...@@ -964,7 +963,7 @@ static void tcp_v4_clear_md5_list(struct sock *sk) ...@@ -964,7 +963,7 @@ static void tcp_v4_clear_md5_list(struct sock *sk)
if (tp->md5sig_info->entries4) { if (tp->md5sig_info->entries4) {
int i; int i;
for (i = 0; i < tp->md5sig_info->entries4; i++) for (i = 0; i < tp->md5sig_info->entries4; i++)
kfree(tp->md5sig_info->keys4[i].key); kfree(tp->md5sig_info->keys4[i].base.key);
tp->md5sig_info->entries4 = 0; tp->md5sig_info->entries4 = 0;
tcp_free_md5sig_pool(); tcp_free_md5sig_pool();
} }
......
...@@ -539,7 +539,7 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, ...@@ -539,7 +539,7 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
for (i = 0; i < tp->md5sig_info->entries6; i++) { for (i = 0; i < tp->md5sig_info->entries6; i++) {
if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0) if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0)
return (struct tcp_md5sig_key *)&tp->md5sig_info->keys6[i]; return &tp->md5sig_info->keys6[i].base;
} }
return NULL; return NULL;
} }
...@@ -567,9 +567,9 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, ...@@ -567,9 +567,9 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer,
key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer); key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer);
if (key) { if (key) {
/* modify existing entry - just update that one */ /* modify existing entry - just update that one */
kfree(key->key); kfree(key->base.key);
key->key = newkey; key->base.key = newkey;
key->keylen = newkeylen; key->base.keylen = newkeylen;
} else { } else {
/* reallocate new list if current one is full. */ /* reallocate new list if current one is full. */
if (!tp->md5sig_info) { if (!tp->md5sig_info) {
...@@ -603,8 +603,8 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, ...@@ -603,8 +603,8 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer,
ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr, ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr,
peer); peer);
tp->md5sig_info->keys6[tp->md5sig_info->entries6].key = newkey; tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.key = newkey;
tp->md5sig_info->keys6[tp->md5sig_info->entries6].keylen = newkeylen; tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.keylen = newkeylen;
tp->md5sig_info->entries6++; tp->md5sig_info->entries6++;
} }
...@@ -626,7 +626,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) ...@@ -626,7 +626,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer)
for (i = 0; i < tp->md5sig_info->entries6; i++) { for (i = 0; i < tp->md5sig_info->entries6; i++) {
if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) { if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) {
/* Free the key */ /* Free the key */
kfree(tp->md5sig_info->keys6[i].key); kfree(tp->md5sig_info->keys6[i].base.key);
tp->md5sig_info->entries6--; tp->md5sig_info->entries6--;
if (tp->md5sig_info->entries6 == 0) { if (tp->md5sig_info->entries6 == 0) {
...@@ -657,7 +657,7 @@ static void tcp_v6_clear_md5_list (struct sock *sk) ...@@ -657,7 +657,7 @@ static void tcp_v6_clear_md5_list (struct sock *sk)
if (tp->md5sig_info->entries6) { if (tp->md5sig_info->entries6) {
for (i = 0; i < tp->md5sig_info->entries6; i++) for (i = 0; i < tp->md5sig_info->entries6; i++)
kfree(tp->md5sig_info->keys6[i].key); kfree(tp->md5sig_info->keys6[i].base.key);
tp->md5sig_info->entries6 = 0; tp->md5sig_info->entries6 = 0;
tcp_free_md5sig_pool(); tcp_free_md5sig_pool();
} }
...@@ -668,7 +668,7 @@ static void tcp_v6_clear_md5_list (struct sock *sk) ...@@ -668,7 +668,7 @@ static void tcp_v6_clear_md5_list (struct sock *sk)
if (tp->md5sig_info->entries4) { if (tp->md5sig_info->entries4) {
for (i = 0; i < tp->md5sig_info->entries4; i++) for (i = 0; i < tp->md5sig_info->entries4; i++)
kfree(tp->md5sig_info->keys4[i].key); kfree(tp->md5sig_info->keys4[i].base.key);
tp->md5sig_info->entries4 = 0; tp->md5sig_info->entries4 = 0;
tcp_free_md5sig_pool(); tcp_free_md5sig_pool();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment