lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 18 Jan 2018 21:21:24 +0100
From:   Christian Brauner <christian.brauner@...ntu.com>
To:     davem@...emloft.net, dsahern@...il.com, fw@...len.de,
        daniel@...earbox.net, lucien.xin@...il.com,
        mschiffer@...verse-factory.net, jakub.kicinski@...ronome.com,
        vyasevich@...il.com, jbenc@...hat.com, netdev@...r.kernel.org,
        linux-kernel@...r.kernel.org
Cc:     Christian Brauner <christian.brauner@...ntu.com>
Subject: [PATCH net-next 1/1] rtnetlink: request RTM_GETLINK by pid or fd

This makes it possible to identify the target network namespace of a
RTM_GETLINK message by pid or fd.
Often userspace tools that make heavy use of network namespaces need a
simple and cheap way of querying network devices and network device
properties. This becomes even more crucial when the network namespaces in
question are transient. In such scenarios setting a netns id property is
not really wanted and it is preferable to avoid the hit of (possibly
multiple) setns() syscalls (e.g. attaching to the target network namespace
and back to the original network namespace.). This commit lets userspace
set the IFLA_NET_NS_{FD,PID} property to identify a target network
namespace where the device in question is to be queried.

Signed-off-by: Christian Brauner <christian.brauner@...ntu.com>
---
 net/core/rtnetlink.c | 63 +++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 50 insertions(+), 13 deletions(-)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 16d644a4f974..5210448dcf1f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1509,7 +1509,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
 			    struct net_device *dev, struct net *src_net,
 			    int type, u32 pid, u32 seq, u32 change,
 			    unsigned int flags, u32 ext_filter_mask,
-			    u32 event, int *new_nsid, int tgt_netnsid)
+			    u32 event, int *new_nsid, int tgt_netnsid,
+			    int tgt_netnsid_type)
 {
 	struct ifinfomsg *ifm;
 	struct nlmsghdr *nlh;
@@ -1527,8 +1528,23 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
 	ifm->ifi_flags = dev_get_flags(dev);
 	ifm->ifi_change = change;
 
-	if (tgt_netnsid >= 0 && nla_put_s32(skb, IFLA_IF_NETNSID, tgt_netnsid))
-		goto nla_put_failure;
+	if (tgt_netnsid >= 0) {
+		u32 err = -1;
+
+		switch (tgt_netnsid_type) {
+		case IFLA_IF_NETNSID:
+			err = nla_put_s32(skb, IFLA_IF_NETNSID, tgt_netnsid);
+			break;
+		case IFLA_NET_NS_PID:
+			err = nla_put_s32(skb, IFLA_NET_NS_PID, tgt_netnsid);
+			break;
+		case IFLA_NET_NS_FD:
+			err = nla_put_s32(skb, IFLA_NET_NS_FD, tgt_netnsid);
+			break;
+		}
+		if (err)
+			goto nla_put_failure;
+	}
 
 	if (nla_put_string(skb, IFLA_IFNAME, dev->name) ||
 	    nla_put_u32(skb, IFLA_TXQLEN, dev->tx_queue_len) ||
@@ -1791,6 +1807,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 	unsigned int flags = NLM_F_MULTI;
 	int master_idx = 0;
 	int netnsid = -1;
+	int netnsid_type = -1;
 	int err;
 	int hdrlen;
 
@@ -1810,12 +1827,22 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 	if (nlmsg_parse(cb->nlh, hdrlen, tb, IFLA_MAX,
 			ifla_policy, NULL) >= 0) {
 		if (tb[IFLA_IF_NETNSID]) {
+			netnsid_type = IFLA_IF_NETNSID;
 			netnsid = nla_get_s32(tb[IFLA_IF_NETNSID]);
 			tgt_net = get_target_net(skb->sk, netnsid);
-			if (IS_ERR(tgt_net)) {
-				tgt_net = net;
-				netnsid = -1;
-			}
+		} else if (tb[IFLA_NET_NS_PID]) {
+			netnsid_type = IFLA_NET_NS_PID;
+			netnsid = nla_get_s32(tb[IFLA_NET_NS_PID]);
+			tgt_net = get_net_ns_by_pid(netnsid);
+		} else if (tb[IFLA_NET_NS_FD]) {
+			netnsid_type = IFLA_NET_NS_FD;
+			netnsid = nla_get_s32(tb[IFLA_NET_NS_FD]);
+			tgt_net = get_net_ns_by_fd(netnsid);
+		}
+		if (IS_ERR(tgt_net)) {
+			tgt_net = net;
+			netnsid = -1;
+			netnsid_type = -1;
 		}
 
 		if (tb[IFLA_EXT_MASK])
@@ -1845,7 +1872,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 					       cb->nlh->nlmsg_seq, 0,
 					       flags,
 					       ext_filter_mask, 0, NULL,
-					       netnsid);
+					       netnsid, netnsid_type);
 
 			if (err < 0) {
 				if (likely(skb->len))
@@ -2984,6 +3011,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct net_device *dev = NULL;
 	struct sk_buff *nskb;
 	int netnsid = -1;
+	int netnsid_type = -1;
 	int err;
 	u32 ext_filter_mask = 0;
 
@@ -2992,11 +3020,20 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
 		return err;
 
 	if (tb[IFLA_IF_NETNSID]) {
+		netnsid_type = IFLA_IF_NETNSID;
 		netnsid = nla_get_s32(tb[IFLA_IF_NETNSID]);
 		tgt_net = get_target_net(NETLINK_CB(skb).sk, netnsid);
-		if (IS_ERR(tgt_net))
-			return PTR_ERR(tgt_net);
-	}
+	} else if (tb[IFLA_NET_NS_PID]) {
+		netnsid_type = IFLA_NET_NS_PID;
+		netnsid = nla_get_s32(tb[IFLA_NET_NS_PID]);
+		tgt_net = get_net_ns_by_pid(netnsid);
+	} else if (tb[IFLA_NET_NS_FD]) {
+		netnsid_type = IFLA_NET_NS_FD;
+		netnsid = nla_get_s32(tb[IFLA_NET_NS_FD]);
+		tgt_net = get_net_ns_by_fd(netnsid);
+	}
+	if (IS_ERR(tgt_net))
+		return PTR_ERR(tgt_net);
 
 	if (tb[IFLA_IFNAME])
 		nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
@@ -3025,7 +3062,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
 	err = rtnl_fill_ifinfo(nskb, dev, net,
 			       RTM_NEWLINK, NETLINK_CB(skb).portid,
 			       nlh->nlmsg_seq, 0, 0, ext_filter_mask,
-			       0, NULL, netnsid);
+			       0, NULL, netnsid, netnsid_type);
 	if (err < 0) {
 		/* -EMSGSIZE implies BUG in if_nlmsg_size */
 		WARN_ON(err == -EMSGSIZE);
@@ -3134,7 +3171,7 @@ struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
 
 	err = rtnl_fill_ifinfo(skb, dev, dev_net(dev),
 			       type, 0, 0, change, 0, 0, event,
-			       new_nsid, -1);
+			       new_nsid, -1, -1);
 	if (err < 0) {
 		/* -EMSGSIZE implies BUG in if_nlmsg_size() */
 		WARN_ON(err == -EMSGSIZE);
-- 
2.14.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ