[Devel] [PATCH RHEL7 COMMIT] ms/net: netlink -- Use ifinfomsg in dumping
Konstantin Khorenko
khorenko at virtuozzo.com
Wed Jun 17 01:47:58 PDT 2015
The commit is pushed to "branch-rh7-3.10.0-123.1.2-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-123.1.2.vz7.5.14
------>
commit 19eaf0d1aa8e5e6e50d4c8205e59a3b94491b165
Author: Kirill Tkhai <ktkhai at odin.com>
Date: Wed Jun 17 12:47:58 2015 +0400
ms/net: netlink -- Use ifinfomsg in dumping
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>
Acked-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
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