Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'ipv6-follow-up-for-rtnl-free-rtm_newroute-series'

Kuniyuki Iwashima says:

====================
ipv6: Follow up for RTNL-free RTM_NEWROUTE series.

Patch 1 removes rcu_read_lock() in fib6_get_table().
Patch 2 removes rtnl_is_held arg for lwtunnel_valid_encap_type(), which
was short-term fix and is no longer used.
Patch 3 fixes RCU vs GFP_KERNEL report by syzkaller.
Patch 4~7 reverts GFP_ATOMIC uses to GFP_KERNEL.

v1: https://lore.kernel.org/20250514201943.74456-1-kuniyu@amazon.com
====================

Link: https://patch.msgid.link/20250516022759.44392-1-kuniyu@amazon.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+131 -220
+5 -8
include/net/lwtunnel.h
··· 116 116 int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op, 117 117 unsigned int num); 118 118 int lwtunnel_valid_encap_type(u16 encap_type, 119 - struct netlink_ext_ack *extack, 120 - bool rtnl_is_held); 119 + struct netlink_ext_ack *extack); 121 120 int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len, 122 - struct netlink_ext_ack *extack, 123 - bool rtnl_is_held); 121 + struct netlink_ext_ack *extack); 124 122 int lwtunnel_build_state(struct net *net, u16 encap_type, 125 123 struct nlattr *encap, 126 124 unsigned int family, const void *cfg, ··· 201 203 } 202 204 203 205 static inline int lwtunnel_valid_encap_type(u16 encap_type, 204 - struct netlink_ext_ack *extack, 205 - bool rtnl_is_held) 206 + struct netlink_ext_ack *extack) 206 207 { 207 208 NL_SET_ERR_MSG(extack, "CONFIG_LWTUNNEL is not enabled in this kernel"); 208 209 return -EOPNOTSUPP; 209 210 } 211 + 210 212 static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len, 211 - struct netlink_ext_ack *extack, 212 - bool rtnl_is_held) 213 + struct netlink_ext_ack *extack) 213 214 { 214 215 /* return 0 since we are not walking attr looking for 215 216 * RTA_ENCAP_TYPE attribute on nexthops.
+3 -12
net/core/lwtunnel.c
··· 149 149 } 150 150 EXPORT_SYMBOL_GPL(lwtunnel_build_state); 151 151 152 - int lwtunnel_valid_encap_type(u16 encap_type, struct netlink_ext_ack *extack, 153 - bool rtnl_is_held) 152 + int lwtunnel_valid_encap_type(u16 encap_type, struct netlink_ext_ack *extack) 154 153 { 155 154 const struct lwtunnel_encap_ops *ops; 156 155 int ret = -EINVAL; ··· 166 167 const char *encap_type_str = lwtunnel_encap_str(encap_type); 167 168 168 169 if (encap_type_str) { 169 - if (rtnl_is_held) 170 - __rtnl_unlock(); 171 170 request_module("rtnl-lwt-%s", encap_type_str); 172 - if (rtnl_is_held) 173 - rtnl_lock(); 174 - 175 171 ops = rcu_access_pointer(lwtun_encaps[encap_type]); 176 172 } 177 173 } ··· 180 186 EXPORT_SYMBOL_GPL(lwtunnel_valid_encap_type); 181 187 182 188 int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int remaining, 183 - struct netlink_ext_ack *extack, 184 - bool rtnl_is_held) 189 + struct netlink_ext_ack *extack) 185 190 { 186 191 struct rtnexthop *rtnh = (struct rtnexthop *)attr; 187 192 struct nlattr *nla_entype; ··· 201 208 } 202 209 encap_type = nla_get_u16(nla_entype); 203 210 204 - if (lwtunnel_valid_encap_type(encap_type, 205 - extack, 206 - rtnl_is_held) != 0) 211 + if (lwtunnel_valid_encap_type(encap_type, extack)) 207 212 return -EOPNOTSUPP; 208 213 } 209 214 }
+2 -2
net/ipv4/fib_frontend.c
··· 807 807 case RTA_MULTIPATH: 808 808 err = lwtunnel_valid_encap_type_attr(nla_data(attr), 809 809 nla_len(attr), 810 - extack, false); 810 + extack); 811 811 if (err < 0) 812 812 goto errout; 813 813 cfg->fc_mp = nla_data(attr); ··· 825 825 case RTA_ENCAP_TYPE: 826 826 cfg->fc_encap_type = nla_get_u16(attr); 827 827 err = lwtunnel_valid_encap_type(cfg->fc_encap_type, 828 - extack, false); 828 + extack); 829 829 if (err < 0) 830 830 goto errout; 831 831 break;
+4 -6
net/ipv4/fib_semantics.c
··· 617 617 { 618 618 int err; 619 619 620 - if (!nhc->nhc_pcpu_rth_output) { 621 - nhc->nhc_pcpu_rth_output = alloc_percpu_gfp(struct rtable __rcu *, 622 - gfp_flags); 623 - if (!nhc->nhc_pcpu_rth_output) 624 - return -ENOMEM; 625 - } 620 + nhc->nhc_pcpu_rth_output = alloc_percpu_gfp(struct rtable __rcu *, 621 + gfp_flags); 622 + if (!nhc->nhc_pcpu_rth_output) 623 + return -ENOMEM; 626 624 627 625 if (encap) { 628 626 struct lwtunnel_state *lwtstate;
+1 -2
net/ipv4/nexthop.c
··· 3180 3180 } 3181 3181 3182 3182 cfg->nh_encap_type = nla_get_u16(tb[NHA_ENCAP_TYPE]); 3183 - err = lwtunnel_valid_encap_type(cfg->nh_encap_type, 3184 - extack, false); 3183 + err = lwtunnel_valid_encap_type(cfg->nh_encap_type, extack); 3185 3184 if (err < 0) 3186 3185 goto out; 3187 3186
+17 -14
net/ipv6/ip6_fib.c
··· 281 281 282 282 struct fib6_table *fib6_get_table(struct net *net, u32 id) 283 283 { 284 - struct fib6_table *tb; 285 284 struct hlist_head *head; 286 - unsigned int h; 285 + struct fib6_table *tb; 287 286 288 - if (id == 0) 287 + if (!id) 289 288 id = RT6_TABLE_MAIN; 290 - h = id & (FIB6_TABLE_HASHSZ - 1); 291 - rcu_read_lock(); 292 - head = &net->ipv6.fib_table_hash[h]; 293 - hlist_for_each_entry_rcu(tb, head, tb6_hlist) { 294 - if (tb->tb6_id == id) { 295 - rcu_read_unlock(); 289 + 290 + head = &net->ipv6.fib_table_hash[id & (FIB6_TABLE_HASHSZ - 1)]; 291 + 292 + /* See comment in fib6_link_table(). RCU is not required, 293 + * but rcu_dereference_raw() is used to avoid data-race. 294 + */ 295 + hlist_for_each_entry_rcu(tb, head, tb6_hlist, true) 296 + if (tb->tb6_id == id) 296 297 return tb; 297 - } 298 - } 299 - rcu_read_unlock(); 300 298 301 299 return NULL; 302 300 } ··· 1027 1029 .table = table 1028 1030 }; 1029 1031 1030 - nexthop_for_each_fib6_nh(f6i->nh, fib6_nh_drop_pcpu_from, 1031 - &arg); 1032 + rcu_read_lock(); 1033 + nexthop_for_each_fib6_nh(f6i->nh, fib6_nh_drop_pcpu_from, &arg); 1034 + rcu_read_unlock(); 1032 1035 } else { 1033 1036 struct fib6_nh *fib6_nh; 1034 1037 ··· 1222 1223 fib6_nsiblings++; 1223 1224 } 1224 1225 BUG_ON(fib6_nsiblings != rt->fib6_nsiblings); 1226 + rcu_read_lock(); 1225 1227 rt6_multipath_rebalance(temp_sibling); 1228 + rcu_read_unlock(); 1226 1229 } 1227 1230 1228 1231 /* ··· 1267 1266 sibling->fib6_nsiblings--; 1268 1267 rt->fib6_nsiblings = 0; 1269 1268 list_del_rcu(&rt->fib6_siblings); 1269 + rcu_read_lock(); 1270 1270 rt6_multipath_rebalance(next_sibling); 1271 + rcu_read_unlock(); 1271 1272 return err; 1272 1273 } 1273 1274 }
+96 -173
net/ipv6/route.c
··· 1820 1820 1821 1821 void rt6_flush_exceptions(struct fib6_info *f6i) 1822 1822 { 1823 - if (f6i->nh) 1824 - nexthop_for_each_fib6_nh(f6i->nh, rt6_nh_flush_exceptions, 1825 - f6i); 1826 - else 1823 + if (f6i->nh) { 1824 + rcu_read_lock(); 1825 + nexthop_for_each_fib6_nh(f6i->nh, rt6_nh_flush_exceptions, f6i); 1826 + rcu_read_unlock(); 1827 + } else { 1827 1828 fib6_nh_flush_exceptions(f6i->fib6_nh, f6i); 1829 + } 1828 1830 } 1829 1831 1830 1832 /* Find cached rt in the hash table inside passed in rt ··· 3674 3672 goto out; 3675 3673 3676 3674 pcpu_alloc: 3675 + fib6_nh->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, gfp_flags); 3677 3676 if (!fib6_nh->rt6i_pcpu) { 3678 - fib6_nh->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, gfp_flags); 3679 - if (!fib6_nh->rt6i_pcpu) { 3680 - err = -ENOMEM; 3681 - goto out; 3682 - } 3677 + err = -ENOMEM; 3678 + goto out; 3683 3679 } 3684 3680 3685 3681 fib6_nh->fib_nh_dev = dev; ··· 3737 3737 } 3738 3738 } 3739 3739 3740 - static int fib6_nh_prealloc_percpu(struct fib6_nh *fib6_nh, gfp_t gfp_flags) 3741 - { 3742 - struct fib_nh_common *nhc = &fib6_nh->nh_common; 3743 - 3744 - fib6_nh->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, gfp_flags); 3745 - if (!fib6_nh->rt6i_pcpu) 3746 - return -ENOMEM; 3747 - 3748 - nhc->nhc_pcpu_rth_output = alloc_percpu_gfp(struct rtable __rcu *, 3749 - gfp_flags); 3750 - if (!nhc->nhc_pcpu_rth_output) { 3751 - free_percpu(fib6_nh->rt6i_pcpu); 3752 - return -ENOMEM; 3753 - } 3754 - 3755 - return 0; 3756 - } 3757 - 3758 3740 static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg, 3759 3741 gfp_t gfp_flags, 3760 3742 struct netlink_ext_ack *extack) ··· 3774 3792 goto free; 3775 3793 } 3776 3794 3777 - if (!cfg->fc_nh_id) { 3778 - err = fib6_nh_prealloc_percpu(&rt->fib6_nh[0], gfp_flags); 3779 - if (err) 3780 - goto free_metrics; 3781 - } 3782 - 3783 3795 if (cfg->fc_flags & RTF_ADDRCONF) 3784 3796 rt->dst_nocount = true; 3785 3797 ··· 3798 3822 rt->fib6_src.plen = cfg->fc_src_len; 3799 3823 #endif 3800 3824 return rt; 3801 - free_metrics: 3802 - ip_fib_metrics_put(rt->fib6_metrics); 3803 3825 free: 3804 3826 kfree(rt); 3805 3827 err: ··· 3806 3832 3807 3833 static int ip6_route_info_create_nh(struct fib6_info *rt, 3808 3834 struct fib6_config *cfg, 3835 + gfp_t gfp_flags, 3809 3836 struct netlink_ext_ack *extack) 3810 3837 { 3811 3838 struct net *net = cfg->fc_nlinfo.nl_net; ··· 3815 3840 3816 3841 if (cfg->fc_nh_id) { 3817 3842 struct nexthop *nh; 3843 + 3844 + rcu_read_lock(); 3818 3845 3819 3846 nh = nexthop_find_by_id(net, cfg->fc_nh_id); 3820 3847 if (!nh) { ··· 3837 3860 3838 3861 rt->nh = nh; 3839 3862 fib6_nh = nexthop_fib6_nh(rt->nh); 3863 + 3864 + rcu_read_unlock(); 3840 3865 } else { 3841 3866 int addr_type; 3842 3867 3843 - err = fib6_nh_init(net, rt->fib6_nh, cfg, GFP_ATOMIC, extack); 3868 + err = fib6_nh_init(net, rt->fib6_nh, cfg, gfp_flags, extack); 3844 3869 if (err) 3845 3870 goto out_release; 3846 3871 ··· 3874 3895 fib6_info_release(rt); 3875 3896 return err; 3876 3897 out_free: 3898 + rcu_read_unlock(); 3877 3899 ip_fib_metrics_put(rt->fib6_metrics); 3878 3900 kfree(rt); 3879 3901 return err; ··· 3890 3910 if (IS_ERR(rt)) 3891 3911 return PTR_ERR(rt); 3892 3912 3893 - rcu_read_lock(); 3894 - 3895 - err = ip6_route_info_create_nh(rt, cfg, extack); 3913 + err = ip6_route_info_create_nh(rt, cfg, gfp_flags, extack); 3896 3914 if (err) 3897 - goto unlock; 3915 + return err; 3898 3916 3899 3917 err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, extack); 3900 3918 fib6_info_release(rt); 3901 - unlock: 3902 - rcu_read_unlock(); 3903 3919 3904 3920 return err; 3905 3921 } ··· 4680 4704 if (IS_ERR(f6i)) 4681 4705 return f6i; 4682 4706 4683 - err = ip6_route_info_create_nh(f6i, &cfg, extack); 4707 + err = ip6_route_info_create_nh(f6i, &cfg, gfp_flags, extack); 4684 4708 if (err) 4685 4709 return ERR_PTR(err); 4686 4710 ··· 5148 5172 rtnh = rtnh_next(rtnh, &remaining); 5149 5173 } while (rtnh_ok(rtnh, remaining)); 5150 5174 5151 - return lwtunnel_valid_encap_type_attr(cfg->fc_mp, cfg->fc_mp_len, 5152 - extack, false); 5175 + return lwtunnel_valid_encap_type_attr(cfg->fc_mp, cfg->fc_mp_len, extack); 5153 5176 } 5154 5177 5155 5178 static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, ··· 5285 5310 if (tb[RTA_ENCAP_TYPE]) { 5286 5311 cfg->fc_encap_type = nla_get_u16(tb[RTA_ENCAP_TYPE]); 5287 5312 5288 - err = lwtunnel_valid_encap_type(cfg->fc_encap_type, 5289 - extack, false); 5313 + err = lwtunnel_valid_encap_type(cfg->fc_encap_type, extack); 5290 5314 if (err < 0) 5291 5315 goto errout; 5292 5316 } ··· 5308 5334 struct fib6_info *fib6_info; 5309 5335 struct fib6_config r_cfg; 5310 5336 struct list_head list; 5311 - int weight; 5312 5337 }; 5313 5338 5314 - static void ip6_route_mpath_info_cleanup(struct list_head *rt6_nh_list) 5339 + static int ip6_route_info_append(struct list_head *rt6_nh_list, 5340 + struct fib6_info *rt, 5341 + struct fib6_config *r_cfg) 5315 5342 { 5316 - struct rt6_nh *nh, *nh_next; 5343 + struct rt6_nh *nh; 5317 5344 5318 - list_for_each_entry_safe(nh, nh_next, rt6_nh_list, list) { 5319 - struct fib6_info *rt = nh->fib6_info; 5320 - 5321 - if (rt) { 5322 - free_percpu(rt->fib6_nh->nh_common.nhc_pcpu_rth_output); 5323 - free_percpu(rt->fib6_nh->rt6i_pcpu); 5324 - ip_fib_metrics_put(rt->fib6_metrics); 5325 - kfree(rt); 5326 - } 5327 - 5328 - list_del(&nh->list); 5329 - kfree(nh); 5345 + list_for_each_entry(nh, rt6_nh_list, list) { 5346 + /* check if fib6_info already exists */ 5347 + if (rt6_duplicate_nexthop(nh->fib6_info, rt)) 5348 + return -EEXIST; 5330 5349 } 5331 - } 5332 5350 5333 - static int ip6_route_mpath_info_create(struct list_head *rt6_nh_list, 5334 - struct fib6_config *cfg, 5335 - struct netlink_ext_ack *extack) 5336 - { 5337 - struct rtnexthop *rtnh; 5338 - int remaining; 5339 - int err; 5351 + nh = kzalloc(sizeof(*nh), GFP_KERNEL); 5352 + if (!nh) 5353 + return -ENOMEM; 5340 5354 5341 - remaining = cfg->fc_mp_len; 5342 - rtnh = (struct rtnexthop *)cfg->fc_mp; 5343 - 5344 - /* Parse a Multipath Entry and build a list (rt6_nh_list) of 5345 - * fib6_info structs per nexthop 5346 - */ 5347 - while (rtnh_ok(rtnh, remaining)) { 5348 - struct fib6_config r_cfg; 5349 - struct fib6_info *rt; 5350 - struct rt6_nh *nh; 5351 - int attrlen; 5352 - 5353 - nh = kzalloc(sizeof(*nh), GFP_KERNEL); 5354 - if (!nh) { 5355 - err = -ENOMEM; 5356 - goto err; 5357 - } 5358 - 5359 - list_add_tail(&nh->list, rt6_nh_list); 5360 - 5361 - memcpy(&r_cfg, cfg, sizeof(*cfg)); 5362 - if (rtnh->rtnh_ifindex) 5363 - r_cfg.fc_ifindex = rtnh->rtnh_ifindex; 5364 - 5365 - attrlen = rtnh_attrlen(rtnh); 5366 - if (attrlen > 0) { 5367 - struct nlattr *nla, *attrs = rtnh_attrs(rtnh); 5368 - 5369 - nla = nla_find(attrs, attrlen, RTA_GATEWAY); 5370 - if (nla) { 5371 - r_cfg.fc_gateway = nla_get_in6_addr(nla); 5372 - r_cfg.fc_flags |= RTF_GATEWAY; 5373 - } 5374 - 5375 - r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP); 5376 - nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE); 5377 - if (nla) 5378 - r_cfg.fc_encap_type = nla_get_u16(nla); 5379 - } 5380 - 5381 - r_cfg.fc_flags |= (rtnh->rtnh_flags & RTNH_F_ONLINK); 5382 - 5383 - rt = ip6_route_info_create(&r_cfg, GFP_KERNEL, extack); 5384 - if (IS_ERR(rt)) { 5385 - err = PTR_ERR(rt); 5386 - goto err; 5387 - } 5388 - 5389 - nh->fib6_info = rt; 5390 - nh->weight = rtnh->rtnh_hops + 1; 5391 - memcpy(&nh->r_cfg, &r_cfg, sizeof(r_cfg)); 5392 - 5393 - rtnh = rtnh_next(rtnh, &remaining); 5394 - } 5355 + nh->fib6_info = rt; 5356 + memcpy(&nh->r_cfg, r_cfg, sizeof(*r_cfg)); 5357 + list_add_tail(&nh->list, rt6_nh_list); 5395 5358 5396 5359 return 0; 5397 - err: 5398 - ip6_route_mpath_info_cleanup(rt6_nh_list); 5399 - return err; 5400 - } 5401 - 5402 - static int ip6_route_mpath_info_create_nh(struct list_head *rt6_nh_list, 5403 - struct netlink_ext_ack *extack) 5404 - { 5405 - struct rt6_nh *nh, *nh_next, *nh_tmp; 5406 - LIST_HEAD(tmp); 5407 - int err; 5408 - 5409 - list_for_each_entry_safe(nh, nh_next, rt6_nh_list, list) { 5410 - struct fib6_info *rt = nh->fib6_info; 5411 - 5412 - err = ip6_route_info_create_nh(rt, &nh->r_cfg, extack); 5413 - if (err) { 5414 - nh->fib6_info = NULL; 5415 - goto err; 5416 - } 5417 - 5418 - rt->fib6_nh->fib_nh_weight = nh->weight; 5419 - 5420 - list_move_tail(&nh->list, &tmp); 5421 - 5422 - list_for_each_entry(nh_tmp, rt6_nh_list, list) { 5423 - /* check if fib6_info already exists */ 5424 - if (rt6_duplicate_nexthop(nh_tmp->fib6_info, rt)) { 5425 - err = -EEXIST; 5426 - goto err; 5427 - } 5428 - } 5429 - } 5430 - out: 5431 - list_splice(&tmp, rt6_nh_list); 5432 - return err; 5433 - err: 5434 - ip6_route_mpath_info_cleanup(rt6_nh_list); 5435 - goto out; 5436 5360 } 5437 5361 5438 5362 static void ip6_route_mpath_notify(struct fib6_info *rt, ··· 5390 5518 struct fib6_info *rt_notif = NULL, *rt_last = NULL; 5391 5519 struct nl_info *info = &cfg->fc_nlinfo; 5392 5520 struct rt6_nh *nh, *nh_safe; 5521 + struct fib6_config r_cfg; 5522 + struct rtnexthop *rtnh; 5393 5523 LIST_HEAD(rt6_nh_list); 5394 5524 struct rt6_nh *err_nh; 5525 + struct fib6_info *rt; 5395 5526 __u16 nlflags; 5396 - int nhn = 0; 5527 + int remaining; 5528 + int attrlen; 5397 5529 int replace; 5530 + int nhn = 0; 5398 5531 int err; 5399 5532 5400 5533 replace = (cfg->fc_nlinfo.nlh && ··· 5409 5532 if (info->nlh && info->nlh->nlmsg_flags & NLM_F_APPEND) 5410 5533 nlflags |= NLM_F_APPEND; 5411 5534 5412 - err = ip6_route_mpath_info_create(&rt6_nh_list, cfg, extack); 5413 - if (err) 5414 - return err; 5535 + remaining = cfg->fc_mp_len; 5536 + rtnh = (struct rtnexthop *)cfg->fc_mp; 5415 5537 5416 - rcu_read_lock(); 5538 + /* Parse a Multipath Entry and build a list (rt6_nh_list) of 5539 + * fib6_info structs per nexthop 5540 + */ 5541 + while (rtnh_ok(rtnh, remaining)) { 5542 + memcpy(&r_cfg, cfg, sizeof(*cfg)); 5543 + if (rtnh->rtnh_ifindex) 5544 + r_cfg.fc_ifindex = rtnh->rtnh_ifindex; 5417 5545 5418 - err = ip6_route_mpath_info_create_nh(&rt6_nh_list, extack); 5419 - if (err) 5420 - goto cleanup; 5546 + attrlen = rtnh_attrlen(rtnh); 5547 + if (attrlen > 0) { 5548 + struct nlattr *nla, *attrs = rtnh_attrs(rtnh); 5549 + 5550 + nla = nla_find(attrs, attrlen, RTA_GATEWAY); 5551 + if (nla) { 5552 + r_cfg.fc_gateway = nla_get_in6_addr(nla); 5553 + r_cfg.fc_flags |= RTF_GATEWAY; 5554 + } 5555 + 5556 + r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP); 5557 + nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE); 5558 + if (nla) 5559 + r_cfg.fc_encap_type = nla_get_u16(nla); 5560 + } 5561 + 5562 + r_cfg.fc_flags |= (rtnh->rtnh_flags & RTNH_F_ONLINK); 5563 + rt = ip6_route_info_create(&r_cfg, GFP_KERNEL, extack); 5564 + if (IS_ERR(rt)) { 5565 + err = PTR_ERR(rt); 5566 + rt = NULL; 5567 + goto cleanup; 5568 + } 5569 + 5570 + err = ip6_route_info_create_nh(rt, &r_cfg, GFP_KERNEL, extack); 5571 + if (err) { 5572 + rt = NULL; 5573 + goto cleanup; 5574 + } 5575 + 5576 + rt->fib6_nh->fib_nh_weight = rtnh->rtnh_hops + 1; 5577 + 5578 + err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg); 5579 + if (err) { 5580 + fib6_info_release(rt); 5581 + goto cleanup; 5582 + } 5583 + 5584 + rtnh = rtnh_next(rtnh, &remaining); 5585 + } 5421 5586 5422 5587 /* for add and replace send one notification with all nexthops. 5423 5588 * Skip the notification in fib6_add_rt2node and send one with ··· 5548 5629 } 5549 5630 5550 5631 cleanup: 5551 - rcu_read_unlock(); 5552 - 5553 5632 list_for_each_entry_safe(nh, nh_safe, &rt6_nh_list, list) { 5554 5633 fib6_info_release(nh->fib6_info); 5555 5634 list_del(&nh->list); ··· 6329 6412 err = -ENOBUFS; 6330 6413 seq = info->nlh ? info->nlh->nlmsg_seq : 0; 6331 6414 6415 + rcu_read_lock(); 6416 + 6332 6417 skb = nlmsg_new(rt6_nlmsg_size(rt), GFP_ATOMIC); 6333 6418 if (!skb) 6334 6419 goto errout; ··· 6343 6424 kfree_skb(skb); 6344 6425 goto errout; 6345 6426 } 6427 + 6428 + rcu_read_unlock(); 6429 + 6346 6430 rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE, 6347 6431 info->nlh, GFP_ATOMIC); 6348 6432 return; 6349 6433 errout: 6434 + rcu_read_unlock(); 6350 6435 rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); 6351 6436 } 6352 6437
+3 -3
net/ipv6/seg6_local.c
··· 1671 1671 if (!seg6_validate_srh(srh, len, false)) 1672 1672 return -EINVAL; 1673 1673 1674 - slwt->srh = kmemdup(srh, len, GFP_ATOMIC); 1674 + slwt->srh = kmemdup(srh, len, GFP_KERNEL); 1675 1675 if (!slwt->srh) 1676 1676 return -ENOMEM; 1677 1677 ··· 1911 1911 if (!tb[SEG6_LOCAL_BPF_PROG] || !tb[SEG6_LOCAL_BPF_PROG_NAME]) 1912 1912 return -EINVAL; 1913 1913 1914 - slwt->bpf.name = nla_memdup(tb[SEG6_LOCAL_BPF_PROG_NAME], GFP_ATOMIC); 1914 + slwt->bpf.name = nla_memdup(tb[SEG6_LOCAL_BPF_PROG_NAME], GFP_KERNEL); 1915 1915 if (!slwt->bpf.name) 1916 1916 return -ENOMEM; 1917 1917 ··· 1994 1994 return -EINVAL; 1995 1995 1996 1996 /* counters are always zero initialized */ 1997 - pcounters = seg6_local_alloc_pcpu_counters(GFP_ATOMIC); 1997 + pcounters = seg6_local_alloc_pcpu_counters(GFP_KERNEL); 1998 1998 if (!pcounters) 1999 1999 return -ENOMEM; 2000 2000