From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 660243630A0 for ; Sun, 12 Apr 2026 22:00:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776031209; cv=none; b=JyMhPXJ4jINoCgUDCyvqdycU74626yAFS9sM3+LwHZevkXRHP+8GiznfB96T+NL+4SA9zDv0MfuPx1l20BKsuo+g/vhNkhGMxJeGfhQSX19zRs3YFuAT4EkBPAl1AsXpUG4B2OpifEf5vPFsSkDdW2+zP3hm9sj3KEMhu8M/86A= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776031209; c=relaxed/simple; bh=GONf6d+BqlNcxoEtP1tY1Yjo7UEVjVvmuorsF4TM02M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BQX5OwQYgna3/aSASCYHC7fhD8HptvSBCfELrB8tR4Hg6xOzUFse7N+2HQdCSIAf40avlvUufeapAens8LID2twPHKMslgDtM7Kz7v7SZLOyRhIIfxakTwR/eoFVR++dcKHLnutaABOs3Eh/EfvE+xECZR9cP1zetYK7r5et+7U= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uWwyDlSn; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uWwyDlSn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4D74CC2BCB0; Sun, 12 Apr 2026 22:00:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1776031209; bh=GONf6d+BqlNcxoEtP1tY1Yjo7UEVjVvmuorsF4TM02M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uWwyDlSnfFmfTw2Ebevn49FxuZ765FA4TI2HvKQnwZsPKuGjGvWb7smNs4QQAjYeF mUtNVs2/0r+/ySdRLae8274EGL7b7GIEbc75VmaoiDnUk7vpoaJRrg8eC9MpHgWmts hTtX8ngizrlEygnwSxXdNwxaHj+TVqtn2wTQAd9sOzEcdDqxAOxxNt2Sqk1ar4DQYI TWG/pF2Z693GZnJvP7mD2gbeNYwaJ6yWhkKZEGx+pKg+jJl+XjEV9gk9kNE+QZTEVV gN89+Vd8LQJD4VQoyZ/lgO5wpc8MpZNQ8r592di2AmBdpHyeusyJUI5D3vji5Gr4K9 Nzp8OHBkp/DpQ== From: Sasha Levin To: stable@vger.kernel.org Cc: Andrea Mayer , Nicolas Dichtel , Justin Iurman , Jakub Kicinski , Sasha Levin Subject: [PATCH 5.15.y] seg6: separate dst_cache for input and output paths in seg6 lwtunnel Date: Sun, 12 Apr 2026 18:00:05 -0400 Message-ID: <20260412220005.2440027-1-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <2026041204-pedicure-icky-445b@gregkh> References: <2026041204-pedicure-icky-445b@gregkh> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Andrea Mayer [ Upstream commit c3812651b522fe8437ebb7063b75ddb95b571643 ] The seg6 lwtunnel uses a single dst_cache per encap route, shared between seg6_input_core() and seg6_output_core(). These two paths can perform the post-encap SID lookup in different routing contexts (e.g., ip rules matching on the ingress interface, or VRF table separation). Whichever path runs first populates the cache, and the other reuses it blindly, bypassing its own lookup. Fix this by splitting the cache into cache_input and cache_output, so each path maintains its own cached dst independently. Fixes: 6c8702c60b88 ("ipv6: sr: add support for SRH encapsulation and injection with lwtunnels") Cc: stable@vger.kernel.org Signed-off-by: Andrea Mayer Reviewed-by: Nicolas Dichtel Reviewed-by: Justin Iurman Link: https://patch.msgid.link/20260404004405.4057-2-andrea.mayer@uniroma2.it Signed-off-by: Jakub Kicinski [ added missing dst reference loop guard in seg6_output_core() ] Signed-off-by: Sasha Levin --- net/ipv6/seg6_iptunnel.c | 41 +++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c index 4188c16754839..62dde5c506b10 100644 --- a/net/ipv6/seg6_iptunnel.c +++ b/net/ipv6/seg6_iptunnel.c @@ -48,7 +48,8 @@ static size_t seg6_lwt_headroom(struct seg6_iptunnel_encap *tuninfo) } struct seg6_lwt { - struct dst_cache cache; + struct dst_cache cache_input; + struct dst_cache cache_output; struct seg6_iptunnel_encap tuninfo[]; }; @@ -486,7 +487,7 @@ static int seg6_input_core(struct net *net, struct sock *sk, slwt = seg6_lwt_lwtunnel(lwtst); local_bh_disable(); - dst = dst_cache_get(&slwt->cache); + dst = dst_cache_get(&slwt->cache_input); local_bh_enable(); err = seg6_do_srh(skb, dst); @@ -504,7 +505,7 @@ static int seg6_input_core(struct net *net, struct sock *sk, /* cache only if we don't create a dst reference loop */ if (!dst->error && lwtst != dst->lwtstate) { local_bh_disable(); - dst_cache_set_ip6(&slwt->cache, dst, + dst_cache_set_ip6(&slwt->cache_input, dst, &ipv6_hdr(skb)->saddr); local_bh_enable(); } @@ -563,7 +564,7 @@ static int seg6_output_core(struct net *net, struct sock *sk, slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate); local_bh_disable(); - dst = dst_cache_get(&slwt->cache); + dst = dst_cache_get(&slwt->cache_output); local_bh_enable(); err = seg6_do_srh(skb, dst); @@ -587,9 +588,12 @@ static int seg6_output_core(struct net *net, struct sock *sk, goto drop; } - local_bh_disable(); - dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr); - local_bh_enable(); + /* cache only if we don't create a dst reference loop */ + if (orig_dst->lwtstate != dst->lwtstate) { + local_bh_disable(); + dst_cache_set_ip6(&slwt->cache_output, dst, &fl6.saddr); + local_bh_enable(); + } err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); if (unlikely(err)) @@ -697,11 +701,13 @@ static int seg6_build_state(struct net *net, struct nlattr *nla, slwt = seg6_lwt_lwtunnel(newts); - err = dst_cache_init(&slwt->cache, GFP_ATOMIC); - if (err) { - kfree(newts); - return err; - } + err = dst_cache_init(&slwt->cache_input, GFP_ATOMIC); + if (err) + goto err_free_newts; + + err = dst_cache_init(&slwt->cache_output, GFP_ATOMIC); + if (err) + goto err_destroy_input; memcpy(&slwt->tuninfo, tuninfo, tuninfo_len); @@ -716,11 +722,20 @@ static int seg6_build_state(struct net *net, struct nlattr *nla, *ts = newts; return 0; + +err_destroy_input: + dst_cache_destroy(&slwt->cache_input); +err_free_newts: + kfree(newts); + return err; } static void seg6_destroy_state(struct lwtunnel_state *lwt) { - dst_cache_destroy(&seg6_lwt_lwtunnel(lwt)->cache); + struct seg6_lwt *slwt = seg6_lwt_lwtunnel(lwt); + + dst_cache_destroy(&slwt->cache_input); + dst_cache_destroy(&slwt->cache_output); } static int seg6_fill_encap_info(struct sk_buff *skb, -- 2.53.0