Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 260fcbeb authored by Yan, Zheng's avatar Yan, Zheng Committed by David S. Miller
Browse files

tcp: properly handle md5sig_pool references



tcp_v4_clear_md5_list() assumes that multiple tcp md5sig peers
only hold one reference to md5sig_pool. but tcp_v4_md5_do_add()
increases use count of md5sig_pool for each peer. This patch
makes tcp_v4_md5_do_add() only increases use count for the first
tcp md5sig peer.

Signed-off-by: default avatarZheng Yan <zheng.z.yan@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cb2d0f3e
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -927,17 +927,20 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
			}
			sk_nocaps_add(sk, NETIF_F_GSO_MASK);
		}
		if (tcp_alloc_md5sig_pool(sk) == NULL) {

		md5sig = tp->md5sig_info;
		if (md5sig->entries4 == 0 &&
		    tcp_alloc_md5sig_pool(sk) == NULL) {
			kfree(newkey);
			return -ENOMEM;
		}
		md5sig = tp->md5sig_info;

		if (md5sig->alloced4 == md5sig->entries4) {
			keys = kmalloc((sizeof(*keys) *
					(md5sig->entries4 + 1)), GFP_ATOMIC);
			if (!keys) {
				kfree(newkey);
				if (md5sig->entries4 == 0)
					tcp_free_md5sig_pool();
				return -ENOMEM;
			}
@@ -982,6 +985,7 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr)
				kfree(tp->md5sig_info->keys4);
				tp->md5sig_info->keys4 = NULL;
				tp->md5sig_info->alloced4 = 0;
				tcp_free_md5sig_pool();
			} else if (tp->md5sig_info->entries4 != i) {
				/* Need to do some manipulation */
				memmove(&tp->md5sig_info->keys4[i],
@@ -989,7 +993,6 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr)
					(tp->md5sig_info->entries4 - i) *
					 sizeof(struct tcp4_md5sig_key));
			}
			tcp_free_md5sig_pool();
			return 0;
		}
	}
+5 −3
Original line number Diff line number Diff line
@@ -591,7 +591,8 @@ static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer,
			}
			sk_nocaps_add(sk, NETIF_F_GSO_MASK);
		}
		if (tcp_alloc_md5sig_pool(sk) == NULL) {
		if (tp->md5sig_info->entries6 == 0 &&
			tcp_alloc_md5sig_pool(sk) == NULL) {
			kfree(newkey);
			return -ENOMEM;
		}
@@ -600,8 +601,9 @@ static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer,
				       (tp->md5sig_info->entries6 + 1)), GFP_ATOMIC);

			if (!keys) {
				tcp_free_md5sig_pool();
				kfree(newkey);
				if (tp->md5sig_info->entries6 == 0)
					tcp_free_md5sig_pool();
				return -ENOMEM;
			}

@@ -647,6 +649,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, const struct in6_addr *peer)
				kfree(tp->md5sig_info->keys6);
				tp->md5sig_info->keys6 = NULL;
				tp->md5sig_info->alloced6 = 0;
				tcp_free_md5sig_pool();
			} else {
				/* shrink the database */
				if (tp->md5sig_info->entries6 != i)
@@ -655,7 +658,6 @@ static int tcp_v6_md5_do_del(struct sock *sk, const struct in6_addr *peer)
						(tp->md5sig_info->entries6 - i)
						* sizeof (tp->md5sig_info->keys6[0]));
			}
			tcp_free_md5sig_pool();
			return 0;
		}
	}