[PATCH v3 net-next 05/15] ip6mr: Allocate skb earlier in ip6mr_rtm_getroute().

Kuniyuki Iwashima
2026-04-07T21:20:12Z

We will convert ip6mr_rtm_getroute() to RCU in the following patch,
where __ip6mr_get_table() will be called under RCU.

nlmsg_new() uses GFP_KERNEL and needs to be called before holding
rcu_read_lock().

As a prep, let's move nlmsg_new() before __ip6mr_get_table().

Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
net/ipv6/ip6mr.c | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 4d78041276c1..db7376cbcc01 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -2705,6 +2705,10 @@ static int ip6mr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
if (err < 0)
return err;

+ skb = nlmsg_new(mr6_msgsize(false), GFP_KERNEL);
+ if (!skb)
+ return -ENOBUFS;
+
if (tb[RTA_SRC])
src = nla_get_in6_addr(tb[RTA_SRC]);
if (tb[RTA_DST])
@@ -2714,7 +2718,8 @@ static int ip6mr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
mrt = __ip6mr_get_table(net, tableid ?: RT_TABLE_DEFAULT);
if (!mrt) {
NL_SET_ERR_MSG_MOD(extack, "MR table does not exist");
- return -ENOENT;
+ err = -ENOENT;
+ goto err;
}

/* entries are added/deleted only under RTNL */
@@ -2723,21 +2728,20 @@ static int ip6mr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
rcu_read_unlock();
if (!cache) {
NL_SET_ERR_MSG_MOD(extack, "MR cache entry not found");
- return -ENOENT;
+ err = -ENOENT;
+ goto err;
}

- skb = nlmsg_new(mr6_msgsize(false), GFP_KERNEL);
- if (!skb)
- return -ENOBUFS;
-
err = ip6mr_fill_mroute(mrt, skb, NETLINK_CB(in_skb).portid,
nlh->nlmsg_seq, cache, RTM_NEWROUTE, 0);
- if (err < 0) {
- kfree_skb(skb);
- return err;
- }
+ if (err < 0)
+ goto err;

return rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
+
+err:
+ kfree_skb(skb);
+ return err;
}

static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
--
2.53.0.1213.gd9a14994de-goog