From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-ej1-f42.google.com (mail-ej1-f42.google.com [209.85.218.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 83C8B1509AB for ; Tue, 21 Apr 2026 17:33:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.42 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776792819; cv=none; b=C/MlSgN6bplwYrY0ldbmqMYq5cF3pMc+PKCNhCxOWMFX26SyntIv3/tKrZW1cToE3vZolf2zSiWuf5lxSDbH7bd2yyHTcjrhDhAOe4xuRmN1kbZgQ8J9I3Q+MQxR6kcV7bkEOwCLKhX3Ixx3Raz8M7ZKtl/p9iHYomp8uoHr6Cw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776792819; c=relaxed/simple; bh=/scXEeQaRN4B/NeF1PUsl2czhaClwcX6Cf0nOChKG7Q=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=D1r6z6T4io3ZLzy9TiLssLFcvXZABENO0NB1MTuz53bSXM7Y/vwWvYB6AcdTlgFRJt8COJeF+RSiijLeWbvjbcpgBzNL4Ju3gStP0g4Vhiv97y7bodyKmn/Pb1BTUj0eo6QF3xkHpS6IozykiykVbYAGaXLEFjXhczYzm50MonM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=DbmcYJb8; arc=none smtp.client-ip=209.85.218.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DbmcYJb8" Received: by mail-ej1-f42.google.com with SMTP id a640c23a62f3a-ba3b9601b97so646856666b.2 for ; Tue, 21 Apr 2026 10:33:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792815; x=1777397615; darn=vger.kernel.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=DoCWrohdiik85XEdHlXUw0nj/jBXY1QzvkY+M7xyZZ4=; b=DbmcYJb8H7k+fsq8ScvYfPAIn69IO2kaxdhnOqw8CtGjvewOR3pEAVd14DYY4rYnPg 2fWbGVLFu0wPXftCrPMXII+KsvOLDNI3siMK7l3FRhozP8pc06+LHD0pBH9Z2CUrzsNe a0Ie/zDXKXZaJnJO4gwaiG2zFJ7+k3MK/bYwO9qR40UTk9Q+bCf0Gk0pfUSITjtLGZvv 5+/N3DDHupTOApEqOiq874Ke3CpQ7VCEw1SNEUUAQeqQOBwWpEp0JAqXd4Hgwix12CFN Zj/CZ1gqr5SsTacJxlCMq/4xhAWI4Fud0bYyqs4m1SKAxJLk1YH+Yie6v2oGZ1taU8t/ lNQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792815; x=1777397615; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=DoCWrohdiik85XEdHlXUw0nj/jBXY1QzvkY+M7xyZZ4=; b=CJAHZprC5u2d7ueoLmBpE9SKu9QM7fpIkcmiX0l0fmtwVZiFRFZIhmg9lx/cpMVesv Wi7m660uypTPgbK/kxkoJjr2wDHx/bdiqRQ2/dA+IX8Pkp/qZQSfggslqVtBIjERJXDs LtNyRVcBl8oA7ZComEzqr3ZLu08cJm7HM6ZRCNfv6ePma70FkyfM7fNlgfUrs5TCtknN NfrkOrXqmD/waQ3jOE6jOguAEThgNhdv1NlpS9Qm4hYN7BRP1RMpz8B83CwPhbDl22iW NYUF7+YgtzQwLCU2IMsdDy4bmRBfSpDoavoqmVpwrO3p+fc9SHu86L/V+fuhWc5pEnfX pTtg== X-Forwarded-Encrypted: i=1; AFNElJ9hrTJmx6bJmkkwAfR6ApcnFiEHrrVS8Xb6q/hToQ0dI9Ic8GcrSj0bLcvxZhoK/LxKvtYrBKBXEjBrUbA=@vger.kernel.org X-Gm-Message-State: AOJu0YybMm9jSF8gUhxllEnxMJMRIDKmMbNGZYZtw5IBV38sCTlnp0El o0IxOKOXiO1GNst586Nqgb2WbhEmk9ncNgfzP4FOA/OFKpTUQkC1QR22 X-Gm-Gg: AeBDieu3beFZojMWlnSggGIHaLGTO71OqERnGA+JwASeFAvkGd0AVUaVci1aL1z/Bm2 +0Xu6mJV/f+B06mN6+wsqcBmGKbuviAtWj9WQn2r9WBW/RKpEHrXBQ0NJnm015MVBRmgN3XPn9v VXa4KbLOTmE5WTmd0CFB5306twtBrQg3fFMJHd/fWpXG3PkxrMK+J+VYHo3nT4o38ipQsyJC7jk GMqlbPGr5N2vjAuwnMhRPX8EAShYVFtLJ82Pz1mfZi6iAx/iBED2IKTWd+hLu7EEx3FckmoapKA A1BPeFrIymVjJBAFg2XbAEwiJM4r2ZKZEe64DiEwtlww9sHq9poUm8LuHFc2IFpEHO6FijkQXt4 7zvSYdng5KfStWfgLTYCRSQAZOxXlc05hNf09Bt+N+v7gamJYOprHCzIFSOvha2pK4Ha5yFWydj 13uiwadKkFQ8B4i8Lk05Nw1PV8DabybPvVoV5VOTQ58ihZVYoLAQCSs3QS02sf4sR2t/of9uwyA 4QWLbeUyIUy1KLYLgoXK5m5xH4= X-Received: by 2002:a17:907:ea6:b0:b96:f6f1:e7af with SMTP id a640c23a62f3a-ba41916eb4dmr907537666b.9.1776792814542; Tue, 21 Apr 2026 10:33:34 -0700 (PDT) Received: from ?IPV6:2a02:a03f:a75e:9a00:7546:18b7:2c8c:e879? ([2a02:a03f:a75e:9a00:7546:18b7:2c8c:e879]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ba4519ee4adsm469401966b.19.2026.04.21.10.33.33 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 21 Apr 2026 10:33:34 -0700 (PDT) Message-ID: <8ce64ee4-dce1-4052-9558-61c97121cc37@gmail.com> Date: Tue, 21 Apr 2026 19:33:32 +0200 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH net] net: ipv6: fix NOREF dst use in seg6 and rpl lwtunnels To: Andrea Mayer , davem@davemloft.net, dsahern@kernel.org, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org Cc: bigeasy@linutronix.de, clrkwllms@kernel.org, rostedt@goodmis.org, david.lebrun@uclouvain.be, alex.aring@gmail.com, stefano.salsano@uniroma2.it, netdev@vger.kernel.org, linux-rt-devel@lists.linux.dev, linux-kernel@vger.kernel.org, stable@vger.kernel.org References: <20260421094735.20997-1-andrea.mayer@uniroma2.it> Content-Language: en-US From: Justin Iurman In-Reply-To: <20260421094735.20997-1-andrea.mayer@uniroma2.it> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit On 4/21/26 11:47, Andrea Mayer wrote: > seg6_input_core() and rpl_input() call ip6_route_input() which sets a > NOREF dst on the skb, then pass it to dst_cache_set_ip6() invoking > dst_hold() unconditionally. > On PREEMPT_RT, ksoftirqd is preemptible and a higher-priority task can > release the underlying pcpu_rt between the lookup and the caching > through a concurrent FIB lookup on a shared nexthop. > Simplified race sequence: > > ksoftirqd/X higher-prio task (same CPU X) > ----------- -------------------------------- > seg6_input_core(,skb)/rpl_input(skb) > dst_cache_get() > -> miss > ip6_route_input(skb) > -> ip6_pol_route(,skb,flags) > [RT6_LOOKUP_F_DST_NOREF in flags] > -> FIB lookup resolves fib6_nh > [nhid=N route] > -> rt6_make_pcpu_route() > [creates pcpu_rt, refcount=1] > pcpu_rt->sernum = fib6_sernum > [fib6_sernum=W] > -> cmpxchg(fib6_nh.rt6i_pcpu, > NULL, pcpu_rt) > [slot was empty, store succeeds] > -> skb_dst_set_noref(skb, dst) > [dst is pcpu_rt, refcount still 1] > > rt_genid_bump_ipv6() > -> bumps fib6_sernum > [fib6_sernum from W to Z] > ip6_route_output() > -> ip6_pol_route() > -> FIB lookup resolves fib6_nh > [nhid=N] > -> rt6_get_pcpu_route() > pcpu_rt->sernum != fib6_sernum > [W <> Z, stale] > -> prev = xchg(rt6i_pcpu, NULL) > -> dst_release(prev) > [prev is pcpu_rt, > refcount 1->0, dead] > > dst = skb_dst(skb) > [dst is the dead pcpu_rt] > dst_cache_set_ip6(dst) > -> dst_hold() on dead dst > -> WARN / use-after-free > > For the race to occur, ksoftirqd must be preemptible (PREEMPT_RT without > PREEMPT_RT_NEEDS_BH_LOCK) and a concurrent task must be able to release > the pcpu_rt. Shared nexthop objects provide such a path, as two routes > pointing to the same nhid share the same fib6_nh and its rt6i_pcpu > entry. > > Fix seg6_input_core() and rpl_input() by calling skb_dst_force() after > ip6_route_input() to force the NOREF dst into a refcounted one before > caching. > The output path is not affected as ip6_route_output() already returns a > refcounted dst. > > Fixes: af4a2209b134 ("ipv6: sr: use dst_cache in seg6_input") > Fixes: a7a29f9c361f ("net: ipv6: add rpl sr tunnel") > Cc: stable@vger.kernel.org > Signed-off-by: Andrea Mayer > --- > net/ipv6/rpl_iptunnel.c | 9 +++++++++ > net/ipv6/seg6_iptunnel.c | 9 +++++++++ > 2 files changed, 18 insertions(+) > > diff --git a/net/ipv6/rpl_iptunnel.c b/net/ipv6/rpl_iptunnel.c > index c7942cf65567..4e10adcd70e8 100644 > --- a/net/ipv6/rpl_iptunnel.c > +++ b/net/ipv6/rpl_iptunnel.c > @@ -287,7 +287,16 @@ static int rpl_input(struct sk_buff *skb) > > if (!dst) { > ip6_route_input(skb); > + > + /* ip6_route_input() sets a NOREF dst; force a refcount on it > + * before caching or further use. > + */ > + skb_dst_force(skb); > dst = skb_dst(skb); > + if (unlikely(!dst)) { > + err = -ENETUNREACH; > + goto drop; > + } > > /* cache only if we don't create a dst reference loop */ > if (!dst->error && lwtst != dst->lwtstate) { > diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c > index 97b50d9b1365..94284b483be0 100644 > --- a/net/ipv6/seg6_iptunnel.c > +++ b/net/ipv6/seg6_iptunnel.c > @@ -515,7 +515,16 @@ static int seg6_input_core(struct net *net, struct sock *sk, > > if (!dst) { > ip6_route_input(skb); > + > + /* ip6_route_input() sets a NOREF dst; force a refcount on it > + * before caching or further use. > + */ > + skb_dst_force(skb); > dst = skb_dst(skb); > + if (unlikely(!dst)) { > + err = -ENETUNREACH; > + goto drop; > + } > > /* cache only if we don't create a dst reference loop */ > if (!dst->error && lwtst != dst->lwtstate) { Thanks for taking care of this, Andrea! LGTM. Reviewed-by: Justin Iurman