[Devel] [PATCH] net: netlink -- Use ifinfomsg in dumping

Kirill Tkhai ktkhai at odin.com
Wed Jun 10 03:17:18 PDT 2015


Porting patch diff-ms-net-netlink-use-ifinfomsg-in-dumping-information-about-interfaces-v2
from 2.6.32:

Newer iproute2 package uses struct ifinfomsg to encode information about ext_filter_mask
(see commit 63338dca45135c85c7f588bd5068e6e77ff816eb in iproute package) but the
kernel is not updated and calculates the data offset incorrectly leading to messages

 | [10424.506841] netlink: 20 bytes leftover after parsing attributes.
 | [10424.506846] netlink: 20 bytes leftover after parsing attributes.
 | [10424.506865] netlink: 20 bytes leftover after parsing attributes.

Introduce compat_parse_size helper which chooses the structure size to be parsed.

Here is an example of request from the iproute2 (ip a)

 | \x28\x00\x00\x00
 | \x12\x00
 | \x01\x03
 | \x7f\xc7\x85\x53
 | \x00\x00\x00\x00
 | \x00
 | \x00
 | \x00\x00
 | \x00\x00\x00\x00
 | \x00\x00\x00\x00
 | \x00\x00\x00\x00
 | \x08\x00\x1d\x00\x01\x00\x00\x00
 |
 | struct nlmsghdr {
 |	__u32		nlmsg_len;				-> \x28\x00\x00\x00	(40)
 |	__u16		nlmsg_type;				-> \x12\x00		(18 - RTM_GETLINK)
 |	__u16		nlmsg_flags;				-> \x01\x03		(NLM_F_REQUEST | NLM_F_DUMP)
 |	__u32		nlmsg_seq;				-> \x13\x89\x85\x53
 |	__u32		nlmsg_pid;				-> \x00\x00\x00\x00
 | }
 |
 | struct ifinfomsg {
 |	unsigned char	ifi_family;				-> \x00
 |	unsigned char	__ifi_pad;				-> \x00
 |	unsigned short	ifi_type;				-> \x00\x00
 |	int		ifi_index;				-> \x00\x00\x00\x00
 |	unsigned	ifi_flags;				-> \x00\x00\x00\x00
 |	unsigned	ifi_change;				-> \x00\x00\x00\x00
 | };

https://jira.sw.ru/browse/PSBM-26757

v2: Actually there is a serious flawn in handling the netlink packets
    when fetching information about interfaces -- the @tb array allocated
    on the stack and (!) nlmsg_parse is not tested for error code thus
    it might leave unitialized if nlmsg_parse exit early (I already
    hit #GP once). So fix this problem at once.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
Acked-by: Kirill Tkhai <ktkhai at parallels.com>

Note: the problem, which is described in v2 paragraph, has gone, because
the code checks for nlmsg_parse() retval now.

Made in scope of https://jira.sw.ru/browse/PSBM-33645

Signed-off-by: Kirill Tkhai <ktkhai at odin.com>
---
 net/core/rtnetlink.c |   16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 40f13c1..d97abba 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1124,6 +1124,18 @@ static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = {
 	[IFLA_PORT_RESPONSE]	= { .type = NLA_U16, },
 };
 
+/*
+ * New iproute2 user-space tool send requests in struct ifinfomsg format,
+ * while old ones use struct rtgenmsg. So guess which one is passed depending
+ * on the payload size.
+ */
+static int compat_parse_size(const struct nlmsghdr *nlh)
+{
+	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(struct ifinfomsg)))
+		return sizeof(struct rtgenmsg);
+	return sizeof(struct ifinfomsg);
+}
+
 static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 {
 	struct net *net = sock_net(skb->sk);
@@ -1140,7 +1152,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 	rcu_read_lock();
 	cb->seq = net->dev_base_seq;
 
-	if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
+	if (nlmsg_parse(cb->nlh, compat_parse_size(cb->nlh), tb, IFLA_MAX,
 			ifla_policy) >= 0) {
 
 		if (tb[IFLA_EXT_MASK])
@@ -1943,7 +1955,7 @@ static u16 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh)
 	u32 ext_filter_mask = 0;
 	u16 min_ifinfo_dump_size = 0;
 
-	if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
+	if (nlmsg_parse(nlh, compat_parse_size(nlh), tb, IFLA_MAX,
 			ifla_policy) >= 0) {
 		if (tb[IFLA_EXT_MASK])
 			ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);




More information about the Devel mailing list