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 'rtnetlink-refactor-rtnl_-new-del-set-link-for-per-netns-rtnl'

Kuniyuki Iwashima says:

====================
rtnetlink: Refactor rtnl_{new,del,set}link() for per-netns RTNL.

This is a prep for the next series where we will push RTNL down to
rtnl_{new,del,set}link().

That means, for example, __rtnl_newlink() is always under RTNL, but
rtnl_newlink() has a non-RTNL section.

As a prerequisite for per-netns RTNL, we will move netns validation
(and RTNL-independent validations if possible) to that section.

rtnl_link_ops and rtnl_af_ops will be protected with SRCU not to
depend on RTNL.

Changes:
v2:
* Add Eric's Reviewed-by to patch 1-4,6,8-11, (no tag on 5,7,12-14)
* Patch 7
* Handle error of init_srcu_struct().
* Call cleanup_srcu_struct() after synchronize_srcu().
* Patch 12
* Move put_net() before errorout label
* Patch 13
* Newly added as prep for patch 14
* Patch 14
* Handle error of init_srcu_struct().
* Call cleanup_srcu_struct() after synchronize_srcu().

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

Link: https://patch.msgid.link/20241016185357.83849-1-kuniyu@amazon.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+355 -267
+9 -3
include/net/rtnetlink.h
··· 3 3 #define __NET_RTNETLINK_H 4 4 5 5 #include <linux/rtnetlink.h> 6 + #include <linux/srcu.h> 6 7 #include <net/netlink.h> 7 8 8 9 typedef int (*rtnl_doit_func)(struct sk_buff *, struct nlmsghdr *, ··· 70 69 /** 71 70 * struct rtnl_link_ops - rtnetlink link operations 72 71 * 73 - * @list: Used internally 72 + * @list: Used internally, protected by RTNL and SRCU 73 + * @srcu: Used internally 74 74 * @kind: Identifier 75 75 * @netns_refund: Physical device, move to init_net on netns exit 76 76 * @maxtype: Highest device specific netlink attribute number ··· 102 100 */ 103 101 struct rtnl_link_ops { 104 102 struct list_head list; 103 + struct srcu_struct srcu; 105 104 106 105 const char *kind; 107 106 ··· 172 169 /** 173 170 * struct rtnl_af_ops - rtnetlink address family operations 174 171 * 175 - * @list: Used internally 172 + * @list: Used internally, protected by RTNL and SRCU 173 + * @srcu: Used internally 176 174 * @family: Address family 177 175 * @fill_link_af: Function to fill IFLA_AF_SPEC with address family 178 176 * specific netlink attributes. ··· 186 182 */ 187 183 struct rtnl_af_ops { 188 184 struct list_head list; 185 + struct srcu_struct srcu; 186 + 189 187 int family; 190 188 191 189 int (*fill_link_af)(struct sk_buff *skb, ··· 207 201 size_t (*get_stats_af_size)(const struct net_device *dev); 208 202 }; 209 203 210 - void rtnl_af_register(struct rtnl_af_ops *ops); 204 + int rtnl_af_register(struct rtnl_af_ops *ops); 211 205 void rtnl_af_unregister(struct rtnl_af_ops *ops); 212 206 213 207 struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]);
+5 -1
net/bridge/br_netlink.c
··· 1924 1924 if (err) 1925 1925 goto out; 1926 1926 1927 - rtnl_af_register(&br_af_ops); 1927 + err = rtnl_af_register(&br_af_ops); 1928 + if (err) 1929 + goto out_vlan; 1928 1930 1929 1931 err = rtnl_link_register(&br_link_ops); 1930 1932 if (err) ··· 1936 1934 1937 1935 out_af: 1938 1936 rtnl_af_unregister(&br_af_ops); 1937 + out_vlan: 1938 + br_vlan_rtnl_uninit(); 1939 1939 out: 1940 1940 return err; 1941 1941 }
+320 -255
net/core/rtnetlink.c
··· 457 457 458 458 static LIST_HEAD(link_ops); 459 459 460 - static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) 460 + static struct rtnl_link_ops *rtnl_link_ops_get(const char *kind, int *srcu_index) 461 461 { 462 - const struct rtnl_link_ops *ops; 462 + struct rtnl_link_ops *ops; 463 463 464 - list_for_each_entry(ops, &link_ops, list) { 465 - if (!strcmp(ops->kind, kind)) 466 - return ops; 464 + rcu_read_lock(); 465 + 466 + list_for_each_entry_rcu(ops, &link_ops, list) { 467 + if (!strcmp(ops->kind, kind)) { 468 + *srcu_index = srcu_read_lock(&ops->srcu); 469 + goto unlock; 470 + } 467 471 } 468 - return NULL; 472 + 473 + ops = NULL; 474 + unlock: 475 + rcu_read_unlock(); 476 + 477 + return ops; 478 + } 479 + 480 + static void rtnl_link_ops_put(struct rtnl_link_ops *ops, int srcu_index) 481 + { 482 + srcu_read_unlock(&ops->srcu, srcu_index); 469 483 } 470 484 471 485 /** ··· 494 480 */ 495 481 int __rtnl_link_register(struct rtnl_link_ops *ops) 496 482 { 497 - if (rtnl_link_ops_get(ops->kind)) 498 - return -EEXIST; 483 + struct rtnl_link_ops *tmp; 484 + int err; 485 + 486 + /* When RTNL is removed, add lock for link_ops. */ 487 + ASSERT_RTNL(); 488 + 489 + list_for_each_entry(tmp, &link_ops, list) { 490 + if (!strcmp(ops->kind, tmp->kind)) 491 + return -EEXIST; 492 + } 499 493 500 494 /* The check for alloc/setup is here because if ops 501 495 * does not have that filled up, it is not possible ··· 513 491 if ((ops->alloc || ops->setup) && !ops->dellink) 514 492 ops->dellink = unregister_netdevice_queue; 515 493 516 - list_add_tail(&ops->list, &link_ops); 494 + err = init_srcu_struct(&ops->srcu); 495 + if (err) 496 + return err; 497 + 498 + list_add_tail_rcu(&ops->list, &link_ops); 499 + 517 500 return 0; 518 501 } 519 502 EXPORT_SYMBOL_GPL(__rtnl_link_register); ··· 569 542 { 570 543 struct net *net; 571 544 572 - for_each_net(net) { 545 + list_del_rcu(&ops->list); 546 + synchronize_srcu(&ops->srcu); 547 + cleanup_srcu_struct(&ops->srcu); 548 + 549 + for_each_net(net) 573 550 __rtnl_kill_links(net, ops); 574 - } 575 - list_del(&ops->list); 576 551 } 577 552 EXPORT_SYMBOL_GPL(__rtnl_link_unregister); 578 553 ··· 666 637 667 638 static LIST_HEAD(rtnl_af_ops); 668 639 669 - static const struct rtnl_af_ops *rtnl_af_lookup(const int family) 640 + static struct rtnl_af_ops *rtnl_af_lookup(const int family, int *srcu_index) 670 641 { 671 - const struct rtnl_af_ops *ops; 642 + struct rtnl_af_ops *ops; 672 643 673 644 ASSERT_RTNL(); 674 645 675 - list_for_each_entry(ops, &rtnl_af_ops, list) { 676 - if (ops->family == family) 677 - return ops; 646 + rcu_read_lock(); 647 + 648 + list_for_each_entry_rcu(ops, &rtnl_af_ops, list) { 649 + if (ops->family == family) { 650 + *srcu_index = srcu_read_lock(&ops->srcu); 651 + goto unlock; 652 + } 678 653 } 679 654 680 - return NULL; 655 + ops = NULL; 656 + unlock: 657 + rcu_read_unlock(); 658 + 659 + return ops; 660 + } 661 + 662 + static void rtnl_af_put(struct rtnl_af_ops *ops, int srcu_index) 663 + { 664 + srcu_read_unlock(&ops->srcu, srcu_index); 681 665 } 682 666 683 667 /** ··· 699 657 * 700 658 * Returns 0 on success or a negative error code. 701 659 */ 702 - void rtnl_af_register(struct rtnl_af_ops *ops) 660 + int rtnl_af_register(struct rtnl_af_ops *ops) 703 661 { 662 + int err = init_srcu_struct(&ops->srcu); 663 + 664 + if (err) 665 + return err; 666 + 704 667 rtnl_lock(); 705 668 list_add_tail_rcu(&ops->list, &rtnl_af_ops); 706 669 rtnl_unlock(); 670 + 671 + return 0; 707 672 } 708 673 EXPORT_SYMBOL_GPL(rtnl_af_register); 709 674 ··· 725 676 rtnl_unlock(); 726 677 727 678 synchronize_rcu(); 679 + synchronize_srcu(&ops->srcu); 680 + cleanup_srcu_struct(&ops->srcu); 728 681 } 729 682 EXPORT_SYMBOL_GPL(rtnl_af_unregister); 730 683 ··· 2209 2158 [IFLA_XDP_PROG_ID] = { .type = NLA_U32 }, 2210 2159 }; 2211 2160 2212 - static const struct rtnl_link_ops *linkinfo_to_kind_ops(const struct nlattr *nla) 2161 + static struct rtnl_link_ops *linkinfo_to_kind_ops(const struct nlattr *nla, 2162 + int *ops_srcu_index) 2213 2163 { 2214 - const struct rtnl_link_ops *ops = NULL; 2215 2164 struct nlattr *linfo[IFLA_INFO_MAX + 1]; 2165 + struct rtnl_link_ops *ops = NULL; 2216 2166 2217 2167 if (nla_parse_nested_deprecated(linfo, IFLA_INFO_MAX, nla, ifla_info_policy, NULL) < 0) 2218 2168 return NULL; ··· 2222 2170 char kind[MODULE_NAME_LEN]; 2223 2171 2224 2172 nla_strscpy(kind, linfo[IFLA_INFO_KIND], sizeof(kind)); 2225 - ops = rtnl_link_ops_get(kind); 2173 + ops = rtnl_link_ops_get(kind, ops_srcu_index); 2226 2174 } 2227 2175 2228 2176 return ops; ··· 2342 2290 2343 2291 static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) 2344 2292 { 2345 - const struct rtnl_link_ops *kind_ops = NULL; 2346 2293 struct netlink_ext_ack *extack = cb->extack; 2294 + struct rtnl_link_ops *kind_ops = NULL; 2347 2295 const struct nlmsghdr *nlh = cb->nlh; 2348 2296 struct net *net = sock_net(skb->sk); 2349 2297 unsigned int flags = NLM_F_MULTI; ··· 2354 2302 struct net *tgt_net = net; 2355 2303 u32 ext_filter_mask = 0; 2356 2304 struct net_device *dev; 2305 + int ops_srcu_index; 2357 2306 int master_idx = 0; 2358 2307 int netnsid = -1; 2359 2308 int err, i; ··· 2388 2335 master_idx = nla_get_u32(tb[i]); 2389 2336 break; 2390 2337 case IFLA_LINKINFO: 2391 - kind_ops = linkinfo_to_kind_ops(tb[i]); 2338 + kind_ops = linkinfo_to_kind_ops(tb[i], &ops_srcu_index); 2392 2339 break; 2393 2340 default: 2394 2341 if (cb->strict_check) { ··· 2414 2361 if (err < 0) 2415 2362 break; 2416 2363 } 2364 + 2365 + if (kind_ops) 2366 + rtnl_link_ops_put(kind_ops, ops_srcu_index); 2367 + 2417 2368 cb->seq = tgt_net->dev_base_seq; 2418 2369 nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 2419 2370 if (netnsid >= 0) ··· 2599 2542 int rem, err; 2600 2543 2601 2544 nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) { 2602 - const struct rtnl_af_ops *af_ops; 2545 + struct rtnl_af_ops *af_ops; 2546 + int af_ops_srcu_index; 2603 2547 2604 - af_ops = rtnl_af_lookup(nla_type(af)); 2548 + af_ops = rtnl_af_lookup(nla_type(af), &af_ops_srcu_index); 2605 2549 if (!af_ops) 2606 2550 return -EAFNOSUPPORT; 2607 2551 2608 2552 if (!af_ops->set_link_af) 2609 - return -EOPNOTSUPP; 2610 - 2611 - if (af_ops->validate_link_af) { 2553 + err = -EOPNOTSUPP; 2554 + else if (af_ops->validate_link_af) 2612 2555 err = af_ops->validate_link_af(dev, af, extack); 2613 - if (err < 0) 2614 - return err; 2615 - } 2556 + else 2557 + err = 0; 2558 + 2559 + rtnl_af_put(af_ops, af_ops_srcu_index); 2560 + 2561 + if (err < 0) 2562 + return err; 2616 2563 } 2617 2564 } 2618 2565 ··· 2907 2846 #define DO_SETLINK_MODIFIED 0x01 2908 2847 /* notify flag means notify + modified. */ 2909 2848 #define DO_SETLINK_NOTIFY 0x03 2910 - static int do_setlink(const struct sk_buff *skb, 2911 - struct net_device *dev, struct ifinfomsg *ifm, 2849 + static int do_setlink(const struct sk_buff *skb, struct net_device *dev, 2850 + struct net *tgt_net, struct ifinfomsg *ifm, 2912 2851 struct netlink_ext_ack *extack, 2913 2852 struct nlattr **tb, int status) 2914 2853 { ··· 2916 2855 char ifname[IFNAMSIZ]; 2917 2856 int err; 2918 2857 2858 + err = validate_linkmsg(dev, tb, extack); 2859 + if (err < 0) 2860 + goto errout; 2861 + 2919 2862 if (tb[IFLA_IFNAME]) 2920 2863 nla_strscpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); 2921 2864 else 2922 2865 ifname[0] = '\0'; 2923 2866 2924 - if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD] || tb[IFLA_TARGET_NETNSID]) { 2867 + if (!net_eq(tgt_net, dev_net(dev))) { 2925 2868 const char *pat = ifname[0] ? ifname : NULL; 2926 - struct net *net; 2927 2869 int new_ifindex; 2928 - 2929 - net = rtnl_link_get_net_capable(skb, dev_net(dev), 2930 - tb, CAP_NET_ADMIN); 2931 - if (IS_ERR(net)) { 2932 - err = PTR_ERR(net); 2933 - goto errout; 2934 - } 2935 2870 2936 2871 if (tb[IFLA_NEW_IFINDEX]) 2937 2872 new_ifindex = nla_get_s32(tb[IFLA_NEW_IFINDEX]); 2938 2873 else 2939 2874 new_ifindex = 0; 2940 2875 2941 - err = __dev_change_net_namespace(dev, net, pat, new_ifindex); 2942 - put_net(net); 2876 + err = __dev_change_net_namespace(dev, tgt_net, pat, new_ifindex); 2943 2877 if (err) 2944 2878 goto errout; 2879 + 2945 2880 status |= DO_SETLINK_MODIFIED; 2946 2881 } 2947 2882 ··· 3196 3139 int rem; 3197 3140 3198 3141 nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) { 3199 - const struct rtnl_af_ops *af_ops; 3142 + struct rtnl_af_ops *af_ops; 3143 + int af_ops_srcu_index; 3200 3144 3201 - BUG_ON(!(af_ops = rtnl_af_lookup(nla_type(af)))); 3145 + af_ops = rtnl_af_lookup(nla_type(af), &af_ops_srcu_index); 3146 + if (!af_ops) { 3147 + err = -EAFNOSUPPORT; 3148 + goto errout; 3149 + } 3202 3150 3203 3151 err = af_ops->set_link_af(dev, af, extack); 3152 + rtnl_af_put(af_ops, af_ops_srcu_index); 3153 + 3204 3154 if (err < 0) 3205 3155 goto errout; 3206 3156 ··· 3304 3240 static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, 3305 3241 struct netlink_ext_ack *extack) 3306 3242 { 3243 + struct ifinfomsg *ifm = nlmsg_data(nlh); 3307 3244 struct net *net = sock_net(skb->sk); 3308 - struct ifinfomsg *ifm; 3309 - struct net_device *dev; 3310 - int err; 3311 3245 struct nlattr *tb[IFLA_MAX+1]; 3246 + struct net_device *dev = NULL; 3247 + struct net *tgt_net; 3248 + int err; 3312 3249 3313 3250 err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFLA_MAX, 3314 3251 ifla_policy, extack); ··· 3320 3255 if (err < 0) 3321 3256 goto errout; 3322 3257 3323 - err = -EINVAL; 3324 - ifm = nlmsg_data(nlh); 3258 + tgt_net = rtnl_link_get_net_capable(skb, net, tb, CAP_NET_ADMIN); 3259 + if (IS_ERR(tgt_net)) { 3260 + err = PTR_ERR(tgt_net); 3261 + goto errout; 3262 + } 3263 + 3325 3264 if (ifm->ifi_index > 0) 3326 3265 dev = __dev_get_by_index(net, ifm->ifi_index); 3327 3266 else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) 3328 3267 dev = rtnl_dev_get(net, tb); 3329 3268 else 3330 - goto errout; 3269 + err = -EINVAL; 3331 3270 3332 - if (dev == NULL) { 3271 + if (dev) 3272 + err = do_setlink(skb, dev, tgt_net, ifm, extack, tb, 0); 3273 + else if (!err) 3333 3274 err = -ENODEV; 3334 - goto errout; 3335 - } 3336 3275 3337 - err = validate_linkmsg(dev, tb, extack); 3338 - if (err < 0) 3339 - goto errout; 3340 - 3341 - err = do_setlink(skb, dev, ifm, extack, tb, 0); 3276 + put_net(tgt_net); 3342 3277 errout: 3343 3278 return err; 3344 3279 } ··· 3398 3333 static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, 3399 3334 struct netlink_ext_ack *extack) 3400 3335 { 3336 + struct ifinfomsg *ifm = nlmsg_data(nlh); 3401 3337 struct net *net = sock_net(skb->sk); 3402 3338 u32 portid = NETLINK_CB(skb).portid; 3403 - struct net *tgt_net = net; 3404 - struct net_device *dev = NULL; 3405 - struct ifinfomsg *ifm; 3406 3339 struct nlattr *tb[IFLA_MAX+1]; 3407 - int err; 3340 + struct net_device *dev = NULL; 3341 + struct net *tgt_net = net; 3408 3342 int netnsid = -1; 3343 + int err; 3409 3344 3410 3345 err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFLA_MAX, 3411 3346 ifla_policy, extack); ··· 3423 3358 return PTR_ERR(tgt_net); 3424 3359 } 3425 3360 3426 - err = -EINVAL; 3427 - ifm = nlmsg_data(nlh); 3428 3361 if (ifm->ifi_index > 0) 3429 3362 dev = __dev_get_by_index(tgt_net, ifm->ifi_index); 3430 3363 else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) 3431 3364 dev = rtnl_dev_get(tgt_net, tb); 3365 + 3366 + if (dev) 3367 + err = rtnl_delete_link(dev, portid, nlh); 3368 + else if (ifm->ifi_index > 0 || tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) 3369 + err = -ENODEV; 3432 3370 else if (tb[IFLA_GROUP]) 3433 3371 err = rtnl_group_dellink(tgt_net, nla_get_u32(tb[IFLA_GROUP])); 3434 3372 else 3435 - goto out; 3373 + err = -EINVAL; 3436 3374 3437 - if (!dev) { 3438 - if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME] || ifm->ifi_index > 0) 3439 - err = -ENODEV; 3440 - 3441 - goto out; 3442 - } 3443 - 3444 - err = rtnl_delete_link(dev, portid, nlh); 3445 - 3446 - out: 3447 3375 if (netnsid >= 0) 3448 3376 put_net(tgt_net); 3449 3377 ··· 3563 3505 } 3564 3506 EXPORT_SYMBOL(rtnl_create_link); 3565 3507 3508 + struct rtnl_newlink_tbs { 3509 + struct nlattr *tb[IFLA_MAX + 1]; 3510 + struct nlattr *linkinfo[IFLA_INFO_MAX + 1]; 3511 + struct nlattr *attr[RTNL_MAX_TYPE + 1]; 3512 + struct nlattr *slave_attr[RTNL_SLAVE_MAX_TYPE + 1]; 3513 + }; 3514 + 3515 + static int rtnl_changelink(const struct sk_buff *skb, struct nlmsghdr *nlh, 3516 + const struct rtnl_link_ops *ops, 3517 + struct net_device *dev, struct net *tgt_net, 3518 + struct rtnl_newlink_tbs *tbs, 3519 + struct nlattr **data, 3520 + struct netlink_ext_ack *extack) 3521 + { 3522 + struct nlattr ** const linkinfo = tbs->linkinfo; 3523 + struct nlattr ** const tb = tbs->tb; 3524 + int status = 0; 3525 + int err; 3526 + 3527 + if (nlh->nlmsg_flags & NLM_F_EXCL) 3528 + return -EEXIST; 3529 + 3530 + if (nlh->nlmsg_flags & NLM_F_REPLACE) 3531 + return -EOPNOTSUPP; 3532 + 3533 + if (linkinfo[IFLA_INFO_DATA]) { 3534 + if (!ops || ops != dev->rtnl_link_ops || !ops->changelink) 3535 + return -EOPNOTSUPP; 3536 + 3537 + err = ops->changelink(dev, tb, data, extack); 3538 + if (err < 0) 3539 + return err; 3540 + 3541 + status |= DO_SETLINK_NOTIFY; 3542 + } 3543 + 3544 + if (linkinfo[IFLA_INFO_SLAVE_DATA]) { 3545 + const struct rtnl_link_ops *m_ops = NULL; 3546 + struct nlattr **slave_data = NULL; 3547 + struct net_device *master_dev; 3548 + 3549 + master_dev = netdev_master_upper_dev_get(dev); 3550 + if (master_dev) 3551 + m_ops = master_dev->rtnl_link_ops; 3552 + 3553 + if (!m_ops || !m_ops->slave_changelink) 3554 + return -EOPNOTSUPP; 3555 + 3556 + if (m_ops->slave_maxtype > RTNL_SLAVE_MAX_TYPE) 3557 + return -EINVAL; 3558 + 3559 + if (m_ops->slave_maxtype) { 3560 + err = nla_parse_nested_deprecated(tbs->slave_attr, 3561 + m_ops->slave_maxtype, 3562 + linkinfo[IFLA_INFO_SLAVE_DATA], 3563 + m_ops->slave_policy, extack); 3564 + if (err < 0) 3565 + return err; 3566 + 3567 + slave_data = tbs->slave_attr; 3568 + } 3569 + 3570 + err = m_ops->slave_changelink(master_dev, dev, tb, slave_data, extack); 3571 + if (err < 0) 3572 + return err; 3573 + 3574 + status |= DO_SETLINK_NOTIFY; 3575 + } 3576 + 3577 + return do_setlink(skb, dev, tgt_net, nlmsg_data(nlh), extack, tb, status); 3578 + } 3579 + 3566 3580 static int rtnl_group_changelink(const struct sk_buff *skb, 3567 - struct net *net, int group, 3568 - struct ifinfomsg *ifm, 3569 - struct netlink_ext_ack *extack, 3570 - struct nlattr **tb) 3581 + struct net *net, struct net *tgt_net, 3582 + int group, struct ifinfomsg *ifm, 3583 + struct netlink_ext_ack *extack, 3584 + struct nlattr **tb) 3571 3585 { 3572 3586 struct net_device *dev, *aux; 3573 3587 int err; 3574 3588 3575 3589 for_each_netdev_safe(net, dev, aux) { 3576 3590 if (dev->group == group) { 3577 - err = validate_linkmsg(dev, tb, extack); 3578 - if (err < 0) 3579 - return err; 3580 - err = do_setlink(skb, dev, ifm, extack, tb, 0); 3591 + err = do_setlink(skb, dev, tgt_net, ifm, extack, tb, 0); 3581 3592 if (err < 0) 3582 3593 return err; 3583 3594 } ··· 3657 3530 3658 3531 static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, 3659 3532 const struct rtnl_link_ops *ops, 3533 + struct net *tgt_net, struct net *link_net, 3660 3534 const struct nlmsghdr *nlh, 3661 3535 struct nlattr **tb, struct nlattr **data, 3662 3536 struct netlink_ext_ack *extack) ··· 3665 3537 unsigned char name_assign_type = NET_NAME_USER; 3666 3538 struct net *net = sock_net(skb->sk); 3667 3539 u32 portid = NETLINK_CB(skb).portid; 3668 - struct net *dest_net, *link_net; 3669 3540 struct net_device *dev; 3670 3541 char ifname[IFNAMSIZ]; 3671 3542 int err; ··· 3679 3552 name_assign_type = NET_NAME_ENUM; 3680 3553 } 3681 3554 3682 - dest_net = rtnl_link_get_net_capable(skb, net, tb, CAP_NET_ADMIN); 3683 - if (IS_ERR(dest_net)) 3684 - return PTR_ERR(dest_net); 3685 - 3686 - if (tb[IFLA_LINK_NETNSID]) { 3687 - int id = nla_get_s32(tb[IFLA_LINK_NETNSID]); 3688 - 3689 - link_net = get_net_ns_by_id(dest_net, id); 3690 - if (!link_net) { 3691 - NL_SET_ERR_MSG(extack, "Unknown network namespace id"); 3692 - err = -EINVAL; 3693 - goto out; 3694 - } 3695 - err = -EPERM; 3696 - if (!netlink_ns_capable(skb, link_net->user_ns, CAP_NET_ADMIN)) 3697 - goto out; 3698 - } else { 3699 - link_net = NULL; 3700 - } 3701 - 3702 - dev = rtnl_create_link(link_net ? : dest_net, ifname, 3555 + dev = rtnl_create_link(link_net ? : tgt_net, ifname, 3703 3556 name_assign_type, ops, tb, extack); 3704 3557 if (IS_ERR(dev)) { 3705 3558 err = PTR_ERR(dev); ··· 3701 3594 if (err < 0) 3702 3595 goto out_unregister; 3703 3596 if (link_net) { 3704 - err = dev_change_net_namespace(dev, dest_net, ifname); 3597 + err = dev_change_net_namespace(dev, tgt_net, ifname); 3705 3598 if (err < 0) 3706 3599 goto out_unregister; 3707 3600 } ··· 3711 3604 goto out_unregister; 3712 3605 } 3713 3606 out: 3714 - if (link_net) 3715 - put_net(link_net); 3716 - put_net(dest_net); 3717 3607 return err; 3718 3608 out_unregister: 3719 3609 if (ops->newlink) { ··· 3724 3620 goto out; 3725 3621 } 3726 3622 3727 - struct rtnl_newlink_tbs { 3728 - struct nlattr *tb[IFLA_MAX + 1]; 3729 - struct nlattr *attr[RTNL_MAX_TYPE + 1]; 3730 - struct nlattr *slave_attr[RTNL_SLAVE_MAX_TYPE + 1]; 3731 - }; 3732 - 3733 3623 static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, 3624 + const struct rtnl_link_ops *ops, 3625 + struct net *tgt_net, struct net *link_net, 3734 3626 struct rtnl_newlink_tbs *tbs, 3627 + struct nlattr **data, 3735 3628 struct netlink_ext_ack *extack) 3736 3629 { 3737 - struct nlattr *linkinfo[IFLA_INFO_MAX + 1]; 3738 3630 struct nlattr ** const tb = tbs->tb; 3739 - const struct rtnl_link_ops *m_ops; 3740 - struct net_device *master_dev; 3741 3631 struct net *net = sock_net(skb->sk); 3742 - const struct rtnl_link_ops *ops; 3743 - struct nlattr **slave_data; 3744 - char kind[MODULE_NAME_LEN]; 3745 3632 struct net_device *dev; 3746 3633 struct ifinfomsg *ifm; 3747 - struct nlattr **data; 3748 3634 bool link_specified; 3749 - int err; 3750 - 3751 - #ifdef CONFIG_MODULES 3752 - replay: 3753 - #endif 3754 - err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFLA_MAX, 3755 - ifla_policy, extack); 3756 - if (err < 0) 3757 - return err; 3758 - 3759 - err = rtnl_ensure_unique_netns(tb, extack, false); 3760 - if (err < 0) 3761 - return err; 3762 3635 3763 3636 ifm = nlmsg_data(nlh); 3764 3637 if (ifm->ifi_index > 0) { ··· 3752 3671 dev = NULL; 3753 3672 } 3754 3673 3755 - master_dev = NULL; 3756 - m_ops = NULL; 3757 - if (dev) { 3758 - master_dev = netdev_master_upper_dev_get(dev); 3759 - if (master_dev) 3760 - m_ops = master_dev->rtnl_link_ops; 3761 - } 3762 - 3763 - if (tb[IFLA_LINKINFO]) { 3764 - err = nla_parse_nested_deprecated(linkinfo, IFLA_INFO_MAX, 3765 - tb[IFLA_LINKINFO], 3766 - ifla_info_policy, NULL); 3767 - if (err < 0) 3768 - return err; 3769 - } else 3770 - memset(linkinfo, 0, sizeof(linkinfo)); 3771 - 3772 - if (linkinfo[IFLA_INFO_KIND]) { 3773 - nla_strscpy(kind, linkinfo[IFLA_INFO_KIND], sizeof(kind)); 3774 - ops = rtnl_link_ops_get(kind); 3775 - } else { 3776 - kind[0] = '\0'; 3777 - ops = NULL; 3778 - } 3779 - 3780 - data = NULL; 3781 - if (ops) { 3782 - if (ops->maxtype > RTNL_MAX_TYPE) 3783 - return -EINVAL; 3784 - 3785 - if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { 3786 - err = nla_parse_nested_deprecated(tbs->attr, ops->maxtype, 3787 - linkinfo[IFLA_INFO_DATA], 3788 - ops->policy, extack); 3789 - if (err < 0) 3790 - return err; 3791 - data = tbs->attr; 3792 - } 3793 - if (ops->validate) { 3794 - err = ops->validate(tb, data, extack); 3795 - if (err < 0) 3796 - return err; 3797 - } 3798 - } 3799 - 3800 - slave_data = NULL; 3801 - if (m_ops) { 3802 - if (m_ops->slave_maxtype > RTNL_SLAVE_MAX_TYPE) 3803 - return -EINVAL; 3804 - 3805 - if (m_ops->slave_maxtype && 3806 - linkinfo[IFLA_INFO_SLAVE_DATA]) { 3807 - err = nla_parse_nested_deprecated(tbs->slave_attr, 3808 - m_ops->slave_maxtype, 3809 - linkinfo[IFLA_INFO_SLAVE_DATA], 3810 - m_ops->slave_policy, 3811 - extack); 3812 - if (err < 0) 3813 - return err; 3814 - slave_data = tbs->slave_attr; 3815 - } 3816 - } 3817 - 3818 - if (dev) { 3819 - int status = 0; 3820 - 3821 - if (nlh->nlmsg_flags & NLM_F_EXCL) 3822 - return -EEXIST; 3823 - if (nlh->nlmsg_flags & NLM_F_REPLACE) 3824 - return -EOPNOTSUPP; 3825 - 3826 - err = validate_linkmsg(dev, tb, extack); 3827 - if (err < 0) 3828 - return err; 3829 - 3830 - if (linkinfo[IFLA_INFO_DATA]) { 3831 - if (!ops || ops != dev->rtnl_link_ops || 3832 - !ops->changelink) 3833 - return -EOPNOTSUPP; 3834 - 3835 - err = ops->changelink(dev, tb, data, extack); 3836 - if (err < 0) 3837 - return err; 3838 - status |= DO_SETLINK_NOTIFY; 3839 - } 3840 - 3841 - if (linkinfo[IFLA_INFO_SLAVE_DATA]) { 3842 - if (!m_ops || !m_ops->slave_changelink) 3843 - return -EOPNOTSUPP; 3844 - 3845 - err = m_ops->slave_changelink(master_dev, dev, tb, 3846 - slave_data, extack); 3847 - if (err < 0) 3848 - return err; 3849 - status |= DO_SETLINK_NOTIFY; 3850 - } 3851 - 3852 - return do_setlink(skb, dev, ifm, extack, tb, status); 3853 - } 3674 + if (dev) 3675 + return rtnl_changelink(skb, nlh, ops, dev, tgt_net, tbs, data, extack); 3854 3676 3855 3677 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { 3856 3678 /* No dev found and NLM_F_CREATE not set. Requested dev does not exist, 3857 3679 * or it's for a group 3858 3680 */ 3859 - if (link_specified) 3681 + if (link_specified || !tb[IFLA_GROUP]) 3860 3682 return -ENODEV; 3861 - if (tb[IFLA_GROUP]) 3862 - return rtnl_group_changelink(skb, net, 3863 - nla_get_u32(tb[IFLA_GROUP]), 3864 - ifm, extack, tb); 3865 - return -ENODEV; 3683 + 3684 + return rtnl_group_changelink(skb, net, tgt_net, 3685 + nla_get_u32(tb[IFLA_GROUP]), 3686 + ifm, extack, tb); 3866 3687 } 3867 3688 3868 3689 if (tb[IFLA_MAP] || tb[IFLA_PROTINFO]) 3869 3690 return -EOPNOTSUPP; 3870 3691 3871 3692 if (!ops) { 3872 - #ifdef CONFIG_MODULES 3873 - if (kind[0]) { 3874 - __rtnl_unlock(); 3875 - request_module("rtnl-link-%s", kind); 3876 - rtnl_lock(); 3877 - ops = rtnl_link_ops_get(kind); 3878 - if (ops) 3879 - goto replay; 3880 - } 3881 - #endif 3882 3693 NL_SET_ERR_MSG(extack, "Unknown device type"); 3883 3694 return -EOPNOTSUPP; 3884 3695 } 3885 3696 3886 - return rtnl_newlink_create(skb, ifm, ops, nlh, tb, data, extack); 3697 + return rtnl_newlink_create(skb, ifm, ops, tgt_net, link_net, nlh, tb, data, extack); 3887 3698 } 3888 3699 3889 3700 static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, 3890 3701 struct netlink_ext_ack *extack) 3891 3702 { 3703 + struct nlattr **tb, **linkinfo, **data = NULL; 3704 + struct net *tgt_net, *link_net = NULL; 3705 + struct rtnl_link_ops *ops = NULL; 3892 3706 struct rtnl_newlink_tbs *tbs; 3707 + int ops_srcu_index; 3893 3708 int ret; 3894 3709 3895 3710 tbs = kmalloc(sizeof(*tbs), GFP_KERNEL); 3896 3711 if (!tbs) 3897 3712 return -ENOMEM; 3898 3713 3899 - ret = __rtnl_newlink(skb, nlh, tbs, extack); 3714 + tb = tbs->tb; 3715 + ret = nlmsg_parse_deprecated(nlh, sizeof(struct ifinfomsg), tb, 3716 + IFLA_MAX, ifla_policy, extack); 3717 + if (ret < 0) 3718 + goto free; 3719 + 3720 + ret = rtnl_ensure_unique_netns(tb, extack, false); 3721 + if (ret < 0) 3722 + goto free; 3723 + 3724 + linkinfo = tbs->linkinfo; 3725 + if (tb[IFLA_LINKINFO]) { 3726 + ret = nla_parse_nested_deprecated(linkinfo, IFLA_INFO_MAX, 3727 + tb[IFLA_LINKINFO], 3728 + ifla_info_policy, NULL); 3729 + if (ret < 0) 3730 + goto free; 3731 + } else { 3732 + memset(linkinfo, 0, sizeof(tbs->linkinfo)); 3733 + } 3734 + 3735 + if (linkinfo[IFLA_INFO_KIND]) { 3736 + char kind[MODULE_NAME_LEN]; 3737 + 3738 + nla_strscpy(kind, linkinfo[IFLA_INFO_KIND], sizeof(kind)); 3739 + ops = rtnl_link_ops_get(kind, &ops_srcu_index); 3740 + #ifdef CONFIG_MODULES 3741 + if (!ops) { 3742 + __rtnl_unlock(); 3743 + request_module("rtnl-link-%s", kind); 3744 + rtnl_lock(); 3745 + ops = rtnl_link_ops_get(kind, &ops_srcu_index); 3746 + } 3747 + #endif 3748 + } 3749 + 3750 + if (ops) { 3751 + if (ops->maxtype > RTNL_MAX_TYPE) 3752 + return -EINVAL; 3753 + 3754 + if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { 3755 + ret = nla_parse_nested_deprecated(tbs->attr, ops->maxtype, 3756 + linkinfo[IFLA_INFO_DATA], 3757 + ops->policy, extack); 3758 + if (ret < 0) 3759 + goto put_ops; 3760 + 3761 + data = tbs->attr; 3762 + } 3763 + 3764 + if (ops->validate) { 3765 + ret = ops->validate(tb, data, extack); 3766 + if (ret < 0) 3767 + goto put_ops; 3768 + } 3769 + } 3770 + 3771 + tgt_net = rtnl_link_get_net_capable(skb, sock_net(skb->sk), tb, CAP_NET_ADMIN); 3772 + if (IS_ERR(tgt_net)) { 3773 + ret = PTR_ERR(tgt_net); 3774 + goto put_ops; 3775 + } 3776 + 3777 + if (tb[IFLA_LINK_NETNSID]) { 3778 + int id = nla_get_s32(tb[IFLA_LINK_NETNSID]); 3779 + 3780 + link_net = get_net_ns_by_id(tgt_net, id); 3781 + if (!link_net) { 3782 + NL_SET_ERR_MSG(extack, "Unknown network namespace id"); 3783 + ret = -EINVAL; 3784 + goto put_net; 3785 + } 3786 + 3787 + if (!netlink_ns_capable(skb, link_net->user_ns, CAP_NET_ADMIN)) { 3788 + ret = -EPERM; 3789 + goto put_net; 3790 + } 3791 + } 3792 + 3793 + ret = __rtnl_newlink(skb, nlh, ops, tgt_net, link_net, tbs, data, extack); 3794 + 3795 + put_net: 3796 + if (link_net) 3797 + put_net(link_net); 3798 + put_net(tgt_net); 3799 + put_ops: 3800 + if (ops) 3801 + rtnl_link_ops_put(ops, ops_srcu_index); 3802 + free: 3900 3803 kfree(tbs); 3901 3804 return ret; 3902 3805 }
+2 -1
net/ipv4/devinet.c
··· 2827 2827 register_pernet_subsys(&devinet_ops); 2828 2828 register_netdevice_notifier(&ip_netdev_notifier); 2829 2829 2830 - rtnl_af_register(&inet_af_ops); 2830 + if (rtnl_af_register(&inet_af_ops)) 2831 + panic("Unable to register inet_af_ops\n"); 2831 2832 2832 2833 rtnl_register_many(devinet_rtnl_msg_handlers); 2833 2834 }
+4 -1
net/ipv6/addrconf.c
··· 7468 7468 7469 7469 addrconf_verify(&init_net); 7470 7470 7471 - rtnl_af_register(&inet6_ops); 7471 + err = rtnl_af_register(&inet6_ops); 7472 + if (err) 7473 + goto erraf; 7472 7474 7473 7475 err = rtnl_register_many(addrconf_rtnl_msg_handlers); 7474 7476 if (err) ··· 7484 7482 errout: 7485 7483 rtnl_unregister_all(PF_INET6); 7486 7484 rtnl_af_unregister(&inet6_ops); 7485 + erraf: 7487 7486 unregister_netdevice_notifier(&ipv6_dev_notf); 7488 7487 errlo: 7489 7488 destroy_workqueue(addrconf_wq);
+11 -5
net/mctp/device.c
··· 535 535 int err; 536 536 537 537 register_netdevice_notifier(&mctp_dev_nb); 538 - rtnl_af_register(&mctp_af_ops); 538 + 539 + err = rtnl_af_register(&mctp_af_ops); 540 + if (err) 541 + goto err_notifier; 539 542 540 543 err = rtnl_register_many(mctp_device_rtnl_msg_handlers); 541 - if (err) { 542 - rtnl_af_unregister(&mctp_af_ops); 543 - unregister_netdevice_notifier(&mctp_dev_nb); 544 - } 544 + if (err) 545 + goto err_af; 545 546 547 + return 0; 548 + err_af: 549 + rtnl_af_unregister(&mctp_af_ops); 550 + err_notifier: 551 + unregister_netdevice_notifier(&mctp_dev_nb); 546 552 return err; 547 553 } 548 554
+4 -1
net/mpls/af_mpls.c
··· 2753 2753 2754 2754 dev_add_pack(&mpls_packet_type); 2755 2755 2756 - rtnl_af_register(&mpls_af_ops); 2756 + err = rtnl_af_register(&mpls_af_ops); 2757 + if (err) 2758 + goto out_unregister_dev_type; 2757 2759 2758 2760 err = rtnl_register_many(mpls_rtnl_msg_handlers); 2759 2761 if (err) ··· 2775 2773 rtnl_unregister_many(mpls_rtnl_msg_handlers); 2776 2774 out_unregister_rtnl_af: 2777 2775 rtnl_af_unregister(&mpls_af_ops); 2776 + out_unregister_dev_type: 2778 2777 dev_remove_pack(&mpls_packet_type); 2779 2778 out_unregister_pernet: 2780 2779 unregister_pernet_subsys(&mpls_net_ops);