diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 227 | ||||
-rw-r--r-- | net/ipv4/tcp_minisocks.c | 12 |
2 files changed, 99 insertions, 140 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 345e24928fa6..1d5fd82c5c08 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -90,16 +90,8 @@ EXPORT_SYMBOL(sysctl_tcp_low_latency); | |||
90 | 90 | ||
91 | 91 | ||
92 | #ifdef CONFIG_TCP_MD5SIG | 92 | #ifdef CONFIG_TCP_MD5SIG |
93 | static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, | 93 | static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key, |
94 | __be32 addr); | ||
95 | static int tcp_v4_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, | ||
96 | __be32 daddr, __be32 saddr, const struct tcphdr *th); | 94 | __be32 daddr, __be32 saddr, const struct tcphdr *th); |
97 | #else | ||
98 | static inline | ||
99 | struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) | ||
100 | { | ||
101 | return NULL; | ||
102 | } | ||
103 | #endif | 95 | #endif |
104 | 96 | ||
105 | struct inet_hashinfo tcp_hashinfo; | 97 | struct inet_hashinfo tcp_hashinfo; |
@@ -631,7 +623,9 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
631 | arg.iov[0].iov_len = sizeof(rep.th); | 623 | arg.iov[0].iov_len = sizeof(rep.th); |
632 | 624 | ||
633 | #ifdef CONFIG_TCP_MD5SIG | 625 | #ifdef CONFIG_TCP_MD5SIG |
634 | key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr) : NULL; | 626 | key = sk ? tcp_md5_do_lookup(sk, |
627 | (union tcp_md5_addr *)&ip_hdr(skb)->saddr, | ||
628 | AF_INET) : NULL; | ||
635 | if (key) { | 629 | if (key) { |
636 | rep.opt[0] = htonl((TCPOPT_NOP << 24) | | 630 | rep.opt[0] = htonl((TCPOPT_NOP << 24) | |
637 | (TCPOPT_NOP << 16) | | 631 | (TCPOPT_NOP << 16) | |
@@ -759,7 +753,8 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
759 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, | 753 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, |
760 | req->ts_recent, | 754 | req->ts_recent, |
761 | 0, | 755 | 0, |
762 | tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr), | 756 | tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->daddr, |
757 | AF_INET), | ||
763 | inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0, | 758 | inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0, |
764 | ip_hdr(skb)->tos); | 759 | ip_hdr(skb)->tos); |
765 | } | 760 | } |
@@ -876,146 +871,124 @@ static struct ip_options_rcu *tcp_v4_save_options(struct sock *sk, | |||
876 | */ | 871 | */ |
877 | 872 | ||
878 | /* Find the Key structure for an address. */ | 873 | /* Find the Key structure for an address. */ |
879 | static struct tcp_md5sig_key * | 874 | struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk, |
880 | tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) | 875 | const union tcp_md5_addr *addr, |
876 | int family) | ||
881 | { | 877 | { |
882 | struct tcp_sock *tp = tcp_sk(sk); | 878 | struct tcp_sock *tp = tcp_sk(sk); |
883 | int i; | 879 | struct tcp_md5sig_key *key; |
880 | struct hlist_node *pos; | ||
881 | unsigned int size = sizeof(struct in_addr); | ||
884 | 882 | ||
885 | if (!tp->md5sig_info || !tp->md5sig_info->entries4) | 883 | if (!tp->md5sig_info) |
886 | return NULL; | 884 | return NULL; |
887 | for (i = 0; i < tp->md5sig_info->entries4; i++) { | 885 | #if IS_ENABLED(CONFIG_IPV6) |
888 | if (tp->md5sig_info->keys4[i].addr == addr) | 886 | if (family == AF_INET6) |
889 | return &tp->md5sig_info->keys4[i].base; | 887 | size = sizeof(struct in6_addr); |
888 | #endif | ||
889 | hlist_for_each_entry_rcu(key, pos, &tp->md5sig_info->head, node) { | ||
890 | if (key->family != family) | ||
891 | continue; | ||
892 | if (!memcmp(&key->addr, addr, size)) | ||
893 | return key; | ||
890 | } | 894 | } |
891 | return NULL; | 895 | return NULL; |
892 | } | 896 | } |
897 | EXPORT_SYMBOL(tcp_md5_do_lookup); | ||
893 | 898 | ||
894 | struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, | 899 | struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, |
895 | struct sock *addr_sk) | 900 | struct sock *addr_sk) |
896 | { | 901 | { |
897 | return tcp_v4_md5_do_lookup(sk, inet_sk(addr_sk)->inet_daddr); | 902 | union tcp_md5_addr *addr; |
903 | |||
904 | addr = (union tcp_md5_addr *)&inet_sk(addr_sk)->inet_daddr; | ||
905 | return tcp_md5_do_lookup(sk, addr, AF_INET); | ||
898 | } | 906 | } |
899 | EXPORT_SYMBOL(tcp_v4_md5_lookup); | 907 | EXPORT_SYMBOL(tcp_v4_md5_lookup); |
900 | 908 | ||
901 | static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk, | 909 | static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk, |
902 | struct request_sock *req) | 910 | struct request_sock *req) |
903 | { | 911 | { |
904 | return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr); | 912 | union tcp_md5_addr *addr; |
913 | |||
914 | addr = (union tcp_md5_addr *)&inet_rsk(req)->rmt_addr; | ||
915 | return tcp_md5_do_lookup(sk, addr, AF_INET); | ||
905 | } | 916 | } |
906 | 917 | ||
907 | /* This can be called on a newly created socket, from other files */ | 918 | /* This can be called on a newly created socket, from other files */ |
908 | int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, | 919 | int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, |
909 | u8 *newkey, u8 newkeylen) | 920 | int family, const u8 *newkey, u8 newkeylen, gfp_t gfp) |
910 | { | 921 | { |
911 | /* Add Key to the list */ | 922 | /* Add Key to the list */ |
912 | struct tcp_md5sig_key *key; | 923 | struct tcp_md5sig_key *key; |
913 | struct tcp_sock *tp = tcp_sk(sk); | 924 | struct tcp_sock *tp = tcp_sk(sk); |
914 | struct tcp4_md5sig_key *keys; | 925 | struct tcp_md5sig_info *md5sig; |
915 | 926 | ||
916 | key = tcp_v4_md5_do_lookup(sk, addr); | 927 | key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET); |
917 | if (key) { | 928 | if (key) { |
918 | /* Pre-existing entry - just update that one. */ | 929 | /* Pre-existing entry - just update that one. */ |
919 | kfree(key->key); | 930 | memcpy(key->key, newkey, newkeylen); |
920 | key->key = newkey; | ||
921 | key->keylen = newkeylen; | 931 | key->keylen = newkeylen; |
922 | } else { | 932 | return 0; |
923 | struct tcp_md5sig_info *md5sig; | 933 | } |
924 | |||
925 | if (!tp->md5sig_info) { | ||
926 | tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info), | ||
927 | GFP_ATOMIC); | ||
928 | if (!tp->md5sig_info) { | ||
929 | kfree(newkey); | ||
930 | return -ENOMEM; | ||
931 | } | ||
932 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); | ||
933 | } | ||
934 | 934 | ||
935 | md5sig = tp->md5sig_info; | 935 | md5sig = tp->md5sig_info; |
936 | if (md5sig->entries4 == 0 && | 936 | if (!md5sig) { |
937 | tcp_alloc_md5sig_pool(sk) == NULL) { | 937 | md5sig = kmalloc(sizeof(*md5sig), gfp); |
938 | kfree(newkey); | 938 | if (!md5sig) |
939 | return -ENOMEM; | 939 | return -ENOMEM; |
940 | } | ||
941 | |||
942 | if (md5sig->alloced4 == md5sig->entries4) { | ||
943 | keys = kmalloc((sizeof(*keys) * | ||
944 | (md5sig->entries4 + 1)), GFP_ATOMIC); | ||
945 | if (!keys) { | ||
946 | kfree(newkey); | ||
947 | if (md5sig->entries4 == 0) | ||
948 | tcp_free_md5sig_pool(); | ||
949 | return -ENOMEM; | ||
950 | } | ||
951 | 940 | ||
952 | if (md5sig->entries4) | 941 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
953 | memcpy(keys, md5sig->keys4, | 942 | INIT_HLIST_HEAD(&md5sig->head); |
954 | sizeof(*keys) * md5sig->entries4); | 943 | tp->md5sig_info = md5sig; |
944 | } | ||
955 | 945 | ||
956 | /* Free old key list, and reference new one */ | 946 | key = kmalloc(sizeof(*key), gfp); |
957 | kfree(md5sig->keys4); | 947 | if (!key) |
958 | md5sig->keys4 = keys; | 948 | return -ENOMEM; |
959 | md5sig->alloced4++; | 949 | if (hlist_empty(&md5sig->head) && !tcp_alloc_md5sig_pool(sk)) { |
960 | } | 950 | kfree(key); |
961 | md5sig->entries4++; | 951 | return -ENOMEM; |
962 | md5sig->keys4[md5sig->entries4 - 1].addr = addr; | ||
963 | md5sig->keys4[md5sig->entries4 - 1].base.key = newkey; | ||
964 | md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen; | ||
965 | } | 952 | } |
953 | |||
954 | memcpy(key->key, newkey, newkeylen); | ||
955 | key->keylen = newkeylen; | ||
956 | key->family = family; | ||
957 | memcpy(&key->addr, addr, | ||
958 | (family == AF_INET6) ? sizeof(struct in6_addr) : | ||
959 | sizeof(struct in_addr)); | ||
960 | hlist_add_head_rcu(&key->node, &md5sig->head); | ||
966 | return 0; | 961 | return 0; |
967 | } | 962 | } |
968 | EXPORT_SYMBOL(tcp_v4_md5_do_add); | 963 | EXPORT_SYMBOL(tcp_md5_do_add); |
969 | 964 | ||
970 | int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) | 965 | int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family) |
971 | { | 966 | { |
972 | struct tcp_sock *tp = tcp_sk(sk); | 967 | struct tcp_sock *tp = tcp_sk(sk); |
973 | int i; | 968 | struct tcp_md5sig_key *key; |
974 | 969 | ||
975 | for (i = 0; i < tp->md5sig_info->entries4; i++) { | 970 | key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET); |
976 | if (tp->md5sig_info->keys4[i].addr == addr) { | 971 | if (!key) |
977 | /* Free the key */ | 972 | return -ENOENT; |
978 | kfree(tp->md5sig_info->keys4[i].base.key); | 973 | hlist_del_rcu(&key->node); |
979 | tp->md5sig_info->entries4--; | 974 | kfree_rcu(key, rcu); |
980 | 975 | if (hlist_empty(&tp->md5sig_info->head)) | |
981 | if (tp->md5sig_info->entries4 == 0) { | 976 | tcp_free_md5sig_pool(); |
982 | kfree(tp->md5sig_info->keys4); | 977 | return 0; |
983 | tp->md5sig_info->keys4 = NULL; | ||
984 | tp->md5sig_info->alloced4 = 0; | ||
985 | tcp_free_md5sig_pool(); | ||
986 | } else if (tp->md5sig_info->entries4 != i) { | ||
987 | /* Need to do some manipulation */ | ||
988 | memmove(&tp->md5sig_info->keys4[i], | ||
989 | &tp->md5sig_info->keys4[i+1], | ||
990 | (tp->md5sig_info->entries4 - i) * | ||
991 | sizeof(struct tcp4_md5sig_key)); | ||
992 | } | ||
993 | return 0; | ||
994 | } | ||
995 | } | ||
996 | return -ENOENT; | ||
997 | } | 978 | } |
998 | EXPORT_SYMBOL(tcp_v4_md5_do_del); | 979 | EXPORT_SYMBOL(tcp_md5_do_del); |
999 | 980 | ||
1000 | static void tcp_v4_clear_md5_list(struct sock *sk) | 981 | void tcp_clear_md5_list(struct sock *sk) |
1001 | { | 982 | { |
1002 | struct tcp_sock *tp = tcp_sk(sk); | 983 | struct tcp_sock *tp = tcp_sk(sk); |
984 | struct tcp_md5sig_key *key; | ||
985 | struct hlist_node *pos, *n; | ||
1003 | 986 | ||
1004 | /* Free each key, then the set of key keys, | 987 | if (!hlist_empty(&tp->md5sig_info->head)) |
1005 | * the crypto element, and then decrement our | ||
1006 | * hold on the last resort crypto. | ||
1007 | */ | ||
1008 | if (tp->md5sig_info->entries4) { | ||
1009 | int i; | ||
1010 | for (i = 0; i < tp->md5sig_info->entries4; i++) | ||
1011 | kfree(tp->md5sig_info->keys4[i].base.key); | ||
1012 | tp->md5sig_info->entries4 = 0; | ||
1013 | tcp_free_md5sig_pool(); | 988 | tcp_free_md5sig_pool(); |
1014 | } | 989 | hlist_for_each_entry_safe(key, pos, n, &tp->md5sig_info->head, node) { |
1015 | if (tp->md5sig_info->keys4) { | 990 | hlist_del_rcu(&key->node); |
1016 | kfree(tp->md5sig_info->keys4); | 991 | kfree_rcu(key, rcu); |
1017 | tp->md5sig_info->keys4 = NULL; | ||
1018 | tp->md5sig_info->alloced4 = 0; | ||
1019 | } | 992 | } |
1020 | } | 993 | } |
1021 | 994 | ||
@@ -1024,7 +997,6 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | |||
1024 | { | 997 | { |
1025 | struct tcp_md5sig cmd; | 998 | struct tcp_md5sig cmd; |
1026 | struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr; | 999 | struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr; |
1027 | u8 *newkey; | ||
1028 | 1000 | ||
1029 | if (optlen < sizeof(cmd)) | 1001 | if (optlen < sizeof(cmd)) |
1030 | return -EINVAL; | 1002 | return -EINVAL; |
@@ -1038,29 +1010,16 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | |||
1038 | if (!cmd.tcpm_key || !cmd.tcpm_keylen) { | 1010 | if (!cmd.tcpm_key || !cmd.tcpm_keylen) { |
1039 | if (!tcp_sk(sk)->md5sig_info) | 1011 | if (!tcp_sk(sk)->md5sig_info) |
1040 | return -ENOENT; | 1012 | return -ENOENT; |
1041 | return tcp_v4_md5_do_del(sk, sin->sin_addr.s_addr); | 1013 | return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr, |
1014 | AF_INET); | ||
1042 | } | 1015 | } |
1043 | 1016 | ||
1044 | if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) | 1017 | if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) |
1045 | return -EINVAL; | 1018 | return -EINVAL; |
1046 | 1019 | ||
1047 | if (!tcp_sk(sk)->md5sig_info) { | 1020 | return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr, |
1048 | struct tcp_sock *tp = tcp_sk(sk); | 1021 | AF_INET, cmd.tcpm_key, cmd.tcpm_keylen, |
1049 | struct tcp_md5sig_info *p; | 1022 | GFP_KERNEL); |
1050 | |||
1051 | p = kzalloc(sizeof(*p), sk->sk_allocation); | ||
1052 | if (!p) | ||
1053 | return -EINVAL; | ||
1054 | |||
1055 | tp->md5sig_info = p; | ||
1056 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); | ||
1057 | } | ||
1058 | |||
1059 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, sk->sk_allocation); | ||
1060 | if (!newkey) | ||
1061 | return -ENOMEM; | ||
1062 | return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr, | ||
1063 | newkey, cmd.tcpm_keylen); | ||
1064 | } | 1023 | } |
1065 | 1024 | ||
1066 | static int tcp_v4_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, | 1025 | static int tcp_v4_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, |
@@ -1086,7 +1045,7 @@ static int tcp_v4_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, | |||
1086 | return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp)); | 1045 | return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp)); |
1087 | } | 1046 | } |
1088 | 1047 | ||
1089 | static int tcp_v4_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, | 1048 | static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key, |
1090 | __be32 daddr, __be32 saddr, const struct tcphdr *th) | 1049 | __be32 daddr, __be32 saddr, const struct tcphdr *th) |
1091 | { | 1050 | { |
1092 | struct tcp_md5sig_pool *hp; | 1051 | struct tcp_md5sig_pool *hp; |
@@ -1186,7 +1145,8 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) | |||
1186 | int genhash; | 1145 | int genhash; |
1187 | unsigned char newhash[16]; | 1146 | unsigned char newhash[16]; |
1188 | 1147 | ||
1189 | hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); | 1148 | hash_expected = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&iph->saddr, |
1149 | AF_INET); | ||
1190 | hash_location = tcp_parse_md5sig_option(th); | 1150 | hash_location = tcp_parse_md5sig_option(th); |
1191 | 1151 | ||
1192 | /* We've parsed the options - do we have a hash? */ | 1152 | /* We've parsed the options - do we have a hash? */ |
@@ -1474,7 +1434,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1474 | 1434 | ||
1475 | #ifdef CONFIG_TCP_MD5SIG | 1435 | #ifdef CONFIG_TCP_MD5SIG |
1476 | /* Copy over the MD5 key from the original socket */ | 1436 | /* Copy over the MD5 key from the original socket */ |
1477 | key = tcp_v4_md5_do_lookup(sk, newinet->inet_daddr); | 1437 | key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&newinet->inet_daddr, |
1438 | AF_INET); | ||
1478 | if (key != NULL) { | 1439 | if (key != NULL) { |
1479 | /* | 1440 | /* |
1480 | * We're using one, so create a matching key | 1441 | * We're using one, so create a matching key |
@@ -1482,10 +1443,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1482 | * memory, then we end up not copying the key | 1443 | * memory, then we end up not copying the key |
1483 | * across. Shucks. | 1444 | * across. Shucks. |
1484 | */ | 1445 | */ |
1485 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); | 1446 | tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newinet->inet_daddr, |
1486 | if (newkey != NULL) | 1447 | AF_INET, key->key, key->keylen, GFP_ATOMIC); |
1487 | tcp_v4_md5_do_add(newsk, newinet->inet_daddr, | ||
1488 | newkey, key->keylen); | ||
1489 | sk_nocaps_add(newsk, NETIF_F_GSO_MASK); | 1448 | sk_nocaps_add(newsk, NETIF_F_GSO_MASK); |
1490 | } | 1449 | } |
1491 | #endif | 1450 | #endif |
@@ -1934,7 +1893,7 @@ void tcp_v4_destroy_sock(struct sock *sk) | |||
1934 | #ifdef CONFIG_TCP_MD5SIG | 1893 | #ifdef CONFIG_TCP_MD5SIG |
1935 | /* Clean up the MD5 key list, if any */ | 1894 | /* Clean up the MD5 key list, if any */ |
1936 | if (tp->md5sig_info) { | 1895 | if (tp->md5sig_info) { |
1937 | tcp_v4_clear_md5_list(sk); | 1896 | tcp_clear_md5_list(sk); |
1938 | kfree(tp->md5sig_info); | 1897 | kfree(tp->md5sig_info); |
1939 | tp->md5sig_info = NULL; | 1898 | tp->md5sig_info = NULL; |
1940 | } | 1899 | } |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 550e755747e0..3cabafb5cdd1 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -359,13 +359,11 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) | |||
359 | */ | 359 | */ |
360 | do { | 360 | do { |
361 | struct tcp_md5sig_key *key; | 361 | struct tcp_md5sig_key *key; |
362 | memset(tcptw->tw_md5_key, 0, sizeof(tcptw->tw_md5_key)); | 362 | tcptw->tw_md5_key = NULL; |
363 | tcptw->tw_md5_keylen = 0; | ||
364 | key = tp->af_specific->md5_lookup(sk, sk); | 363 | key = tp->af_specific->md5_lookup(sk, sk); |
365 | if (key != NULL) { | 364 | if (key != NULL) { |
366 | memcpy(&tcptw->tw_md5_key, key->key, key->keylen); | 365 | tcptw->tw_md5_key = kmemdup(key, sizeof(*key), GFP_ATOMIC); |
367 | tcptw->tw_md5_keylen = key->keylen; | 366 | if (tcptw->tw_md5_key && tcp_alloc_md5sig_pool(sk) == NULL) |
368 | if (tcp_alloc_md5sig_pool(sk) == NULL) | ||
369 | BUG(); | 367 | BUG(); |
370 | } | 368 | } |
371 | } while (0); | 369 | } while (0); |
@@ -405,8 +403,10 @@ void tcp_twsk_destructor(struct sock *sk) | |||
405 | { | 403 | { |
406 | #ifdef CONFIG_TCP_MD5SIG | 404 | #ifdef CONFIG_TCP_MD5SIG |
407 | struct tcp_timewait_sock *twsk = tcp_twsk(sk); | 405 | struct tcp_timewait_sock *twsk = tcp_twsk(sk); |
408 | if (twsk->tw_md5_keylen) | 406 | if (twsk->tw_md5_key) { |
409 | tcp_free_md5sig_pool(); | 407 | tcp_free_md5sig_pool(); |
408 | kfree_rcu(twsk->tw_md5_key, rcu); | ||
409 | } | ||
410 | #endif | 410 | #endif |
411 | } | 411 | } |
412 | EXPORT_SYMBOL_GPL(tcp_twsk_destructor); | 412 | EXPORT_SYMBOL_GPL(tcp_twsk_destructor); |