* [PATCH net-next 0/4] Ease to interpret net-nsid @ 2018-11-21 11:01 Nicolas Dichtel 2018-11-21 11:01 ` [PATCH net-next 1/4] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel ` (4 more replies) 0 siblings, 5 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-21 11:01 UTC (permalink / raw) To: davem; +Cc: netdev The goal of this series is to ease the interpretation of nsid received in netlink messages from other netns (when the user uses NETLINK_F_LISTEN_ALL_NSID). After this series, with a patched iproute2: $ ip netns add foo $ ip netns add bar $ touch /var/run/netns/init_net $ mount --bind /proc/1/ns/net /var/run/netns/init_net $ ip netns set init_net 11 $ ip netns set foo 12 $ ip netns set bar 13 $ ip netns init_net (id: 11) bar (id: 13) foo (id: 12) $ ip -n foo netns set init_net 21 $ ip -n foo netns set foo 22 $ ip -n foo netns set bar 23 $ ip -n foo netns init_net (id: 21) bar (id: 23) foo (id: 22) $ ip -n bar netns set init_net 31 $ ip -n bar netns set foo 32 $ ip -n bar netns set bar 33 $ ip -n bar netns init_net (id: 31) bar (id: 33) foo (id: 32) $ ip netns list-id target-nsid 12 nsid 21 current-nsid 11 (iproute2 netns name: init_net) nsid 22 current-nsid 12 (iproute2 netns name: foo) nsid 23 current-nsid 13 (iproute2 netns name: bar) $ ip -n bar netns list-id target-nsid 32 nsid 31 nsid 21 current-nsid 31 (iproute2 netns name: init_net) include/uapi/linux/net_namespace.h | 2 + net/core/net_namespace.c | 132 ++++++++++++++++++++++++++++++------- 2 files changed, 110 insertions(+), 24 deletions(-) Comments are welcomed, Regards, Nicolas ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next 1/4] netns: remove net arg from rtnl_net_fill() 2018-11-21 11:01 [PATCH net-next 0/4] Ease to interpret net-nsid Nicolas Dichtel @ 2018-11-21 11:01 ` Nicolas Dichtel 2018-11-21 11:01 ` [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel ` (3 subsequent siblings) 4 siblings, 0 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-21 11:01 UTC (permalink / raw) To: davem; +Cc: netdev, Nicolas Dichtel This argument is not used anymore. Fixes: cab3c8ec8d57 ("netns: always provide the id to rtnl_net_fill()") Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> --- net/core/net_namespace.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index fefe72774aeb..3e6af99bbe53 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -739,7 +739,7 @@ static int rtnl_net_get_size(void) } static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, - int cmd, struct net *net, int nsid) + int cmd, int nsid) { struct nlmsghdr *nlh; struct rtgenmsg *rth; @@ -801,7 +801,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, id = peernet2id(net, peer); err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, - RTM_NEWNSID, net, id); + RTM_NEWNSID, id); if (err < 0) goto err_out; @@ -833,7 +833,7 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid, net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI, - RTM_NEWNSID, net_cb->net, id); + RTM_NEWNSID, id); if (ret < 0) return ret; @@ -876,7 +876,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id) if (!msg) goto out; - err = rtnl_net_fill(msg, 0, 0, 0, cmd, net, id); + err = rtnl_net_fill(msg, 0, 0, 0, cmd, id); if (err < 0) goto err_out; -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID 2018-11-21 11:01 [PATCH net-next 0/4] Ease to interpret net-nsid Nicolas Dichtel 2018-11-21 11:01 ` [PATCH net-next 1/4] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel @ 2018-11-21 11:01 ` Nicolas Dichtel 2018-11-21 18:05 ` David Ahern 2018-11-21 11:01 ` [PATCH net-next 3/4] netns: enable to specify a nsid for a get request Nicolas Dichtel ` (2 subsequent siblings) 4 siblings, 1 reply; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-21 11:01 UTC (permalink / raw) To: davem; +Cc: netdev, Nicolas Dichtel Like it was done for link and address, add the ability to perform get/dump in another netns by specifying a target nsid attribute. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> --- include/uapi/linux/net_namespace.h | 1 + net/core/net_namespace.c | 97 ++++++++++++++++++++++++------ 2 files changed, 80 insertions(+), 18 deletions(-) diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h index 0187c74d8889..0ed9dd61d32a 100644 --- a/include/uapi/linux/net_namespace.h +++ b/include/uapi/linux/net_namespace.h @@ -16,6 +16,7 @@ enum { NETNSA_NSID, NETNSA_PID, NETNSA_FD, + NETNSA_TARGET_NSID, __NETNSA_MAX, }; diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 3e6af99bbe53..3d02a742155f 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -669,6 +669,7 @@ static const struct nla_policy rtnl_net_policy[NETNSA_MAX + 1] = { [NETNSA_NSID] = { .type = NLA_S32 }, [NETNSA_PID] = { .type = NLA_U32 }, [NETNSA_FD] = { .type = NLA_U32 }, + [NETNSA_TARGET_NSID] = { .type = NLA_S32 }, }; static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh, @@ -767,9 +768,9 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, { struct net *net = sock_net(skb->sk); struct nlattr *tb[NETNSA_MAX + 1]; + struct net *peer, *target = net; struct nlattr *nla; struct sk_buff *msg; - struct net *peer; int err, id; err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX, @@ -793,30 +794,47 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, return PTR_ERR(peer); } + if (tb[NETNSA_TARGET_NSID]) { + id = nla_get_s32(tb[NETNSA_TARGET_NSID]); + target = rtnl_get_net_ns_capable(NETLINK_CB(skb).sk, id); + if (IS_ERR(target)) { + NL_SET_BAD_ATTR(extack, tb[NETNSA_TARGET_NSID]); + NL_SET_ERR_MSG(extack, + "Target netns reference is invalid"); + err = PTR_ERR(target); + goto put_peer; + } + } else { + get_net(target); + } + msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL); if (!msg) { err = -ENOMEM; - goto out; + goto put_target; } - id = peernet2id(net, peer); + id = peernet2id(target, peer); err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, RTM_NEWNSID, id); if (err < 0) - goto err_out; + goto free_nlmsg; err = rtnl_unicast(msg, net, NETLINK_CB(skb).portid); - goto out; + goto put_target; -err_out: +free_nlmsg: nlmsg_free(msg); -out: +put_target: + put_net(target); +put_peer: put_net(peer); return err; } struct rtnl_net_dump_cb { - struct net *net; + struct net *tgt_net; + struct net *ref_net; struct sk_buff *skb; struct netlink_callback *cb; int idx; @@ -842,29 +860,72 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) return 0; } +static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk, + struct rtnl_net_dump_cb *net_cb, + struct netlink_callback *cb) +{ + struct netlink_ext_ack *extack = cb->extack; + struct nlattr *tb[NETNSA_MAX + 1]; + int err, i; + + err = nlmsg_parse_strict(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX, + rtnl_net_policy, extack); + if (err < 0) + return err; + + for (i = 0; i <= NETNSA_MAX; i++) { + if (!tb[i]) + continue; + + if (i == NETNSA_TARGET_NSID) { + struct net *net; + + net = rtnl_get_net_ns_capable(sk, nla_get_s32(tb[i])); + if (IS_ERR(net)) { + NL_SET_BAD_ATTR(extack, tb[i]); + NL_SET_ERR_MSG(extack, + "Invalid target network namespace id"); + return PTR_ERR(net); + } + net_cb->ref_net = net_cb->tgt_net; + net_cb->tgt_net = net; + } else { + NL_SET_BAD_ATTR(extack, tb[i]); + NL_SET_ERR_MSG(extack, + "Unsupported attribute in dump request"); + return -EINVAL; + } + } + + return 0; +} + static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) { - struct net *net = sock_net(skb->sk); struct rtnl_net_dump_cb net_cb = { - .net = net, + .tgt_net = sock_net(skb->sk), .skb = skb, .cb = cb, .idx = 0, .s_idx = cb->args[0], }; + int err = 0; - if (cb->strict_check && - nlmsg_attrlen(cb->nlh, sizeof(struct rtgenmsg))) { - NL_SET_ERR_MSG(cb->extack, "Unknown data in network namespace id dump request"); - return -EINVAL; + if (cb->strict_check) { + err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb); + if (err < 0) + goto end; } - spin_lock_bh(&net->nsid_lock); - idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb); - spin_unlock_bh(&net->nsid_lock); + spin_lock_bh(&net_cb.tgt_net->nsid_lock); + idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb); + spin_unlock_bh(&net_cb.tgt_net->nsid_lock); cb->args[0] = net_cb.idx; - return skb->len; +end: + if (net_cb.ref_net) + put_net(net_cb.tgt_net); + return err < 0 ? err : skb->len; } static void rtnl_net_notifyid(struct net *net, int cmd, int id) -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID 2018-11-21 11:01 ` [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel @ 2018-11-21 18:05 ` David Ahern 2018-11-21 20:58 ` Nicolas Dichtel 0 siblings, 1 reply; 39+ messages in thread From: David Ahern @ 2018-11-21 18:05 UTC (permalink / raw) To: Nicolas Dichtel, davem; +Cc: netdev On 11/21/18 4:01 AM, Nicolas Dichtel wrote: > static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) > { > - struct net *net = sock_net(skb->sk); > struct rtnl_net_dump_cb net_cb = { > - .net = net, > + .tgt_net = sock_net(skb->sk), > .skb = skb, > .cb = cb, > .idx = 0, > .s_idx = cb->args[0], > }; > + int err = 0; > > - if (cb->strict_check && > - nlmsg_attrlen(cb->nlh, sizeof(struct rtgenmsg))) { > - NL_SET_ERR_MSG(cb->extack, "Unknown data in network namespace id dump request"); > - return -EINVAL; > + if (cb->strict_check) { > + err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb); > + if (err < 0) > + goto end; > } > > - spin_lock_bh(&net->nsid_lock); > - idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb); > - spin_unlock_bh(&net->nsid_lock); > + spin_lock_bh(&net_cb.tgt_net->nsid_lock); > + idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb); > + spin_unlock_bh(&net_cb.tgt_net->nsid_lock); > > cb->args[0] = net_cb.idx; > - return skb->len; > +end: > + if (net_cb.ref_net) > + put_net(net_cb.tgt_net); That is going to lead to confusion -- you check that ref_net is set put do a put on tgt_net. Other places using a target namespace use the nsid as the key to whether a put_net is needed. > + return err < 0 ? err : skb->len; > } > > static void rtnl_net_notifyid(struct net *net, int cmd, int id) > ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID 2018-11-21 18:05 ` David Ahern @ 2018-11-21 20:58 ` Nicolas Dichtel 2018-11-21 21:07 ` David Ahern 0 siblings, 1 reply; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-21 20:58 UTC (permalink / raw) To: David Ahern, davem; +Cc: netdev Le 21/11/2018 à 19:05, David Ahern a écrit : > On 11/21/18 4:01 AM, Nicolas Dichtel wrote: >> static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) >> { >> - struct net *net = sock_net(skb->sk); >> struct rtnl_net_dump_cb net_cb = { >> - .net = net, >> + .tgt_net = sock_net(skb->sk), >> .skb = skb, >> .cb = cb, >> .idx = 0, >> .s_idx = cb->args[0], >> }; >> + int err = 0; >> >> - if (cb->strict_check && >> - nlmsg_attrlen(cb->nlh, sizeof(struct rtgenmsg))) { >> - NL_SET_ERR_MSG(cb->extack, "Unknown data in network namespace id dump request"); >> - return -EINVAL; >> + if (cb->strict_check) { >> + err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb); >> + if (err < 0) >> + goto end; >> } >> >> - spin_lock_bh(&net->nsid_lock); >> - idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb); >> - spin_unlock_bh(&net->nsid_lock); >> + spin_lock_bh(&net_cb.tgt_net->nsid_lock); >> + idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb); >> + spin_unlock_bh(&net_cb.tgt_net->nsid_lock); >> >> cb->args[0] = net_cb.idx; >> - return skb->len; >> +end: >> + if (net_cb.ref_net) >> + put_net(net_cb.tgt_net); > > That is going to lead to confusion -- you check that ref_net is set put > do a put on tgt_net. Other places using a target namespace use the nsid > as the key to whether a put_net is needed. The target-nsid is not stored in net_cb (not needed). ref_net is set only if tgt_net comes from TARGET_NSID. I can add a comment. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID 2018-11-21 20:58 ` Nicolas Dichtel @ 2018-11-21 21:07 ` David Ahern 2018-11-22 8:06 ` Nicolas Dichtel 0 siblings, 1 reply; 39+ messages in thread From: David Ahern @ 2018-11-21 21:07 UTC (permalink / raw) To: nicolas.dichtel, davem; +Cc: netdev On 11/21/18 1:58 PM, Nicolas Dichtel wrote: > The target-nsid is not stored in net_cb (not needed). ref_net is set only if > tgt_net comes from TARGET_NSID. I can add a comment. ref_net is added by this patch and it is only used (unless I missed something) to know if the put_net is needed. ie/, drop ref_net in place of nsid ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID 2018-11-21 21:07 ` David Ahern @ 2018-11-22 8:06 ` Nicolas Dichtel 0 siblings, 0 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 8:06 UTC (permalink / raw) To: David Ahern, davem; +Cc: netdev Le 21/11/2018 à 22:07, David Ahern a écrit : > On 11/21/18 1:58 PM, Nicolas Dichtel wrote: >> The target-nsid is not stored in net_cb (not needed). ref_net is set only if >> tgt_net comes from TARGET_NSID. I can add a comment. > > ref_net is added by this patch and it is only used (unless I missed > something) to know if the put_net is needed. ie/, drop ref_net in place > of nsid It is used by a following patch (4/4) to get NETNSA_CURRENT_NSID. ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next 3/4] netns: enable to specify a nsid for a get request 2018-11-21 11:01 [PATCH net-next 0/4] Ease to interpret net-nsid Nicolas Dichtel 2018-11-21 11:01 ` [PATCH net-next 1/4] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel 2018-11-21 11:01 ` [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel @ 2018-11-21 11:01 ` Nicolas Dichtel 2018-11-21 11:01 ` [PATCH net-next 4/4] netns: enable to dump full nsid translation table Nicolas Dichtel 2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel 4 siblings, 0 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-21 11:01 UTC (permalink / raw) To: davem; +Cc: netdev, Nicolas Dichtel Combined with NETNSA_TARGET_NSID, it enables to "translate" a nsid from one netns to a nsid of another netns. This is useful when using NETLINK_F_LISTEN_ALL_NSID because it helps the user to interpret a nsid received from an other netns. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> --- net/core/net_namespace.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 3d02a742155f..92730905886c 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -783,6 +783,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, } else if (tb[NETNSA_FD]) { peer = get_net_ns_by_fd(nla_get_u32(tb[NETNSA_FD])); nla = tb[NETNSA_FD]; + } else if (tb[NETNSA_NSID]) { + peer = get_net_ns_by_id(net, nla_get_u32(tb[NETNSA_NSID])); + if (!peer) + peer = ERR_PTR(-ENOENT); + nla = tb[NETNSA_NSID]; } else { NL_SET_ERR_MSG(extack, "Peer netns reference is missing"); return -EINVAL; -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next 4/4] netns: enable to dump full nsid translation table 2018-11-21 11:01 [PATCH net-next 0/4] Ease to interpret net-nsid Nicolas Dichtel ` (2 preceding siblings ...) 2018-11-21 11:01 ` [PATCH net-next 3/4] netns: enable to specify a nsid for a get request Nicolas Dichtel @ 2018-11-21 11:01 ` Nicolas Dichtel 2018-11-21 18:09 ` David Ahern 2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel 4 siblings, 1 reply; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-21 11:01 UTC (permalink / raw) To: davem; +Cc: netdev, Nicolas Dichtel Like the previous patch, the goal is to ease to convert nsids from one netns to another netns. A new attribute (NETNSA_CURRENT_NSID) is added to the kernel answer when NETNSA_TARGET_NSID is provided, thus the user can easily convert nsids. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> --- include/uapi/linux/net_namespace.h | 1 + net/core/net_namespace.c | 30 ++++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h index 0ed9dd61d32a..9f9956809565 100644 --- a/include/uapi/linux/net_namespace.h +++ b/include/uapi/linux/net_namespace.h @@ -17,6 +17,7 @@ enum { NETNSA_PID, NETNSA_FD, NETNSA_TARGET_NSID, + NETNSA_CURRENT_NSID, __NETNSA_MAX, }; diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 92730905886c..fc568cd0b560 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -740,7 +740,7 @@ static int rtnl_net_get_size(void) } static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, - int cmd, int nsid) + int cmd, int nsid, bool add_ref, int ref_nsid) { struct nlmsghdr *nlh; struct rtgenmsg *rth; @@ -755,6 +755,9 @@ static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, if (nla_put_s32(skb, NETNSA_NSID, nsid)) goto nla_put_failure; + if (add_ref && nla_put_s32(skb, NETNSA_CURRENT_NSID, ref_nsid)) + goto nla_put_failure; + nlmsg_end(skb, nlh); return 0; @@ -769,9 +772,10 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, struct net *net = sock_net(skb->sk); struct nlattr *tb[NETNSA_MAX + 1]; struct net *peer, *target = net; + bool add_ref = false; struct nlattr *nla; struct sk_buff *msg; - int err, id; + int err, id, ref_id; err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX, rtnl_net_policy, extack); @@ -809,6 +813,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, err = PTR_ERR(target); goto put_peer; } + ref_id = peernet2id(net, peer); + add_ref = true; } else { get_net(target); } @@ -821,7 +827,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, id = peernet2id(target, peer); err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, - RTM_NEWNSID, id); + RTM_NEWNSID, id, add_ref, ref_id); if (err < 0) goto free_nlmsg; @@ -849,14 +855,17 @@ struct rtnl_net_dump_cb { static int rtnl_net_dumpid_one(int id, void *peer, void *data) { struct rtnl_net_dump_cb *net_cb = (struct rtnl_net_dump_cb *)data; - int ret; + int ref_id = 0, ret; if (net_cb->idx < net_cb->s_idx) goto cont; + if (net_cb->ref_net) + ref_id = __peernet2id(net_cb->ref_net, peer); + ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid, net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI, - RTM_NEWNSID, id); + RTM_NEWNSID, id, net_cb->ref_net, ref_id); if (ret < 0) return ret; @@ -923,7 +932,16 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) } spin_lock_bh(&net_cb.tgt_net->nsid_lock); + if (net_cb.ref_net && + !net_eq(net_cb.ref_net, net_cb.tgt_net) && + !spin_trylock_bh(&net_cb.ref_net->nsid_lock)) { + err = -EAGAIN; + goto end; + } idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb); + if (net_cb.ref_net && + !net_eq(net_cb.ref_net, net_cb.tgt_net)) + spin_unlock_bh(&net_cb.ref_net->nsid_lock); spin_unlock_bh(&net_cb.tgt_net->nsid_lock); cb->args[0] = net_cb.idx; @@ -942,7 +960,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id) if (!msg) goto out; - err = rtnl_net_fill(msg, 0, 0, 0, cmd, id); + err = rtnl_net_fill(msg, 0, 0, 0, cmd, id, false, 0); if (err < 0) goto err_out; -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 4/4] netns: enable to dump full nsid translation table 2018-11-21 11:01 ` [PATCH net-next 4/4] netns: enable to dump full nsid translation table Nicolas Dichtel @ 2018-11-21 18:09 ` David Ahern 2018-11-21 21:01 ` Nicolas Dichtel 0 siblings, 1 reply; 39+ messages in thread From: David Ahern @ 2018-11-21 18:09 UTC (permalink / raw) To: Nicolas Dichtel, davem; +Cc: netdev On 11/21/18 4:01 AM, Nicolas Dichtel wrote: > diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c > index 92730905886c..fc568cd0b560 100644 > --- a/net/core/net_namespace.c > +++ b/net/core/net_namespace.c > @@ -740,7 +740,7 @@ static int rtnl_net_get_size(void) > } > > static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, > - int cmd, int nsid) > + int cmd, int nsid, bool add_ref, int ref_nsid) > { > struct nlmsghdr *nlh; > struct rtgenmsg *rth; > @@ -755,6 +755,9 @@ static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, > if (nla_put_s32(skb, NETNSA_NSID, nsid)) > goto nla_put_failure; > > + if (add_ref && nla_put_s32(skb, NETNSA_CURRENT_NSID, ref_nsid)) > + goto nla_put_failure; Why not use ref_nsid >= 0 and drop the add_ref argument? ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 4/4] netns: enable to dump full nsid translation table 2018-11-21 18:09 ` David Ahern @ 2018-11-21 21:01 ` Nicolas Dichtel 2018-11-21 21:08 ` David Ahern 0 siblings, 1 reply; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-21 21:01 UTC (permalink / raw) To: David Ahern, davem; +Cc: netdev Le 21/11/2018 à 19:09, David Ahern a écrit : > On 11/21/18 4:01 AM, Nicolas Dichtel wrote: >> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c >> index 92730905886c..fc568cd0b560 100644 >> --- a/net/core/net_namespace.c >> +++ b/net/core/net_namespace.c >> @@ -740,7 +740,7 @@ static int rtnl_net_get_size(void) >> } >> >> static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, >> - int cmd, int nsid) >> + int cmd, int nsid, bool add_ref, int ref_nsid) >> { >> struct nlmsghdr *nlh; >> struct rtgenmsg *rth; >> @@ -755,6 +755,9 @@ static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, >> if (nla_put_s32(skb, NETNSA_NSID, nsid)) >> goto nla_put_failure; >> >> + if (add_ref && nla_put_s32(skb, NETNSA_CURRENT_NSID, ref_nsid)) >> + goto nla_put_failure; > > Why not use ref_nsid >= 0 and drop the add_ref argument? Because ref_nsid can be -1 (NETNSA_NSID_NOT_ASSIGNED) and I didn't want to add another magic, I think it's clearer with an explicit bool. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next 4/4] netns: enable to dump full nsid translation table 2018-11-21 21:01 ` Nicolas Dichtel @ 2018-11-21 21:08 ` David Ahern 0 siblings, 0 replies; 39+ messages in thread From: David Ahern @ 2018-11-21 21:08 UTC (permalink / raw) To: nicolas.dichtel, davem; +Cc: netdev On 11/21/18 2:01 PM, Nicolas Dichtel wrote: > Le 21/11/2018 à 19:09, David Ahern a écrit : >> On 11/21/18 4:01 AM, Nicolas Dichtel wrote: >>> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c >>> index 92730905886c..fc568cd0b560 100644 >>> --- a/net/core/net_namespace.c >>> +++ b/net/core/net_namespace.c >>> @@ -740,7 +740,7 @@ static int rtnl_net_get_size(void) >>> } >>> >>> static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, >>> - int cmd, int nsid) >>> + int cmd, int nsid, bool add_ref, int ref_nsid) >>> { >>> struct nlmsghdr *nlh; >>> struct rtgenmsg *rth; >>> @@ -755,6 +755,9 @@ static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, >>> if (nla_put_s32(skb, NETNSA_NSID, nsid)) >>> goto nla_put_failure; >>> >>> + if (add_ref && nla_put_s32(skb, NETNSA_CURRENT_NSID, ref_nsid)) >>> + goto nla_put_failure; >> >> Why not use ref_nsid >= 0 and drop the add_ref argument? > Because ref_nsid can be -1 (NETNSA_NSID_NOT_ASSIGNED) and I didn't want to add > another magic, I think it's clearer with an explicit bool. > it pushes the input args to 8. ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v2 0/5] Ease to interpret net-nsid 2018-11-21 11:01 [PATCH net-next 0/4] Ease to interpret net-nsid Nicolas Dichtel ` (3 preceding siblings ...) 2018-11-21 11:01 ` [PATCH net-next 4/4] netns: enable to dump full nsid translation table Nicolas Dichtel @ 2018-11-22 15:50 ` Nicolas Dichtel 2018-11-22 15:50 ` [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel ` (5 more replies) 4 siblings, 6 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem The goal of this series is to ease the interpretation of nsid received in netlink messages from other netns (when the user uses NETLINK_F_LISTEN_ALL_NSID). After this series, with a patched iproute2: $ ip netns add foo $ ip netns add bar $ touch /var/run/netns/init_net $ mount --bind /proc/1/ns/net /var/run/netns/init_net $ ip netns set init_net 11 $ ip netns set foo 12 $ ip netns set bar 13 $ ip netns init_net (id: 11) bar (id: 13) foo (id: 12) $ ip -n foo netns set init_net 21 $ ip -n foo netns set foo 22 $ ip -n foo netns set bar 23 $ ip -n foo netns init_net (id: 21) bar (id: 23) foo (id: 22) $ ip -n bar netns set init_net 31 $ ip -n bar netns set foo 32 $ ip -n bar netns set bar 33 $ ip -n bar netns init_net (id: 31) bar (id: 33) foo (id: 32) $ ip netns list-id target-nsid 12 nsid 21 current-nsid 11 (iproute2 netns name: init_net) nsid 22 current-nsid 12 (iproute2 netns name: foo) nsid 23 current-nsid 13 (iproute2 netns name: bar) $ ip -n bar netns list-id target-nsid 32 nsid 31 nsid 21 current-nsid 31 (iproute2 netns name: init_net) v1 -> v2: - patch 1/5: remove net from struct rtnl_net_dump_cb - patch 2/5: new in this version - patch 3/5: use a bool to know if rtnl_get_net_ns_capable() was called - patch 5/5: use struct net_fill_args include/uapi/linux/net_namespace.h | 2 + net/core/net_namespace.c | 157 +++++++++++++++++++++++++++++++------ 2 files changed, 133 insertions(+), 26 deletions(-) Comments are welcomed, Regards, Nicolas ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill() 2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel @ 2018-11-22 15:50 ` Nicolas Dichtel 2018-11-22 16:18 ` David Ahern 2018-11-22 15:50 ` [PATCH net-next v2 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel ` (4 subsequent siblings) 5 siblings, 1 reply; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel This argument is not used anymore. Fixes: cab3c8ec8d57 ("netns: always provide the id to rtnl_net_fill()") Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> --- net/core/net_namespace.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index fefe72774aeb..52b9620e3457 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -739,7 +739,7 @@ static int rtnl_net_get_size(void) } static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, - int cmd, struct net *net, int nsid) + int cmd, int nsid) { struct nlmsghdr *nlh; struct rtgenmsg *rth; @@ -801,7 +801,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, id = peernet2id(net, peer); err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, - RTM_NEWNSID, net, id); + RTM_NEWNSID, id); if (err < 0) goto err_out; @@ -816,7 +816,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, } struct rtnl_net_dump_cb { - struct net *net; struct sk_buff *skb; struct netlink_callback *cb; int idx; @@ -833,7 +832,7 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid, net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI, - RTM_NEWNSID, net_cb->net, id); + RTM_NEWNSID, id); if (ret < 0) return ret; @@ -846,7 +845,6 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) { struct net *net = sock_net(skb->sk); struct rtnl_net_dump_cb net_cb = { - .net = net, .skb = skb, .cb = cb, .idx = 0, @@ -876,7 +874,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id) if (!msg) goto out; - err = rtnl_net_fill(msg, 0, 0, 0, cmd, net, id); + err = rtnl_net_fill(msg, 0, 0, 0, cmd, id); if (err < 0) goto err_out; -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill() 2018-11-22 15:50 ` [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel @ 2018-11-22 16:18 ` David Ahern 0 siblings, 0 replies; 39+ messages in thread From: David Ahern @ 2018-11-22 16:18 UTC (permalink / raw) To: Nicolas Dichtel; +Cc: netdev, davem On 11/22/18 8:50 AM, Nicolas Dichtel wrote: > This argument is not used anymore. > > Fixes: cab3c8ec8d57 ("netns: always provide the id to rtnl_net_fill()") > Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> > --- > net/core/net_namespace.c | 10 ++++------ > 1 file changed, 4 insertions(+), 6 deletions(-) > Reviewed-by: David Ahern <dsahern@gmail.com> ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v2 2/5] netns: introduce 'struct net_fill_args' 2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel 2018-11-22 15:50 ` [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel @ 2018-11-22 15:50 ` Nicolas Dichtel 2018-11-22 16:23 ` David Ahern 2018-11-22 15:50 ` [PATCH net-next v2 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel ` (3 subsequent siblings) 5 siblings, 1 reply; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel This is a preparatory work. To avoid having to much arguments for the function rtnl_net_fill(), a new structure is defined. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> --- net/core/net_namespace.c | 48 ++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 52b9620e3457..f8a5966b086c 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -738,20 +738,28 @@ static int rtnl_net_get_size(void) ; } -static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, - int cmd, int nsid) +struct net_fill_args { + u32 portid; + u32 seq; + int flags; + int cmd; + int nsid; +}; + +static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args) { struct nlmsghdr *nlh; struct rtgenmsg *rth; - nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rth), flags); + nlh = nlmsg_put(skb, args->portid, args->seq, args->cmd, sizeof(*rth), + args->flags); if (!nlh) return -EMSGSIZE; rth = nlmsg_data(nlh); rth->rtgen_family = AF_UNSPEC; - if (nla_put_s32(skb, NETNSA_NSID, nsid)) + if (nla_put_s32(skb, NETNSA_NSID, args->nsid)) goto nla_put_failure; nlmsg_end(skb, nlh); @@ -767,10 +775,15 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, { struct net *net = sock_net(skb->sk); struct nlattr *tb[NETNSA_MAX + 1]; + struct net_fill_args fillargs = { + .portid = NETLINK_CB(skb).portid, + .seq = nlh->nlmsg_seq, + .cmd = RTM_NEWNSID, + }; struct nlattr *nla; struct sk_buff *msg; struct net *peer; - int err, id; + int err; err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX, rtnl_net_policy, extack); @@ -799,9 +812,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, goto out; } - id = peernet2id(net, peer); - err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, - RTM_NEWNSID, id); + fillargs.nsid = peernet2id(net, peer); + err = rtnl_net_fill(msg, &fillargs); if (err < 0) goto err_out; @@ -817,7 +829,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, struct rtnl_net_dump_cb { struct sk_buff *skb; - struct netlink_callback *cb; + struct net_fill_args fillargs; int idx; int s_idx; }; @@ -830,9 +842,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) if (net_cb->idx < net_cb->s_idx) goto cont; - ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid, - net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI, - RTM_NEWNSID, id); + net_cb->fillargs.nsid = id; + ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs); if (ret < 0) return ret; @@ -846,7 +857,12 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) struct net *net = sock_net(skb->sk); struct rtnl_net_dump_cb net_cb = { .skb = skb, - .cb = cb, + .fillargs = { + .portid = NETLINK_CB(cb->skb).portid, + .seq = cb->nlh->nlmsg_seq, + .flags = NLM_F_MULTI, + .cmd = RTM_NEWNSID, + }, .idx = 0, .s_idx = cb->args[0], }; @@ -867,6 +883,10 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) static void rtnl_net_notifyid(struct net *net, int cmd, int id) { + struct net_fill_args fillargs = { + .cmd = cmd, + .nsid = id, + }; struct sk_buff *msg; int err = -ENOMEM; @@ -874,7 +894,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id) if (!msg) goto out; - err = rtnl_net_fill(msg, 0, 0, 0, cmd, id); + err = rtnl_net_fill(msg, &fillargs); if (err < 0) goto err_out; -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v2 2/5] netns: introduce 'struct net_fill_args' 2018-11-22 15:50 ` [PATCH net-next v2 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel @ 2018-11-22 16:23 ` David Ahern 0 siblings, 0 replies; 39+ messages in thread From: David Ahern @ 2018-11-22 16:23 UTC (permalink / raw) To: Nicolas Dichtel; +Cc: netdev, davem On 11/22/18 8:50 AM, Nicolas Dichtel wrote: > This is a preparatory work. To avoid having to much arguments for the > function rtnl_net_fill(), a new structure is defined. > > Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> > --- > net/core/net_namespace.c | 48 ++++++++++++++++++++++++++++------------ > 1 file changed, 34 insertions(+), 14 deletions(-) > Reviewed-by: David Ahern <dsahern@gmail.com> ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v2 3/5] netns: add support of NETNSA_TARGET_NSID 2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel 2018-11-22 15:50 ` [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel 2018-11-22 15:50 ` [PATCH net-next v2 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel @ 2018-11-22 15:50 ` Nicolas Dichtel 2018-11-22 16:32 ` David Ahern 2018-11-22 15:50 ` [PATCH net-next v2 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel ` (2 subsequent siblings) 5 siblings, 1 reply; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel Like it was done for link and address, add the ability to perform get/dump in another netns by specifying a target nsid attribute. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> --- include/uapi/linux/net_namespace.h | 1 + net/core/net_namespace.c | 86 ++++++++++++++++++++++++++---- 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h index 0187c74d8889..0ed9dd61d32a 100644 --- a/include/uapi/linux/net_namespace.h +++ b/include/uapi/linux/net_namespace.h @@ -16,6 +16,7 @@ enum { NETNSA_NSID, NETNSA_PID, NETNSA_FD, + NETNSA_TARGET_NSID, __NETNSA_MAX, }; diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index f8a5966b086c..885c54197e31 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -669,6 +669,7 @@ static const struct nla_policy rtnl_net_policy[NETNSA_MAX + 1] = { [NETNSA_NSID] = { .type = NLA_S32 }, [NETNSA_PID] = { .type = NLA_U32 }, [NETNSA_FD] = { .type = NLA_U32 }, + [NETNSA_TARGET_NSID] = { .type = NLA_S32 }, }; static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh, @@ -780,9 +781,10 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, .seq = nlh->nlmsg_seq, .cmd = RTM_NEWNSID, }; + struct net *peer, *target = net; + bool put_target = false; struct nlattr *nla; struct sk_buff *msg; - struct net *peer; int err; err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX, @@ -806,13 +808,27 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, return PTR_ERR(peer); } + if (tb[NETNSA_TARGET_NSID]) { + int id = nla_get_s32(tb[NETNSA_TARGET_NSID]); + + target = rtnl_get_net_ns_capable(NETLINK_CB(skb).sk, id); + if (IS_ERR(target)) { + NL_SET_BAD_ATTR(extack, tb[NETNSA_TARGET_NSID]); + NL_SET_ERR_MSG(extack, + "Target netns reference is invalid"); + err = PTR_ERR(target); + goto out; + } + put_target = true; + } + msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL); if (!msg) { err = -ENOMEM; goto out; } - fillargs.nsid = peernet2id(net, peer); + fillargs.nsid = peernet2id(target, peer); err = rtnl_net_fill(msg, &fillargs); if (err < 0) goto err_out; @@ -823,15 +839,19 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, err_out: nlmsg_free(msg); out: + if (put_target) + put_net(target); put_net(peer); return err; } struct rtnl_net_dump_cb { + struct net *tgt_net; struct sk_buff *skb; struct net_fill_args fillargs; int idx; int s_idx; + bool put_tgt_net; }; static int rtnl_net_dumpid_one(int id, void *peer, void *data) @@ -852,10 +872,50 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) return 0; } +static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk, + struct rtnl_net_dump_cb *net_cb, + struct netlink_callback *cb) +{ + struct netlink_ext_ack *extack = cb->extack; + struct nlattr *tb[NETNSA_MAX + 1]; + int err, i; + + err = nlmsg_parse_strict(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX, + rtnl_net_policy, extack); + if (err < 0) + return err; + + for (i = 0; i <= NETNSA_MAX; i++) { + if (!tb[i]) + continue; + + if (i == NETNSA_TARGET_NSID) { + struct net *net; + + net = rtnl_get_net_ns_capable(sk, nla_get_s32(tb[i])); + if (IS_ERR(net)) { + NL_SET_BAD_ATTR(extack, tb[i]); + NL_SET_ERR_MSG(extack, + "Invalid target network namespace id"); + return PTR_ERR(net); + } + net_cb->tgt_net = net; + net_cb->put_tgt_net = true; + } else { + NL_SET_BAD_ATTR(extack, tb[i]); + NL_SET_ERR_MSG(extack, + "Unsupported attribute in dump request"); + return -EINVAL; + } + } + + return 0; +} + static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) { - struct net *net = sock_net(skb->sk); struct rtnl_net_dump_cb net_cb = { + .tgt_net = sock_net(skb->sk), .skb = skb, .fillargs = { .portid = NETLINK_CB(cb->skb).portid, @@ -866,19 +926,23 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) .idx = 0, .s_idx = cb->args[0], }; + int err = 0; - if (cb->strict_check && - nlmsg_attrlen(cb->nlh, sizeof(struct rtgenmsg))) { - NL_SET_ERR_MSG(cb->extack, "Unknown data in network namespace id dump request"); - return -EINVAL; + if (cb->strict_check) { + err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb); + if (err < 0) + goto end; } - spin_lock_bh(&net->nsid_lock); - idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb); - spin_unlock_bh(&net->nsid_lock); + spin_lock_bh(&net_cb.tgt_net->nsid_lock); + idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb); + spin_unlock_bh(&net_cb.tgt_net->nsid_lock); cb->args[0] = net_cb.idx; - return skb->len; +end: + if (net_cb.put_tgt_net) + put_net(net_cb.tgt_net); + return err < 0 ? err : skb->len; } static void rtnl_net_notifyid(struct net *net, int cmd, int id) -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v2 3/5] netns: add support of NETNSA_TARGET_NSID 2018-11-22 15:50 ` [PATCH net-next v2 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel @ 2018-11-22 16:32 ` David Ahern 0 siblings, 0 replies; 39+ messages in thread From: David Ahern @ 2018-11-22 16:32 UTC (permalink / raw) To: Nicolas Dichtel; +Cc: netdev, davem On 11/22/18 8:50 AM, Nicolas Dichtel wrote: > Like it was done for link and address, add the ability to perform get/dump > in another netns by specifying a target nsid attribute. > > Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> > --- > include/uapi/linux/net_namespace.h | 1 + > net/core/net_namespace.c | 86 ++++++++++++++++++++++++++---- > 2 files changed, 76 insertions(+), 11 deletions(-) Reviewed-by: David Ahern <dsahern@gmail.com> ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v2 4/5] netns: enable to specify a nsid for a get request 2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel ` (2 preceding siblings ...) 2018-11-22 15:50 ` [PATCH net-next v2 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel @ 2018-11-22 15:50 ` Nicolas Dichtel 2018-11-22 16:32 ` David Ahern 2018-11-22 15:50 ` [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel 5 siblings, 1 reply; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel Combined with NETNSA_TARGET_NSID, it enables to "translate" a nsid from one netns to a nsid of another netns. This is useful when using NETLINK_F_LISTEN_ALL_NSID because it helps the user to interpret a nsid received from an other netns. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> --- net/core/net_namespace.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 885c54197e31..dd25fb22ad45 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -797,6 +797,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, } else if (tb[NETNSA_FD]) { peer = get_net_ns_by_fd(nla_get_u32(tb[NETNSA_FD])); nla = tb[NETNSA_FD]; + } else if (tb[NETNSA_NSID]) { + peer = get_net_ns_by_id(net, nla_get_u32(tb[NETNSA_NSID])); + if (!peer) + peer = ERR_PTR(-ENOENT); + nla = tb[NETNSA_NSID]; } else { NL_SET_ERR_MSG(extack, "Peer netns reference is missing"); return -EINVAL; -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v2 4/5] netns: enable to specify a nsid for a get request 2018-11-22 15:50 ` [PATCH net-next v2 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel @ 2018-11-22 16:32 ` David Ahern 0 siblings, 0 replies; 39+ messages in thread From: David Ahern @ 2018-11-22 16:32 UTC (permalink / raw) To: Nicolas Dichtel; +Cc: netdev, davem On 11/22/18 8:50 AM, Nicolas Dichtel wrote: > Combined with NETNSA_TARGET_NSID, it enables to "translate" a nsid from one > netns to a nsid of another netns. > This is useful when using NETLINK_F_LISTEN_ALL_NSID because it helps the > user to interpret a nsid received from an other netns. > > Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> > --- > net/core/net_namespace.c | 5 +++++ > 1 file changed, 5 insertions(+) > Reviewed-by: David Ahern <dsahern@gmail.com> ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table 2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel ` (3 preceding siblings ...) 2018-11-22 15:50 ` [PATCH net-next v2 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel @ 2018-11-22 15:50 ` Nicolas Dichtel 2018-11-22 16:40 ` David Ahern 2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel 5 siblings, 1 reply; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel Like the previous patch, the goal is to ease to convert nsids from one netns to another netns. A new attribute (NETNSA_CURRENT_NSID) is added to the kernel answer when NETNSA_TARGET_NSID is provided, thus the user can easily convert nsids. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> --- include/uapi/linux/net_namespace.h | 1 + net/core/net_namespace.c | 30 ++++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h index 0ed9dd61d32a..9f9956809565 100644 --- a/include/uapi/linux/net_namespace.h +++ b/include/uapi/linux/net_namespace.h @@ -17,6 +17,7 @@ enum { NETNSA_PID, NETNSA_FD, NETNSA_TARGET_NSID, + NETNSA_CURRENT_NSID, __NETNSA_MAX, }; diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index dd25fb22ad45..25030e0317a2 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -745,6 +745,8 @@ struct net_fill_args { int flags; int cmd; int nsid; + bool add_ref; + int ref_nsid; }; static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args) @@ -763,6 +765,10 @@ static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args) if (nla_put_s32(skb, NETNSA_NSID, args->nsid)) goto nla_put_failure; + if (args->add_ref && + nla_put_s32(skb, NETNSA_CURRENT_NSID, args->ref_nsid)) + goto nla_put_failure; + nlmsg_end(skb, nlh); return 0; @@ -782,7 +788,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, .cmd = RTM_NEWNSID, }; struct net *peer, *target = net; - bool put_target = false; struct nlattr *nla; struct sk_buff *msg; int err; @@ -824,7 +829,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, err = PTR_ERR(target); goto out; } - put_target = true; + fillargs.add_ref = true; + fillargs.ref_nsid = peernet2id(net, peer); } msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL); @@ -844,7 +850,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, err_out: nlmsg_free(msg); out: - if (put_target) + if (fillargs.add_ref) put_net(target); put_net(peer); return err; @@ -852,11 +858,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, struct rtnl_net_dump_cb { struct net *tgt_net; + struct net *ref_net; struct sk_buff *skb; struct net_fill_args fillargs; int idx; int s_idx; - bool put_tgt_net; }; static int rtnl_net_dumpid_one(int id, void *peer, void *data) @@ -868,6 +874,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) goto cont; net_cb->fillargs.nsid = id; + if (net_cb->fillargs.add_ref) + net_cb->fillargs.ref_nsid = __peernet2id(net_cb->ref_net, peer); ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs); if (ret < 0) return ret; @@ -904,8 +912,9 @@ static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk, "Invalid target network namespace id"); return PTR_ERR(net); } + net_cb->fillargs.add_ref = true; + net_cb->ref_net = net_cb->tgt_net; net_cb->tgt_net = net; - net_cb->put_tgt_net = true; } else { NL_SET_BAD_ATTR(extack, tb[i]); NL_SET_ERR_MSG(extack, @@ -940,12 +949,21 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) } spin_lock_bh(&net_cb.tgt_net->nsid_lock); + if (net_cb.fillargs.add_ref && + !net_eq(net_cb.ref_net, net_cb.tgt_net) && + !spin_trylock_bh(&net_cb.ref_net->nsid_lock)) { + err = -EAGAIN; + goto end; + } idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb); + if (net_cb.fillargs.add_ref && + !net_eq(net_cb.ref_net, net_cb.tgt_net)) + spin_unlock_bh(&net_cb.ref_net->nsid_lock); spin_unlock_bh(&net_cb.tgt_net->nsid_lock); cb->args[0] = net_cb.idx; end: - if (net_cb.put_tgt_net) + if (net_cb.fillargs.add_ref) put_net(net_cb.tgt_net); return err < 0 ? err : skb->len; } -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table 2018-11-22 15:50 ` [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel @ 2018-11-22 16:40 ` David Ahern 2018-11-22 16:42 ` Nicolas Dichtel 0 siblings, 1 reply; 39+ messages in thread From: David Ahern @ 2018-11-22 16:40 UTC (permalink / raw) To: Nicolas Dichtel; +Cc: netdev, davem On 11/22/18 8:50 AM, Nicolas Dichtel wrote: > diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c > index dd25fb22ad45..25030e0317a2 100644 > --- a/net/core/net_namespace.c > +++ b/net/core/net_namespace.c > @@ -745,6 +745,8 @@ struct net_fill_args { > int flags; > int cmd; > int nsid; > + bool add_ref; > + int ref_nsid; > }; > > static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args) > @@ -763,6 +765,10 @@ static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args) > if (nla_put_s32(skb, NETNSA_NSID, args->nsid)) > goto nla_put_failure; > > + if (args->add_ref && > + nla_put_s32(skb, NETNSA_CURRENT_NSID, args->ref_nsid)) > + goto nla_put_failure; > + you need to add NETNSA_CURRENT_NSID to rtnl_net_get_size. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table 2018-11-22 16:40 ` David Ahern @ 2018-11-22 16:42 ` Nicolas Dichtel 0 siblings, 0 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 16:42 UTC (permalink / raw) To: David Ahern; +Cc: netdev, davem Le 22/11/2018 à 17:40, David Ahern a écrit : > On 11/22/18 8:50 AM, Nicolas Dichtel wrote: >> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c >> index dd25fb22ad45..25030e0317a2 100644 >> --- a/net/core/net_namespace.c >> +++ b/net/core/net_namespace.c >> @@ -745,6 +745,8 @@ struct net_fill_args { >> int flags; >> int cmd; >> int nsid; >> + bool add_ref; >> + int ref_nsid; >> }; >> >> static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args) >> @@ -763,6 +765,10 @@ static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args) >> if (nla_put_s32(skb, NETNSA_NSID, args->nsid)) >> goto nla_put_failure; >> >> + if (args->add_ref && >> + nla_put_s32(skb, NETNSA_CURRENT_NSID, args->ref_nsid)) >> + goto nla_put_failure; >> + > > you need to add NETNSA_CURRENT_NSID to rtnl_net_get_size. > Good catch. I thought to this and I forgot at the end :/ ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v3 0/5] Ease to interpret net-nsid 2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel ` (4 preceding siblings ...) 2018-11-22 15:50 ` [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel @ 2018-11-22 22:22 ` Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel ` (5 more replies) 5 siblings, 6 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 22:22 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem The goal of this series is to ease the interpretation of nsid received in netlink messages from other netns (when the user uses NETLINK_F_LISTEN_ALL_NSID). After this series, with a patched iproute2: $ ip netns add foo $ ip netns add bar $ touch /var/run/netns/init_net $ mount --bind /proc/1/ns/net /var/run/netns/init_net $ ip netns set init_net 11 $ ip netns set foo 12 $ ip netns set bar 13 $ ip netns init_net (id: 11) bar (id: 13) foo (id: 12) $ ip -n foo netns set init_net 21 $ ip -n foo netns set foo 22 $ ip -n foo netns set bar 23 $ ip -n foo netns init_net (id: 21) bar (id: 23) foo (id: 22) $ ip -n bar netns set init_net 31 $ ip -n bar netns set foo 32 $ ip -n bar netns set bar 33 $ ip -n bar netns init_net (id: 31) bar (id: 33) foo (id: 32) $ ip netns list-id target-nsid 12 nsid 21 current-nsid 11 (iproute2 netns name: init_net) nsid 22 current-nsid 12 (iproute2 netns name: foo) nsid 23 current-nsid 13 (iproute2 netns name: bar) $ ip -n bar netns list-id target-nsid 32 nsid 31 nsid 21 current-nsid 31 (iproute2 netns name: init_net) v2 -> v3: - patch 5/5: account NETNSA_CURRENT_NSID in rtnl_net_get_size() v1 -> v2: - patch 1/5: remove net from struct rtnl_net_dump_cb - patch 2/5: new in this version - patch 3/5: use a bool to know if rtnl_get_net_ns_capable() was called - patch 5/5: use struct net_fill_args include/uapi/linux/net_namespace.h | 2 + net/core/net_namespace.c | 158 +++++++++++++++++++++++++++++++------ 2 files changed, 134 insertions(+), 26 deletions(-) Comments are welcomed, Regards, Nicolas ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v3 1/5] netns: remove net arg from rtnl_net_fill() 2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel @ 2018-11-22 22:22 ` Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel ` (4 subsequent siblings) 5 siblings, 0 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 22:22 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel This argument is not used anymore. Fixes: cab3c8ec8d57 ("netns: always provide the id to rtnl_net_fill()") Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Reviewed-by: David Ahern <dsahern@gmail.com> --- net/core/net_namespace.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index fefe72774aeb..52b9620e3457 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -739,7 +739,7 @@ static int rtnl_net_get_size(void) } static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, - int cmd, struct net *net, int nsid) + int cmd, int nsid) { struct nlmsghdr *nlh; struct rtgenmsg *rth; @@ -801,7 +801,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, id = peernet2id(net, peer); err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, - RTM_NEWNSID, net, id); + RTM_NEWNSID, id); if (err < 0) goto err_out; @@ -816,7 +816,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, } struct rtnl_net_dump_cb { - struct net *net; struct sk_buff *skb; struct netlink_callback *cb; int idx; @@ -833,7 +832,7 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid, net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI, - RTM_NEWNSID, net_cb->net, id); + RTM_NEWNSID, id); if (ret < 0) return ret; @@ -846,7 +845,6 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) { struct net *net = sock_net(skb->sk); struct rtnl_net_dump_cb net_cb = { - .net = net, .skb = skb, .cb = cb, .idx = 0, @@ -876,7 +874,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id) if (!msg) goto out; - err = rtnl_net_fill(msg, 0, 0, 0, cmd, net, id); + err = rtnl_net_fill(msg, 0, 0, 0, cmd, id); if (err < 0) goto err_out; -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v3 2/5] netns: introduce 'struct net_fill_args' 2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel @ 2018-11-22 22:22 ` Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel ` (3 subsequent siblings) 5 siblings, 0 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 22:22 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel This is a preparatory work. To avoid having to much arguments for the function rtnl_net_fill(), a new structure is defined. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Reviewed-by: David Ahern <dsahern@gmail.com> --- net/core/net_namespace.c | 48 ++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 52b9620e3457..f8a5966b086c 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -738,20 +738,28 @@ static int rtnl_net_get_size(void) ; } -static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, - int cmd, int nsid) +struct net_fill_args { + u32 portid; + u32 seq; + int flags; + int cmd; + int nsid; +}; + +static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args) { struct nlmsghdr *nlh; struct rtgenmsg *rth; - nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rth), flags); + nlh = nlmsg_put(skb, args->portid, args->seq, args->cmd, sizeof(*rth), + args->flags); if (!nlh) return -EMSGSIZE; rth = nlmsg_data(nlh); rth->rtgen_family = AF_UNSPEC; - if (nla_put_s32(skb, NETNSA_NSID, nsid)) + if (nla_put_s32(skb, NETNSA_NSID, args->nsid)) goto nla_put_failure; nlmsg_end(skb, nlh); @@ -767,10 +775,15 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, { struct net *net = sock_net(skb->sk); struct nlattr *tb[NETNSA_MAX + 1]; + struct net_fill_args fillargs = { + .portid = NETLINK_CB(skb).portid, + .seq = nlh->nlmsg_seq, + .cmd = RTM_NEWNSID, + }; struct nlattr *nla; struct sk_buff *msg; struct net *peer; - int err, id; + int err; err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX, rtnl_net_policy, extack); @@ -799,9 +812,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, goto out; } - id = peernet2id(net, peer); - err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, - RTM_NEWNSID, id); + fillargs.nsid = peernet2id(net, peer); + err = rtnl_net_fill(msg, &fillargs); if (err < 0) goto err_out; @@ -817,7 +829,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, struct rtnl_net_dump_cb { struct sk_buff *skb; - struct netlink_callback *cb; + struct net_fill_args fillargs; int idx; int s_idx; }; @@ -830,9 +842,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) if (net_cb->idx < net_cb->s_idx) goto cont; - ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid, - net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI, - RTM_NEWNSID, id); + net_cb->fillargs.nsid = id; + ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs); if (ret < 0) return ret; @@ -846,7 +857,12 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) struct net *net = sock_net(skb->sk); struct rtnl_net_dump_cb net_cb = { .skb = skb, - .cb = cb, + .fillargs = { + .portid = NETLINK_CB(cb->skb).portid, + .seq = cb->nlh->nlmsg_seq, + .flags = NLM_F_MULTI, + .cmd = RTM_NEWNSID, + }, .idx = 0, .s_idx = cb->args[0], }; @@ -867,6 +883,10 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) static void rtnl_net_notifyid(struct net *net, int cmd, int id) { + struct net_fill_args fillargs = { + .cmd = cmd, + .nsid = id, + }; struct sk_buff *msg; int err = -ENOMEM; @@ -874,7 +894,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id) if (!msg) goto out; - err = rtnl_net_fill(msg, 0, 0, 0, cmd, id); + err = rtnl_net_fill(msg, &fillargs); if (err < 0) goto err_out; -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v3 3/5] netns: add support of NETNSA_TARGET_NSID 2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel @ 2018-11-22 22:22 ` Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel ` (2 subsequent siblings) 5 siblings, 0 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 22:22 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel Like it was done for link and address, add the ability to perform get/dump in another netns by specifying a target nsid attribute. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Reviewed-by: David Ahern <dsahern@gmail.com> --- include/uapi/linux/net_namespace.h | 1 + net/core/net_namespace.c | 86 ++++++++++++++++++++++++++---- 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h index 0187c74d8889..0ed9dd61d32a 100644 --- a/include/uapi/linux/net_namespace.h +++ b/include/uapi/linux/net_namespace.h @@ -16,6 +16,7 @@ enum { NETNSA_NSID, NETNSA_PID, NETNSA_FD, + NETNSA_TARGET_NSID, __NETNSA_MAX, }; diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index f8a5966b086c..885c54197e31 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -669,6 +669,7 @@ static const struct nla_policy rtnl_net_policy[NETNSA_MAX + 1] = { [NETNSA_NSID] = { .type = NLA_S32 }, [NETNSA_PID] = { .type = NLA_U32 }, [NETNSA_FD] = { .type = NLA_U32 }, + [NETNSA_TARGET_NSID] = { .type = NLA_S32 }, }; static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh, @@ -780,9 +781,10 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, .seq = nlh->nlmsg_seq, .cmd = RTM_NEWNSID, }; + struct net *peer, *target = net; + bool put_target = false; struct nlattr *nla; struct sk_buff *msg; - struct net *peer; int err; err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX, @@ -806,13 +808,27 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, return PTR_ERR(peer); } + if (tb[NETNSA_TARGET_NSID]) { + int id = nla_get_s32(tb[NETNSA_TARGET_NSID]); + + target = rtnl_get_net_ns_capable(NETLINK_CB(skb).sk, id); + if (IS_ERR(target)) { + NL_SET_BAD_ATTR(extack, tb[NETNSA_TARGET_NSID]); + NL_SET_ERR_MSG(extack, + "Target netns reference is invalid"); + err = PTR_ERR(target); + goto out; + } + put_target = true; + } + msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL); if (!msg) { err = -ENOMEM; goto out; } - fillargs.nsid = peernet2id(net, peer); + fillargs.nsid = peernet2id(target, peer); err = rtnl_net_fill(msg, &fillargs); if (err < 0) goto err_out; @@ -823,15 +839,19 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, err_out: nlmsg_free(msg); out: + if (put_target) + put_net(target); put_net(peer); return err; } struct rtnl_net_dump_cb { + struct net *tgt_net; struct sk_buff *skb; struct net_fill_args fillargs; int idx; int s_idx; + bool put_tgt_net; }; static int rtnl_net_dumpid_one(int id, void *peer, void *data) @@ -852,10 +872,50 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) return 0; } +static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk, + struct rtnl_net_dump_cb *net_cb, + struct netlink_callback *cb) +{ + struct netlink_ext_ack *extack = cb->extack; + struct nlattr *tb[NETNSA_MAX + 1]; + int err, i; + + err = nlmsg_parse_strict(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX, + rtnl_net_policy, extack); + if (err < 0) + return err; + + for (i = 0; i <= NETNSA_MAX; i++) { + if (!tb[i]) + continue; + + if (i == NETNSA_TARGET_NSID) { + struct net *net; + + net = rtnl_get_net_ns_capable(sk, nla_get_s32(tb[i])); + if (IS_ERR(net)) { + NL_SET_BAD_ATTR(extack, tb[i]); + NL_SET_ERR_MSG(extack, + "Invalid target network namespace id"); + return PTR_ERR(net); + } + net_cb->tgt_net = net; + net_cb->put_tgt_net = true; + } else { + NL_SET_BAD_ATTR(extack, tb[i]); + NL_SET_ERR_MSG(extack, + "Unsupported attribute in dump request"); + return -EINVAL; + } + } + + return 0; +} + static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) { - struct net *net = sock_net(skb->sk); struct rtnl_net_dump_cb net_cb = { + .tgt_net = sock_net(skb->sk), .skb = skb, .fillargs = { .portid = NETLINK_CB(cb->skb).portid, @@ -866,19 +926,23 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) .idx = 0, .s_idx = cb->args[0], }; + int err = 0; - if (cb->strict_check && - nlmsg_attrlen(cb->nlh, sizeof(struct rtgenmsg))) { - NL_SET_ERR_MSG(cb->extack, "Unknown data in network namespace id dump request"); - return -EINVAL; + if (cb->strict_check) { + err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb); + if (err < 0) + goto end; } - spin_lock_bh(&net->nsid_lock); - idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb); - spin_unlock_bh(&net->nsid_lock); + spin_lock_bh(&net_cb.tgt_net->nsid_lock); + idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb); + spin_unlock_bh(&net_cb.tgt_net->nsid_lock); cb->args[0] = net_cb.idx; - return skb->len; +end: + if (net_cb.put_tgt_net) + put_net(net_cb.tgt_net); + return err < 0 ? err : skb->len; } static void rtnl_net_notifyid(struct net *net, int cmd, int id) -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v3 4/5] netns: enable to specify a nsid for a get request 2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel ` (2 preceding siblings ...) 2018-11-22 22:22 ` [PATCH net-next v3 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel @ 2018-11-22 22:22 ` Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel 5 siblings, 0 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 22:22 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel Combined with NETNSA_TARGET_NSID, it enables to "translate" a nsid from one netns to a nsid of another netns. This is useful when using NETLINK_F_LISTEN_ALL_NSID because it helps the user to interpret a nsid received from an other netns. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Reviewed-by: David Ahern <dsahern@gmail.com> --- net/core/net_namespace.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 885c54197e31..dd25fb22ad45 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -797,6 +797,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, } else if (tb[NETNSA_FD]) { peer = get_net_ns_by_fd(nla_get_u32(tb[NETNSA_FD])); nla = tb[NETNSA_FD]; + } else if (tb[NETNSA_NSID]) { + peer = get_net_ns_by_id(net, nla_get_u32(tb[NETNSA_NSID])); + if (!peer) + peer = ERR_PTR(-ENOENT); + nla = tb[NETNSA_NSID]; } else { NL_SET_ERR_MSG(extack, "Peer netns reference is missing"); return -EINVAL; -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table 2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel ` (3 preceding siblings ...) 2018-11-22 22:22 ` [PATCH net-next v3 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel @ 2018-11-22 22:22 ` Nicolas Dichtel 2018-11-24 15:47 ` David Ahern 2018-11-26 10:06 ` kbuild test robot 2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel 5 siblings, 2 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-22 22:22 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel Like the previous patch, the goal is to ease to convert nsids from one netns to another netns. A new attribute (NETNSA_CURRENT_NSID) is added to the kernel answer when NETNSA_TARGET_NSID is provided, thus the user can easily convert nsids. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> --- include/uapi/linux/net_namespace.h | 1 + net/core/net_namespace.c | 31 ++++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h index 0ed9dd61d32a..9f9956809565 100644 --- a/include/uapi/linux/net_namespace.h +++ b/include/uapi/linux/net_namespace.h @@ -17,6 +17,7 @@ enum { NETNSA_PID, NETNSA_FD, NETNSA_TARGET_NSID, + NETNSA_CURRENT_NSID, __NETNSA_MAX, }; diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index dd25fb22ad45..2f25d7f2a43b 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -736,6 +736,7 @@ static int rtnl_net_get_size(void) { return NLMSG_ALIGN(sizeof(struct rtgenmsg)) + nla_total_size(sizeof(s32)) /* NETNSA_NSID */ + + nla_total_size(sizeof(s32)) /* NETNSA_CURRENT_NSID */ ; } @@ -745,6 +746,8 @@ struct net_fill_args { int flags; int cmd; int nsid; + bool add_ref; + int ref_nsid; }; static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args) @@ -763,6 +766,10 @@ static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args) if (nla_put_s32(skb, NETNSA_NSID, args->nsid)) goto nla_put_failure; + if (args->add_ref && + nla_put_s32(skb, NETNSA_CURRENT_NSID, args->ref_nsid)) + goto nla_put_failure; + nlmsg_end(skb, nlh); return 0; @@ -782,7 +789,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, .cmd = RTM_NEWNSID, }; struct net *peer, *target = net; - bool put_target = false; struct nlattr *nla; struct sk_buff *msg; int err; @@ -824,7 +830,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, err = PTR_ERR(target); goto out; } - put_target = true; + fillargs.add_ref = true; + fillargs.ref_nsid = peernet2id(net, peer); } msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL); @@ -844,7 +851,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, err_out: nlmsg_free(msg); out: - if (put_target) + if (fillargs.add_ref) put_net(target); put_net(peer); return err; @@ -852,11 +859,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, struct rtnl_net_dump_cb { struct net *tgt_net; + struct net *ref_net; struct sk_buff *skb; struct net_fill_args fillargs; int idx; int s_idx; - bool put_tgt_net; }; static int rtnl_net_dumpid_one(int id, void *peer, void *data) @@ -868,6 +875,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) goto cont; net_cb->fillargs.nsid = id; + if (net_cb->fillargs.add_ref) + net_cb->fillargs.ref_nsid = __peernet2id(net_cb->ref_net, peer); ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs); if (ret < 0) return ret; @@ -904,8 +913,9 @@ static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk, "Invalid target network namespace id"); return PTR_ERR(net); } + net_cb->fillargs.add_ref = true; + net_cb->ref_net = net_cb->tgt_net; net_cb->tgt_net = net; - net_cb->put_tgt_net = true; } else { NL_SET_BAD_ATTR(extack, tb[i]); NL_SET_ERR_MSG(extack, @@ -940,12 +950,21 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) } spin_lock_bh(&net_cb.tgt_net->nsid_lock); + if (net_cb.fillargs.add_ref && + !net_eq(net_cb.ref_net, net_cb.tgt_net) && + !spin_trylock_bh(&net_cb.ref_net->nsid_lock)) { + err = -EAGAIN; + goto end; + } idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb); + if (net_cb.fillargs.add_ref && + !net_eq(net_cb.ref_net, net_cb.tgt_net)) + spin_unlock_bh(&net_cb.ref_net->nsid_lock); spin_unlock_bh(&net_cb.tgt_net->nsid_lock); cb->args[0] = net_cb.idx; end: - if (net_cb.put_tgt_net) + if (net_cb.fillargs.add_ref) put_net(net_cb.tgt_net); return err < 0 ? err : skb->len; } -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table 2018-11-22 22:22 ` [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel @ 2018-11-24 15:47 ` David Ahern 2018-11-26 10:06 ` kbuild test robot 1 sibling, 0 replies; 39+ messages in thread From: David Ahern @ 2018-11-24 15:47 UTC (permalink / raw) To: Nicolas Dichtel; +Cc: netdev, davem On 11/22/18 3:22 PM, Nicolas Dichtel wrote: > Like the previous patch, the goal is to ease to convert nsids from one > netns to another netns. > A new attribute (NETNSA_CURRENT_NSID) is added to the kernel answer when > NETNSA_TARGET_NSID is provided, thus the user can easily convert nsids. > > Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> > --- > include/uapi/linux/net_namespace.h | 1 + > net/core/net_namespace.c | 31 ++++++++++++++++++++++++------ > 2 files changed, 26 insertions(+), 6 deletions(-) > Reviewed-by: David Ahern <dsahern@gmail.com> ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table 2018-11-22 22:22 ` [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel 2018-11-24 15:47 ` David Ahern @ 2018-11-26 10:06 ` kbuild test robot 1 sibling, 0 replies; 39+ messages in thread From: kbuild test robot @ 2018-11-26 10:06 UTC (permalink / raw) To: Nicolas Dichtel; +Cc: kbuild-all, dsahern, netdev, davem, Nicolas Dichtel [-- Attachment #1: Type: text/plain, Size: 4062 bytes --] Hi Nicolas, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on net-next/master] url: https://github.com/0day-ci/linux/commits/Nicolas-Dichtel/netns-remove-net-arg-from-rtnl_net_fill/20181126-035032 config: x86_64-allmodconfig (attached as .config) compiler: gcc-7 (Debian 7.3.0-1) 7.3.0 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All warnings (new ones prefixed by >>): include/linux/slab.h:332:43: warning: dubious: x & !y include/linux/slab.h:332:43: warning: dubious: x & !y >> net/core/net_namespace.c:963:23: warning: context imbalance in 'rtnl_net_dumpid' - different lock contexts for basic block vim +/rtnl_net_dumpid +963 net/core/net_namespace.c 5589651eb Nicolas Dichtel 2018-11-22 929 a143c40c3 Nicolas Dichtel 2015-04-07 930 static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) a143c40c3 Nicolas Dichtel 2015-04-07 931 { a143c40c3 Nicolas Dichtel 2015-04-07 932 struct rtnl_net_dump_cb net_cb = { 5589651eb Nicolas Dichtel 2018-11-22 933 .tgt_net = sock_net(skb->sk), a143c40c3 Nicolas Dichtel 2015-04-07 934 .skb = skb, 70955fc94 Nicolas Dichtel 2018-11-22 935 .fillargs = { 70955fc94 Nicolas Dichtel 2018-11-22 936 .portid = NETLINK_CB(cb->skb).portid, 70955fc94 Nicolas Dichtel 2018-11-22 937 .seq = cb->nlh->nlmsg_seq, 70955fc94 Nicolas Dichtel 2018-11-22 938 .flags = NLM_F_MULTI, 70955fc94 Nicolas Dichtel 2018-11-22 939 .cmd = RTM_NEWNSID, 70955fc94 Nicolas Dichtel 2018-11-22 940 }, a143c40c3 Nicolas Dichtel 2015-04-07 941 .idx = 0, a143c40c3 Nicolas Dichtel 2015-04-07 942 .s_idx = cb->args[0], a143c40c3 Nicolas Dichtel 2015-04-07 943 }; 5589651eb Nicolas Dichtel 2018-11-22 944 int err = 0; a143c40c3 Nicolas Dichtel 2015-04-07 945 5589651eb Nicolas Dichtel 2018-11-22 946 if (cb->strict_check) { 5589651eb Nicolas Dichtel 2018-11-22 947 err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb); 5589651eb Nicolas Dichtel 2018-11-22 948 if (err < 0) 5589651eb Nicolas Dichtel 2018-11-22 949 goto end; f80f14c36 David Ahern 2018-10-07 950 } f80f14c36 David Ahern 2018-10-07 951 5589651eb Nicolas Dichtel 2018-11-22 952 spin_lock_bh(&net_cb.tgt_net->nsid_lock); 8a46e1ccc Nicolas Dichtel 2018-11-22 953 if (net_cb.fillargs.add_ref && 8a46e1ccc Nicolas Dichtel 2018-11-22 954 !net_eq(net_cb.ref_net, net_cb.tgt_net) && 8a46e1ccc Nicolas Dichtel 2018-11-22 955 !spin_trylock_bh(&net_cb.ref_net->nsid_lock)) { 8a46e1ccc Nicolas Dichtel 2018-11-22 956 err = -EAGAIN; 8a46e1ccc Nicolas Dichtel 2018-11-22 957 goto end; 8a46e1ccc Nicolas Dichtel 2018-11-22 958 } 5589651eb Nicolas Dichtel 2018-11-22 959 idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb); 8a46e1ccc Nicolas Dichtel 2018-11-22 960 if (net_cb.fillargs.add_ref && 8a46e1ccc Nicolas Dichtel 2018-11-22 961 !net_eq(net_cb.ref_net, net_cb.tgt_net)) 8a46e1ccc Nicolas Dichtel 2018-11-22 962 spin_unlock_bh(&net_cb.ref_net->nsid_lock); 5589651eb Nicolas Dichtel 2018-11-22 @963 spin_unlock_bh(&net_cb.tgt_net->nsid_lock); a143c40c3 Nicolas Dichtel 2015-04-07 964 a143c40c3 Nicolas Dichtel 2015-04-07 965 cb->args[0] = net_cb.idx; 5589651eb Nicolas Dichtel 2018-11-22 966 end: 8a46e1ccc Nicolas Dichtel 2018-11-22 967 if (net_cb.fillargs.add_ref) 5589651eb Nicolas Dichtel 2018-11-22 968 put_net(net_cb.tgt_net); 5589651eb Nicolas Dichtel 2018-11-22 969 return err < 0 ? err : skb->len; a143c40c3 Nicolas Dichtel 2015-04-07 970 } a143c40c3 Nicolas Dichtel 2015-04-07 971 :::::: The code at line 963 was first introduced by commit :::::: 5589651eb5e06b32107a1d8830af4be67aa58b85 netns: add support of NETNSA_TARGET_NSID :::::: TO: Nicolas Dichtel <nicolas.dichtel@6wind.com> :::::: CC: 0day robot <lkp@intel.com> --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation [-- Attachment #2: .config.gz --] [-- Type: application/gzip, Size: 66610 bytes --] ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v4 0/5] Ease to interpret net-nsid 2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel ` (4 preceding siblings ...) 2018-11-22 22:22 ` [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel @ 2018-11-26 14:42 ` Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel ` (5 more replies) 5 siblings, 6 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-26 14:42 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem The goal of this series is to ease the interpretation of nsid received in netlink messages from other netns (when the user uses NETLINK_F_LISTEN_ALL_NSID). After this series, with a patched iproute2: $ ip netns add foo $ ip netns add bar $ touch /var/run/netns/init_net $ mount --bind /proc/1/ns/net /var/run/netns/init_net $ ip netns set init_net 11 $ ip netns set foo 12 $ ip netns set bar 13 $ ip netns init_net (id: 11) bar (id: 13) foo (id: 12) $ ip -n foo netns set init_net 21 $ ip -n foo netns set foo 22 $ ip -n foo netns set bar 23 $ ip -n foo netns init_net (id: 21) bar (id: 23) foo (id: 22) $ ip -n bar netns set init_net 31 $ ip -n bar netns set foo 32 $ ip -n bar netns set bar 33 $ ip -n bar netns init_net (id: 31) bar (id: 33) foo (id: 32) $ ip netns list-id target-nsid 12 nsid 21 current-nsid 11 (iproute2 netns name: init_net) nsid 22 current-nsid 12 (iproute2 netns name: foo) nsid 23 current-nsid 13 (iproute2 netns name: bar) $ ip -n bar netns list-id target-nsid 32 nsid 31 nsid 21 current-nsid 31 (iproute2 netns name: init_net) v3 -> v4: - patch 5/5: fix imbalance lock in error path v2 -> v3: - patch 5/5: account NETNSA_CURRENT_NSID in rtnl_net_get_size() v1 -> v2: - patch 1/5: remove net from struct rtnl_net_dump_cb - patch 2/5: new in this version - patch 3/5: use a bool to know if rtnl_get_net_ns_capable() was called - patch 5/5: use struct net_fill_args include/uapi/linux/net_namespace.h | 2 + net/core/net_namespace.c | 159 +++++++++++++++++++++++++++++++------ 2 files changed, 135 insertions(+), 26 deletions(-) Comments are welcomed, Regards, Nicolas ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH net-next v4 1/5] netns: remove net arg from rtnl_net_fill() 2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel @ 2018-11-26 14:42 ` Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel ` (4 subsequent siblings) 5 siblings, 0 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-26 14:42 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel This argument is not used anymore. Fixes: cab3c8ec8d57 ("netns: always provide the id to rtnl_net_fill()") Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Reviewed-by: David Ahern <dsahern@gmail.com> --- net/core/net_namespace.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index fefe72774aeb..52b9620e3457 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -739,7 +739,7 @@ static int rtnl_net_get_size(void) } static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, - int cmd, struct net *net, int nsid) + int cmd, int nsid) { struct nlmsghdr *nlh; struct rtgenmsg *rth; @@ -801,7 +801,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, id = peernet2id(net, peer); err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, - RTM_NEWNSID, net, id); + RTM_NEWNSID, id); if (err < 0) goto err_out; @@ -816,7 +816,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, } struct rtnl_net_dump_cb { - struct net *net; struct sk_buff *skb; struct netlink_callback *cb; int idx; @@ -833,7 +832,7 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid, net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI, - RTM_NEWNSID, net_cb->net, id); + RTM_NEWNSID, id); if (ret < 0) return ret; @@ -846,7 +845,6 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) { struct net *net = sock_net(skb->sk); struct rtnl_net_dump_cb net_cb = { - .net = net, .skb = skb, .cb = cb, .idx = 0, @@ -876,7 +874,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id) if (!msg) goto out; - err = rtnl_net_fill(msg, 0, 0, 0, cmd, net, id); + err = rtnl_net_fill(msg, 0, 0, 0, cmd, id); if (err < 0) goto err_out; -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v4 2/5] netns: introduce 'struct net_fill_args' 2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel @ 2018-11-26 14:42 ` Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel ` (3 subsequent siblings) 5 siblings, 0 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-26 14:42 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel This is a preparatory work. To avoid having to much arguments for the function rtnl_net_fill(), a new structure is defined. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Reviewed-by: David Ahern <dsahern@gmail.com> --- net/core/net_namespace.c | 48 ++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 52b9620e3457..f8a5966b086c 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -738,20 +738,28 @@ static int rtnl_net_get_size(void) ; } -static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags, - int cmd, int nsid) +struct net_fill_args { + u32 portid; + u32 seq; + int flags; + int cmd; + int nsid; +}; + +static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args) { struct nlmsghdr *nlh; struct rtgenmsg *rth; - nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rth), flags); + nlh = nlmsg_put(skb, args->portid, args->seq, args->cmd, sizeof(*rth), + args->flags); if (!nlh) return -EMSGSIZE; rth = nlmsg_data(nlh); rth->rtgen_family = AF_UNSPEC; - if (nla_put_s32(skb, NETNSA_NSID, nsid)) + if (nla_put_s32(skb, NETNSA_NSID, args->nsid)) goto nla_put_failure; nlmsg_end(skb, nlh); @@ -767,10 +775,15 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, { struct net *net = sock_net(skb->sk); struct nlattr *tb[NETNSA_MAX + 1]; + struct net_fill_args fillargs = { + .portid = NETLINK_CB(skb).portid, + .seq = nlh->nlmsg_seq, + .cmd = RTM_NEWNSID, + }; struct nlattr *nla; struct sk_buff *msg; struct net *peer; - int err, id; + int err; err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX, rtnl_net_policy, extack); @@ -799,9 +812,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, goto out; } - id = peernet2id(net, peer); - err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, - RTM_NEWNSID, id); + fillargs.nsid = peernet2id(net, peer); + err = rtnl_net_fill(msg, &fillargs); if (err < 0) goto err_out; @@ -817,7 +829,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, struct rtnl_net_dump_cb { struct sk_buff *skb; - struct netlink_callback *cb; + struct net_fill_args fillargs; int idx; int s_idx; }; @@ -830,9 +842,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) if (net_cb->idx < net_cb->s_idx) goto cont; - ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid, - net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI, - RTM_NEWNSID, id); + net_cb->fillargs.nsid = id; + ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs); if (ret < 0) return ret; @@ -846,7 +857,12 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) struct net *net = sock_net(skb->sk); struct rtnl_net_dump_cb net_cb = { .skb = skb, - .cb = cb, + .fillargs = { + .portid = NETLINK_CB(cb->skb).portid, + .seq = cb->nlh->nlmsg_seq, + .flags = NLM_F_MULTI, + .cmd = RTM_NEWNSID, + }, .idx = 0, .s_idx = cb->args[0], }; @@ -867,6 +883,10 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) static void rtnl_net_notifyid(struct net *net, int cmd, int id) { + struct net_fill_args fillargs = { + .cmd = cmd, + .nsid = id, + }; struct sk_buff *msg; int err = -ENOMEM; @@ -874,7 +894,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id) if (!msg) goto out; - err = rtnl_net_fill(msg, 0, 0, 0, cmd, id); + err = rtnl_net_fill(msg, &fillargs); if (err < 0) goto err_out; -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v4 3/5] netns: add support of NETNSA_TARGET_NSID 2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel @ 2018-11-26 14:42 ` Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel ` (2 subsequent siblings) 5 siblings, 0 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-26 14:42 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel Like it was done for link and address, add the ability to perform get/dump in another netns by specifying a target nsid attribute. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Reviewed-by: David Ahern <dsahern@gmail.com> --- include/uapi/linux/net_namespace.h | 1 + net/core/net_namespace.c | 86 ++++++++++++++++++++++++++---- 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h index 0187c74d8889..0ed9dd61d32a 100644 --- a/include/uapi/linux/net_namespace.h +++ b/include/uapi/linux/net_namespace.h @@ -16,6 +16,7 @@ enum { NETNSA_NSID, NETNSA_PID, NETNSA_FD, + NETNSA_TARGET_NSID, __NETNSA_MAX, }; diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index f8a5966b086c..885c54197e31 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -669,6 +669,7 @@ static const struct nla_policy rtnl_net_policy[NETNSA_MAX + 1] = { [NETNSA_NSID] = { .type = NLA_S32 }, [NETNSA_PID] = { .type = NLA_U32 }, [NETNSA_FD] = { .type = NLA_U32 }, + [NETNSA_TARGET_NSID] = { .type = NLA_S32 }, }; static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh, @@ -780,9 +781,10 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, .seq = nlh->nlmsg_seq, .cmd = RTM_NEWNSID, }; + struct net *peer, *target = net; + bool put_target = false; struct nlattr *nla; struct sk_buff *msg; - struct net *peer; int err; err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX, @@ -806,13 +808,27 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, return PTR_ERR(peer); } + if (tb[NETNSA_TARGET_NSID]) { + int id = nla_get_s32(tb[NETNSA_TARGET_NSID]); + + target = rtnl_get_net_ns_capable(NETLINK_CB(skb).sk, id); + if (IS_ERR(target)) { + NL_SET_BAD_ATTR(extack, tb[NETNSA_TARGET_NSID]); + NL_SET_ERR_MSG(extack, + "Target netns reference is invalid"); + err = PTR_ERR(target); + goto out; + } + put_target = true; + } + msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL); if (!msg) { err = -ENOMEM; goto out; } - fillargs.nsid = peernet2id(net, peer); + fillargs.nsid = peernet2id(target, peer); err = rtnl_net_fill(msg, &fillargs); if (err < 0) goto err_out; @@ -823,15 +839,19 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, err_out: nlmsg_free(msg); out: + if (put_target) + put_net(target); put_net(peer); return err; } struct rtnl_net_dump_cb { + struct net *tgt_net; struct sk_buff *skb; struct net_fill_args fillargs; int idx; int s_idx; + bool put_tgt_net; }; static int rtnl_net_dumpid_one(int id, void *peer, void *data) @@ -852,10 +872,50 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) return 0; } +static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk, + struct rtnl_net_dump_cb *net_cb, + struct netlink_callback *cb) +{ + struct netlink_ext_ack *extack = cb->extack; + struct nlattr *tb[NETNSA_MAX + 1]; + int err, i; + + err = nlmsg_parse_strict(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX, + rtnl_net_policy, extack); + if (err < 0) + return err; + + for (i = 0; i <= NETNSA_MAX; i++) { + if (!tb[i]) + continue; + + if (i == NETNSA_TARGET_NSID) { + struct net *net; + + net = rtnl_get_net_ns_capable(sk, nla_get_s32(tb[i])); + if (IS_ERR(net)) { + NL_SET_BAD_ATTR(extack, tb[i]); + NL_SET_ERR_MSG(extack, + "Invalid target network namespace id"); + return PTR_ERR(net); + } + net_cb->tgt_net = net; + net_cb->put_tgt_net = true; + } else { + NL_SET_BAD_ATTR(extack, tb[i]); + NL_SET_ERR_MSG(extack, + "Unsupported attribute in dump request"); + return -EINVAL; + } + } + + return 0; +} + static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) { - struct net *net = sock_net(skb->sk); struct rtnl_net_dump_cb net_cb = { + .tgt_net = sock_net(skb->sk), .skb = skb, .fillargs = { .portid = NETLINK_CB(cb->skb).portid, @@ -866,19 +926,23 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) .idx = 0, .s_idx = cb->args[0], }; + int err = 0; - if (cb->strict_check && - nlmsg_attrlen(cb->nlh, sizeof(struct rtgenmsg))) { - NL_SET_ERR_MSG(cb->extack, "Unknown data in network namespace id dump request"); - return -EINVAL; + if (cb->strict_check) { + err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb); + if (err < 0) + goto end; } - spin_lock_bh(&net->nsid_lock); - idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb); - spin_unlock_bh(&net->nsid_lock); + spin_lock_bh(&net_cb.tgt_net->nsid_lock); + idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb); + spin_unlock_bh(&net_cb.tgt_net->nsid_lock); cb->args[0] = net_cb.idx; - return skb->len; +end: + if (net_cb.put_tgt_net) + put_net(net_cb.tgt_net); + return err < 0 ? err : skb->len; } static void rtnl_net_notifyid(struct net *net, int cmd, int id) -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v4 4/5] netns: enable to specify a nsid for a get request 2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel ` (2 preceding siblings ...) 2018-11-26 14:42 ` [PATCH net-next v4 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel @ 2018-11-26 14:42 ` Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel 2018-11-28 0:20 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid David Miller 5 siblings, 0 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-26 14:42 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel Combined with NETNSA_TARGET_NSID, it enables to "translate" a nsid from one netns to a nsid of another netns. This is useful when using NETLINK_F_LISTEN_ALL_NSID because it helps the user to interpret a nsid received from an other netns. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Reviewed-by: David Ahern <dsahern@gmail.com> --- net/core/net_namespace.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 885c54197e31..dd25fb22ad45 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -797,6 +797,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, } else if (tb[NETNSA_FD]) { peer = get_net_ns_by_fd(nla_get_u32(tb[NETNSA_FD])); nla = tb[NETNSA_FD]; + } else if (tb[NETNSA_NSID]) { + peer = get_net_ns_by_id(net, nla_get_u32(tb[NETNSA_NSID])); + if (!peer) + peer = ERR_PTR(-ENOENT); + nla = tb[NETNSA_NSID]; } else { NL_SET_ERR_MSG(extack, "Peer netns reference is missing"); return -EINVAL; -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH net-next v4 5/5] netns: enable to dump full nsid translation table 2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel ` (3 preceding siblings ...) 2018-11-26 14:42 ` [PATCH net-next v4 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel @ 2018-11-26 14:42 ` Nicolas Dichtel 2018-11-28 0:20 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid David Miller 5 siblings, 0 replies; 39+ messages in thread From: Nicolas Dichtel @ 2018-11-26 14:42 UTC (permalink / raw) To: dsahern; +Cc: netdev, davem, Nicolas Dichtel Like the previous patch, the goal is to ease to convert nsids from one netns to another netns. A new attribute (NETNSA_CURRENT_NSID) is added to the kernel answer when NETNSA_TARGET_NSID is provided, thus the user can easily convert nsids. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Reviewed-by: David Ahern <dsahern@gmail.com> --- include/uapi/linux/net_namespace.h | 1 + net/core/net_namespace.c | 32 ++++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h index 0ed9dd61d32a..9f9956809565 100644 --- a/include/uapi/linux/net_namespace.h +++ b/include/uapi/linux/net_namespace.h @@ -17,6 +17,7 @@ enum { NETNSA_PID, NETNSA_FD, NETNSA_TARGET_NSID, + NETNSA_CURRENT_NSID, __NETNSA_MAX, }; diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index dd25fb22ad45..05b23b285058 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -736,6 +736,7 @@ static int rtnl_net_get_size(void) { return NLMSG_ALIGN(sizeof(struct rtgenmsg)) + nla_total_size(sizeof(s32)) /* NETNSA_NSID */ + + nla_total_size(sizeof(s32)) /* NETNSA_CURRENT_NSID */ ; } @@ -745,6 +746,8 @@ struct net_fill_args { int flags; int cmd; int nsid; + bool add_ref; + int ref_nsid; }; static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args) @@ -763,6 +766,10 @@ static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args) if (nla_put_s32(skb, NETNSA_NSID, args->nsid)) goto nla_put_failure; + if (args->add_ref && + nla_put_s32(skb, NETNSA_CURRENT_NSID, args->ref_nsid)) + goto nla_put_failure; + nlmsg_end(skb, nlh); return 0; @@ -782,7 +789,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, .cmd = RTM_NEWNSID, }; struct net *peer, *target = net; - bool put_target = false; struct nlattr *nla; struct sk_buff *msg; int err; @@ -824,7 +830,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, err = PTR_ERR(target); goto out; } - put_target = true; + fillargs.add_ref = true; + fillargs.ref_nsid = peernet2id(net, peer); } msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL); @@ -844,7 +851,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, err_out: nlmsg_free(msg); out: - if (put_target) + if (fillargs.add_ref) put_net(target); put_net(peer); return err; @@ -852,11 +859,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh, struct rtnl_net_dump_cb { struct net *tgt_net; + struct net *ref_net; struct sk_buff *skb; struct net_fill_args fillargs; int idx; int s_idx; - bool put_tgt_net; }; static int rtnl_net_dumpid_one(int id, void *peer, void *data) @@ -868,6 +875,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data) goto cont; net_cb->fillargs.nsid = id; + if (net_cb->fillargs.add_ref) + net_cb->fillargs.ref_nsid = __peernet2id(net_cb->ref_net, peer); ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs); if (ret < 0) return ret; @@ -904,8 +913,9 @@ static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk, "Invalid target network namespace id"); return PTR_ERR(net); } + net_cb->fillargs.add_ref = true; + net_cb->ref_net = net_cb->tgt_net; net_cb->tgt_net = net; - net_cb->put_tgt_net = true; } else { NL_SET_BAD_ATTR(extack, tb[i]); NL_SET_ERR_MSG(extack, @@ -940,12 +950,22 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) } spin_lock_bh(&net_cb.tgt_net->nsid_lock); + if (net_cb.fillargs.add_ref && + !net_eq(net_cb.ref_net, net_cb.tgt_net) && + !spin_trylock_bh(&net_cb.ref_net->nsid_lock)) { + spin_unlock_bh(&net_cb.tgt_net->nsid_lock); + err = -EAGAIN; + goto end; + } idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb); + if (net_cb.fillargs.add_ref && + !net_eq(net_cb.ref_net, net_cb.tgt_net)) + spin_unlock_bh(&net_cb.ref_net->nsid_lock); spin_unlock_bh(&net_cb.tgt_net->nsid_lock); cb->args[0] = net_cb.idx; end: - if (net_cb.put_tgt_net) + if (net_cb.fillargs.add_ref) put_net(net_cb.tgt_net); return err < 0 ? err : skb->len; } -- 2.18.0 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH net-next v4 0/5] Ease to interpret net-nsid 2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel ` (4 preceding siblings ...) 2018-11-26 14:42 ` [PATCH net-next v4 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel @ 2018-11-28 0:20 ` David Miller 5 siblings, 0 replies; 39+ messages in thread From: David Miller @ 2018-11-28 0:20 UTC (permalink / raw) To: nicolas.dichtel; +Cc: dsahern, netdev From: Nicolas Dichtel <nicolas.dichtel@6wind.com> Date: Mon, 26 Nov 2018 15:42:01 +0100 > > The goal of this series is to ease the interpretation of nsid received in > netlink messages from other netns (when the user uses > NETLINK_F_LISTEN_ALL_NSID). > > After this series, with a patched iproute2: ... > v3 -> v4: > - patch 5/5: fix imbalance lock in error path > > v2 -> v3: > - patch 5/5: account NETNSA_CURRENT_NSID in rtnl_net_get_size() > > v1 -> v2: > - patch 1/5: remove net from struct rtnl_net_dump_cb > - patch 2/5: new in this version > - patch 3/5: use a bool to know if rtnl_get_net_ns_capable() was called > - patch 5/5: use struct net_fill_args Series applied. ^ permalink raw reply [flat|nested] 39+ messages in thread
end of thread, other threads:[~2018-11-28 11:20 UTC | newest] Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-11-21 11:01 [PATCH net-next 0/4] Ease to interpret net-nsid Nicolas Dichtel 2018-11-21 11:01 ` [PATCH net-next 1/4] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel 2018-11-21 11:01 ` [PATCH net-next 2/4] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel 2018-11-21 18:05 ` David Ahern 2018-11-21 20:58 ` Nicolas Dichtel 2018-11-21 21:07 ` David Ahern 2018-11-22 8:06 ` Nicolas Dichtel 2018-11-21 11:01 ` [PATCH net-next 3/4] netns: enable to specify a nsid for a get request Nicolas Dichtel 2018-11-21 11:01 ` [PATCH net-next 4/4] netns: enable to dump full nsid translation table Nicolas Dichtel 2018-11-21 18:09 ` David Ahern 2018-11-21 21:01 ` Nicolas Dichtel 2018-11-21 21:08 ` David Ahern 2018-11-22 15:50 ` [PATCH net-next v2 0/5] Ease to interpret net-nsid Nicolas Dichtel 2018-11-22 15:50 ` [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel 2018-11-22 16:18 ` David Ahern 2018-11-22 15:50 ` [PATCH net-next v2 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel 2018-11-22 16:23 ` David Ahern 2018-11-22 15:50 ` [PATCH net-next v2 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel 2018-11-22 16:32 ` David Ahern 2018-11-22 15:50 ` [PATCH net-next v2 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel 2018-11-22 16:32 ` David Ahern 2018-11-22 15:50 ` [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel 2018-11-22 16:40 ` David Ahern 2018-11-22 16:42 ` Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 0/5] Ease to interpret net-nsid Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel 2018-11-22 22:22 ` [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel 2018-11-24 15:47 ` David Ahern 2018-11-26 10:06 ` kbuild test robot 2018-11-26 14:42 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 1/5] netns: remove net arg from rtnl_net_fill() Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 2/5] netns: introduce 'struct net_fill_args' Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 3/5] netns: add support of NETNSA_TARGET_NSID Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 4/5] netns: enable to specify a nsid for a get request Nicolas Dichtel 2018-11-26 14:42 ` [PATCH net-next v4 5/5] netns: enable to dump full nsid translation table Nicolas Dichtel 2018-11-28 0:20 ` [PATCH net-next v4 0/5] Ease to interpret net-nsid David Miller
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.