summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKuniyuki Iwashima <kuniyu@google.com>2026-06-05 01:46:22 +0300
committerJakub Kicinski <kuba@kernel.org>2026-06-09 03:06:23 +0300
commitc2f5fd21aca4c7d002bbf264da4464509674ee78 (patch)
tree341a15c24442773c8ee9cc6f2f6cf4638ba1b8a3
parent36be7d7c5ded0d70c3384e4730664e25b8d076fc (diff)
downloadlinux-c2f5fd21aca4c7d002bbf264da4464509674ee78.tar.xz
ip6mr: Allocate skb earlier in ip6mr_rtm_getroute().
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> Link: https://patch.msgid.link/20260604224712.3209821-5-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--net/ipv6/ip6mr.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index ed56c4c8fda0..018985593b03 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -2700,6 +2700,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])
@@ -2709,7 +2713,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 */
@@ -2718,21 +2723,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)