diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 27140e5cdc06..de5f0306b594 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1168,6 +1168,14 @@ struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk, } EXPORT_SYMBOL(tcp_v4_md5_lookup); +static void tcp_md5sig_info_free(struct rcu_head *head) +{ + struct tcp_md5sig_info *md5sig = + container_of(head, struct tcp_md5sig_info, rcu); + + kfree_sensitive(md5sig); +} + static int tcp_md5sig_info_add(struct sock *sk, gfp_t gfp) { struct tcp_sock *tp = tcp_sk(sk); @@ -1183,6 +1191,14 @@ static int tcp_md5sig_info_add(struct sock *sk, gfp_t gfp) return 0; } +static void tcp_md5sig_key_free(struct rcu_head *head) +{ + struct tcp_md5sig_key *key = + container_of(head, struct tcp_md5sig_key, rcu); + + kfree_sensitive(key); +} + /* This can be called on a newly created socket, from other files */ static int __tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, int family, u8 prefixlen, int l3index, u8 flags, @@ -1299,7 +1315,7 @@ int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family, return -ENOENT; hlist_del_rcu(&key->node); atomic_sub(sizeof(*key), &sk->sk_omem_alloc); - kfree_rcu(key, rcu); + call_rcu(&key->rcu, tcp_md5sig_key_free); return 0; } EXPORT_SYMBOL(tcp_md5_do_del); @@ -1316,7 +1332,7 @@ static void tcp_clear_md5_list(struct sock *sk) hlist_for_each_entry_safe(key, n, &md5sig->head, node) { hlist_del_rcu(&key->node); atomic_sub(sizeof(*key), &sk->sk_omem_alloc); - kfree_rcu(key, rcu); + call_rcu(&key->rcu, tcp_md5sig_key_free); } } @@ -2318,7 +2334,7 @@ void tcp_v4_destroy_sock(struct sock *sk) /* Clean up the MD5 key list, if any */ if (tp->md5sig_info) { tcp_clear_md5_list(sk); - kfree_rcu(rcu_dereference_protected(tp->md5sig_info, 1), rcu); + call_rcu(&tp->md5sig_info->rcu, tcp_md5sig_info_free); tp->md5sig_info = NULL; static_branch_slow_dec_deferred(&tcp_md5_needed); }