FAILED: patch "[PATCH] net: phonet: free phonet_device after RCU grace period" failed to apply to 6.1-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x 71de0177b28da751f407581a4515cf4d762f6296
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026061545-rival-anything-e56f@gregkh' --subject-prefix 'PATCH 6.1.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 71de0177b28da751f407581a4515cf4d762f6296 Mon Sep 17 00:00:00 2001
From: Santosh Kalluri <[email protected]>
Date: Wed, 3 Jun 2026 17:08:43 -0700
Subject: [PATCH] net: phonet: free phonet_device after RCU grace period
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
phonet_device_destroy() removes a phonet_device from the per-net device list with list_del_rcu(), but frees it immediately. RCU readers walking the same list can still hold a pointer to the object after it has been removed, leading to a slab-use-after-free.
Use kfree_rcu(), matching the lifetime rule already used by phonet_address_del() for the same object type.
net/phonet/pn_dev.c +1 -1
@@ -108,7 +108,7 @@ static void phonet_device_destroy(struct net_device *dev)for_each_set_bit (addr, pnd->addrs,64 )phonet_address_notify (net,RTM_DELADDR , ifindex, addr); -kfree (pnd); +kfree_rcu (pnd, rcu); } }
Sasha Levin
maintainerPATCH 1/3 phonet: Pass ifindex to fill_addr().
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 08a9572be36819b5d9011604edfa5db6c5062a7a ]
We will convert addr_doit() and getaddr_dumpit() to RCU, both of which call fill_addr().
The former will call phonet_address_notify() outside of RCU due to GFP_KERNEL, so dev will not be available in fill_addr().
Let's pass ifindex directly to fill_addr().
Stable-dep-of: 71de0177b28d ("net: phonet: free phonet_device after RCU grace period")
--- net/phonet/pn_netlink.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
net/phonet/pn_netlink.c +7 -6
@@ -19,7 +19,7 @@/* Device address handling */ -static int fill_addr (struct sk_buff *skb,struct net_device *dev,u8 addr, +static int fill_addr (struct sk_buff *skb,u32 ifindex,u8 addr,u32 portid,u32 seq,int event);void phonet_address_notify (int event,struct net_device *dev,u8 addr)
@@ -31,7 +31,8 @@ void phonet_address_notify(int event, struct net_device *dev, u8 addr) nla_total_size(1), GFP_KERNEL);if (skb ==NULL ) goto errout; - err =fill_addr (skb, dev, addr,0 ,0 , event); + + err =fill_addr (skb, dev->ifindex, addr,0 ,0 , event);if (err <0 ) {WARN_ON (err == -EMSGSIZE );kfree_skb (skb);
@@ -92,8 +93,8 @@ static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh,return err; } -static int fill_addr (struct sk_buff *skb,struct net_device *dev,u8 addr, -u32 portid,u32 seq,int event) +static int fill_addr (struct sk_buff *skb,u32 ifindex,u8 addr, +u32 portid,u32 seq,int event) {struct ifaddrmsg *ifm;struct nlmsghdr *nlh;
@@ -107,7 +108,7 @@ static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr, ifm->ifa_prefixlen =0 ; ifm->ifa_flags =IFA_F_PERMANENT ; ifm->ifa_scope =RT_SCOPE_LINK ; - ifm->ifa_index = dev->ifindex; + ifm->ifa_index = ifindex;if (nla_put_u8 (skb,IFA_LOCAL , addr)) goto nla_put_failure;nlmsg_end (skb, nlh);
@@ -140,7 +141,7 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)if (addr_idx++ < addr_start_idx)continue ; -if (fill_addr (skb, pnd->netdev, addr <<2 , +if (fill_addr (skb, pnd->netdev->ifindex, addr <<2 ,NETLINK_CB (cb->skb).portid, cb->nlh->nlmsg_seq,RTM_NEWADDR ) <0 ) goto out;
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/3 phonet: Pass net and ifindex to phonet_address_notify().
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 68ed5c38b512b734caf3da1f87db4a99fcfe3002 ]
Currently, phonet_address_notify() fetches netns and ifindex from dev.
Once addr_doit() is converted to RCU, phonet_address_notify() will be called outside of RCU due to GFP_KERNEL, and dev will be unavailable there.
Let's pass net and ifindex to phonet_address_notify().
Stable-dep-of: 71de0177b28d ("net: phonet: free phonet_device after RCU grace period")
--- include/net/phonet/pn_dev.h | 2 +- net/phonet/pn_dev.c | 10 +++++++--- net/phonet/pn_netlink.c | 12 ++++++------ 3 files changed, 14 insertions(+), 10 deletions(-)
include/net/phonet/pn_dev.h +1 -1
@@ -38,7 +38,7 @@ int phonet_address_add(struct net_device *dev, u8 addr);int phonet_address_del (struct net_device *dev,u8 addr);u8 phonet_address_get (struct net_device *dev,u8 addr);int phonet_address_lookup (struct net *net,u8 addr); -void phonet_address_notify (int event,struct net_device *dev,u8 addr); +void phonet_address_notify (struct net *net,int event,u32 ifindex,u8 addr);int phonet_route_add (struct net_device *dev,u8 daddr);int phonet_route_del (struct net_device *dev,u8 daddr);
net/phonet/pn_dev.c +7 -3
@@ -98,10 +98,13 @@ static void phonet_device_destroy(struct net_device *dev)mutex_unlock (&pndevs->lock);if (pnd) { +struct net *net =dev_net (dev); +u32 ifindex = dev->ifindex;u8 addr;for_each_set_bit (addr, pnd->addrs,64 ) -phonet_address_notify (RTM_DELADDR , dev, addr); +phonet_address_notify (net,RTM_DELADDR , ifindex, addr); +kfree (pnd); } }
@@ -244,8 +247,9 @@ static int phonet_device_autoconf(struct net_device *dev) ret =phonet_address_add (dev, req.ifr_phonet_autoconf.device);if (ret)return ret; -phonet_address_notify (RTM_NEWADDR , dev, - req.ifr_phonet_autoconf.device); + +phonet_address_notify (dev_net (dev),RTM_NEWADDR , dev->ifindex, + req.ifr_phonet_autoconf.device);return 0 ; }
net/phonet/pn_netlink.c +6 -6
@@ -22,7 +22,7 @@static int fill_addr (struct sk_buff *skb,u32 ifindex,u8 addr,u32 portid,u32 seq,int event); -void phonet_address_notify (int event,struct net_device *dev,u8 addr) +void phonet_address_notify (struct net *net,int event,u32 ifindex,u8 addr) {struct sk_buff *skb;int err = -ENOBUFS ;
@@ -32,17 +32,17 @@ void phonet_address_notify(int event, struct net_device *dev, u8 addr)if (skb ==NULL ) goto errout; - err =fill_addr (skb, dev->ifindex, addr,0 ,0 , event); + err =fill_addr (skb, ifindex, addr,0 ,0 , event);if (err <0 ) {WARN_ON (err == -EMSGSIZE );kfree_skb (skb); goto errout; } -rtnl_notify (skb,dev_net (dev),0 , -RTNLGRP_PHONET_IFADDR ,NULL ,GFP_KERNEL ); + +rtnl_notify (skb, net,0 ,RTNLGRP_PHONET_IFADDR ,NULL ,GFP_KERNEL );return ; errout: -rtnl_set_sk_err (dev_net (dev),RTNLGRP_PHONET_IFADDR , err); +rtnl_set_sk_err (net,RTNLGRP_PHONET_IFADDR , err); }static const struct nla_policy ifa_phonet_policy[IFA_MAX +1 ] = {
@@ -89,7 +89,7 @@ static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh,else err =phonet_address_del (dev, pnaddr);if (!err) -phonet_address_notify (nlh->nlmsg_type, dev, pnaddr); +phonet_address_notify (net, nlh->nlmsg_type, ifm->ifa_index, pnaddr);return err; }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/3 net: phonet: free phonet_device after RCU grace period
In reply to Sasha LevinFrom: Santosh Kalluri <[email protected]>
[ Upstream commit 71de0177b28da751f407581a4515cf4d762f6296 ]
phonet_device_destroy() removes a phonet_device from the per-net device list with list_del_rcu(), but frees it immediately. RCU readers walking the same list can still hold a pointer to the object after it has been removed, leading to a slab-use-after-free.
Use kfree_rcu(), matching the lifetime rule already used by phonet_address_del() for the same object type.
--- net/phonet/pn_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/phonet/pn_dev.c +1 -1
@@ -105,7 +105,7 @@ static void phonet_device_destroy(struct net_device *dev)for_each_set_bit (addr, pnd->addrs,64 )phonet_address_notify (net,RTM_DELADDR , ifindex, addr); -kfree (pnd); +kfree_rcu (pnd, rcu); } }
Signature · 1 line
2.53.0