Received: by 2002:a05:6a10:17d3:0:0:0:0 with SMTP id hz19csp2056493pxb; Mon, 12 Apr 2021 13:10:12 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwuzFKh6IyBvV2azfdVTv8NXKMOjtv+gTqXSx++eO9em7T6gCaRWkwaVZvmm8kuM2uCP7q1 X-Received: by 2002:a17:90a:4e0b:: with SMTP id n11mr966683pjh.108.1618258212180; Mon, 12 Apr 2021 13:10:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1618258212; cv=none; d=google.com; s=arc-20160816; b=Rxx/B3F3BVttINirnXcHntCVucma2P6d2lws7Xw7CKfVFikfXCI4JHSC2UIucmbUA7 aCFMHF0dM3sMIp+ndDwE6f1S46eNGwbQtrLd4UVnpw3GRfZeT3ZB2SbdIQ86IVwoVM0E O3mQk2EIIjcTT5k9vLEHazZFG5w76rjYw3u4LNUUWhTXmsG1fnsQoLHelCbUoCVAyBnA ZDLJUeE/Fk1HVyPjTYG4iDBqcLE37RpJyDcalBX8IjJtLsP8gqRr+J6MpI9MemQ/VaNM 0e6UoTVUZ7BytfXLqsacpUmzJDRC8OVbOmROyCpLpDjXvuynq2nvCf6JNEo/HtJyCgra mAvg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=s1B9du/JaIuchBDch23jx0OdMsx3CVd2rRSCcS0mgbI=; b=pEOa5gtx+WQOR7XXleKZLXwJp/MU6VMc7fOXm4oOUFPu/T+p3GBJsZCXYsnsHs8zg0 Jdj5QkcJEXiIeq/PsrUuEq+Y4n0qLA9I99fw3NLqsLDypQjjp+CGpOAAbvu/JLcOCr9W U0bDaQpy25l7kjdk8Dd+sNqHS9HwdtEByzgVaWRbyb57SPrBFdyC9gPM0ySOKq4izJks NKH2uY/MVpZJH8ANgGcMWQpUYYf4ouqNFYcQ+qMdU6eQxRbSxQB2ZyNz1Qm6Or4VUzzT kXB3yVAnKHUhzg7eN7lvZO45yEWeZQVgbFL6FGtK7ytUaroLPz8/i+FnZSI6wbj1No6e F5Lw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=hjpaHGaJ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id f9si16017639pln.165.2021.04.12.13.09.58; Mon, 12 Apr 2021 13:10:12 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=hjpaHGaJ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238156AbhDLIsu (ORCPT + 99 others); Mon, 12 Apr 2021 04:48:50 -0400 Received: from mail.kernel.org ([198.145.29.99]:39046 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237885AbhDLIqV (ORCPT ); Mon, 12 Apr 2021 04:46:21 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id EC5B561243; Mon, 12 Apr 2021 08:46:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1618217163; bh=FQJbzzytCx483H7KJVt/YJXUP21vVBFtQmovjuBIkC4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hjpaHGaJRunsQKzAxZANzgsZ8i58jY4/+cprjDF1/Rt1UOvA5TloonRyD4KkmdLJM PuY4OKhzthHpXe7yvnHqcMl40AXpHzejzDrsGZDPUNwQeMB0n7WwLfkJxDjSbNtjIx e2UbPYYYMk9KeimLvhbQbV87zufW3wDl1bk7O8hc= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Cong Wang , Lorenz Bauer , John Fastabend , Daniel Borkmann Subject: [PATCH 5.4 027/111] bpf, sockmap: Fix sk->prot unhash op reset Date: Mon, 12 Apr 2021 10:40:05 +0200 Message-Id: <20210412084005.138857863@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210412084004.200986670@linuxfoundation.org> References: <20210412084004.200986670@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: John Fastabend commit 1c84b33101c82683dee8b06761ca1f69e78c8ee7 upstream. In '4da6a196f93b1' we fixed a potential unhash loop caused when a TLS socket in a sockmap was removed from the sockmap. This happened because the unhash operation on the TLS ctx continued to point at the sockmap implementation of unhash even though the psock has already been removed. The sockmap unhash handler when a psock is removed does the following, void sock_map_unhash(struct sock *sk) { void (*saved_unhash)(struct sock *sk); struct sk_psock *psock; rcu_read_lock(); psock = sk_psock(sk); if (unlikely(!psock)) { rcu_read_unlock(); if (sk->sk_prot->unhash) sk->sk_prot->unhash(sk); return; } [...] } The unlikely() case is there to handle the case where psock is detached but the proto ops have not been updated yet. But, in the above case with TLS and removed psock we never fixed sk_prot->unhash() and unhash() points back to sock_map_unhash resulting in a loop. To fix this we added this bit of code, static inline void sk_psock_restore_proto(struct sock *sk, struct sk_psock *psock) { sk->sk_prot->unhash = psock->saved_unhash; This will set the sk_prot->unhash back to its saved value. This is the correct callback for a TLS socket that has been removed from the sock_map. Unfortunately, this also overwrites the unhash pointer for all psocks. We effectively break sockmap unhash handling for any future socks. Omitting the unhash operation will leave stale entries in the map if a socket transition through unhash, but does not do close() op. To fix set unhash correctly before calling into tls_update. This way the TLS enabled socket will point to the saved unhash() handler. Fixes: 4da6a196f93b1 ("bpf: Sockmap/tls, during free we may call tcp_bpf_unhash() in loop") Reported-by: Cong Wang Reported-by: Lorenz Bauer Suggested-by: Cong Wang Signed-off-by: John Fastabend Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/161731441904.68884.15593917809745631972.stgit@john-XPS-13-9370 Signed-off-by: Greg Kroah-Hartman --- include/linux/skmsg.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) --- a/include/linux/skmsg.h +++ b/include/linux/skmsg.h @@ -355,13 +355,17 @@ static inline void sk_psock_update_proto static inline void sk_psock_restore_proto(struct sock *sk, struct sk_psock *psock) { - sk->sk_prot->unhash = psock->saved_unhash; - if (psock->sk_proto) { struct inet_connection_sock *icsk = inet_csk(sk); bool has_ulp = !!icsk->icsk_ulp_data; if (has_ulp) { + /* TLS does not have an unhash proto in SW cases, but we need + * to ensure we stop using the sock_map unhash routine because + * the associated psock is being removed. So use the original + * unhash handler. + */ + WRITE_ONCE(sk->sk_prot->unhash, psock->saved_unhash); tcp_update_ulp(sk, psock->sk_proto, psock->saved_write_space); } else {