From bb2f97e6636aab7eca08fbc02a144d0f65326947 Mon Sep 17 00:00:00 2001 From: Andrew Vagin Date: Wed, 16 Mar 2016 08:06:00 +0300 Subject: [PATCH] libnetlink: back port a fix for nlattr_parse() The bug was fixed in libnl-3 3.2.24, but rhel7 and the Trusty ubuntu don't update this packet yet commit b50a36bf34e7452377ab9bbb4d1873b68c65bf72 Author: Samuel Gauthier Date: Fri Nov 29 09:28:44 2013 +0100 The commit 6a8d90f5fec4 "attr: Allow attribute type 0" intended to allow the parsing of {netlink,packet,unix}_diag, even if they are using type 0 for valid attributes. It lacked this part in nla_parse. Cc: Nicolas Dichtel Signed-off-by: Samuel Gauthier Signed-off-by: Thomas Graf Fixes #137 Signed-off-by: Andrew Vagin Acked-by: Cyrill Gorcunov Signed-off-by: Pavel Emelyanov --- criu/Makefile | 4 +++ criu/libnetlink.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/criu/Makefile b/criu/Makefile index 575d7e475..25d75dfd7 100644 --- a/criu/Makefile +++ b/criu/Makefile @@ -6,6 +6,10 @@ HOSTLD ?= ld HOSTCFLAGS ?= $(CFLAGS) CFLAGS += $(USERCFLAGS) +# here is a workaround for a bug in libnl-3: +# 6a8d90f5fec4 "attr: Allow attribute type 0" +LDFLAGS += -Wl,--wrap=nla_parse,--wrap=nlmsg_parse + export HOSTCC HOSTLD HOSTCFLAGS ifeq ($(ARCH),x86) diff --git a/criu/libnetlink.c b/criu/libnetlink.c index 4a651cbd1..5f69a3d66 100644 --- a/criu/libnetlink.c +++ b/criu/libnetlink.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -146,3 +147,74 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); return 0; } + +/* + * Here is a workaround for a bug in libnl-3: + * 6a8d90f5fec4 "attr: Allow attribute type 0 + */ + +/** + * Create attribute index based on a stream of attributes. + * @arg tb Index array to be filled (maxtype+1 elements). + * @arg maxtype Maximum attribute type expected and accepted. + * @arg head Head of attribute stream. + * @arg len Length of attribute stream. + * @arg policy Attribute validation policy. + * + * Iterates over the stream of attributes and stores a pointer to each + * attribute in the index array using the attribute type as index to + * the array. Attribute with a type greater than the maximum type + * specified will be silently ignored in order to maintain backwards + * compatibility. If \a policy is not NULL, the attribute will be + * validated using the specified policy. + * + * @see nla_validate + * @return 0 on success or a negative error code. + */ +int __wrap_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, + struct nla_policy *policy) +{ + struct nlattr *nla; + int rem; + + memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); + + nla_for_each_attr(nla, head, len, rem) { + int type = nla_type(nla); + + if (type > maxtype) + continue; + + if (tb[type]) + pr_warn("Attribute of type %#x found multiple times in message, " + "previous attribute is being ignored.\n", type); + + tb[type] = nla; + } + + if (rem > 0) + pr_warn("netlink: %d bytes leftover after parsing " + "attributes.\n", rem); + + return 0; +} + +/** + * parse attributes of a netlink message + * @arg nlh netlink message header + * @arg hdrlen length of family specific header + * @arg tb destination array with maxtype+1 elements + * @arg maxtype maximum attribute type to be expected + * @arg policy validation policy + * + * See nla_parse() + */ +int __wrap_nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], + int maxtype, struct nla_policy *policy) +{ + if (!nlmsg_valid_hdr(nlh, hdrlen)) + return -NLE_MSG_TOOSHORT; + + return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen), + nlmsg_attrlen(nlh, hdrlen), policy); +}