[PATCH] lib: Return error on Netlink attribute length overflow

Przemyslaw Szczerbik przemekszczerbik at gmail.com
Mon May 30 14:26:00 PDT 2016


Netlink attribute length is defined as u16. It's possible to exceed nla_len when
creating nested attributes. Storing incorrect length due to overflow will cause
a reader to read only a part of nested attribute or skip it entirely.

As a solution cancel the addition of a nested attribute when nla_len size is
exceeded.

Signed-off-by: Przemyslaw Szczerbik <przemek.szczerbik at gmail.com>
---
 include/netlink/errno.h | 3 ++-
 lib/attr.c              | 9 +++++----
 lib/error.c             | 1 +
 3 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/include/netlink/errno.h b/include/netlink/errno.h
index f8b5130..35710cf 100644
--- a/include/netlink/errno.h
+++ b/include/netlink/errno.h
@@ -50,8 +50,9 @@ extern "C" {
 #define NLE_NODEV		31
 #define NLE_IMMUTABLE		32
 #define NLE_DUMP_INTR		33
+#define NLE_ATTRSIZE		34
 
-#define NLE_MAX			NLE_DUMP_INTR
+#define NLE_MAX		NLE_ATTRSIZE
 
 extern const char *	nl_geterror(int);
 extern void		nl_perror(int, const char *);
diff --git a/lib/attr.c b/lib/attr.c
index 9d8bb26..a3d1b16 100644
--- a/lib/attr.c
+++ b/lib/attr.c
@@ -912,7 +912,7 @@ struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype)
  *
  * Corrects the container attribute header to include the appeneded attributes.
  *
- * @return 0
+ * @return 0 on success or a negative error code.
  */
 int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
 {
@@ -920,14 +920,15 @@ int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
 
 	len = (void *) nlmsg_tail(msg->nm_nlh) - (void *) start;
 
-	if (len == NLA_HDRLEN) {
+	if (len == NLA_HDRLEN || len > USHRT_MAX) {
 		/*
-		 * Kernel can't handle empty nested attributes, trim the
+		 * Max nlattr size exceeded or empty nested attribute, trim the
 		 * attribute header again
 		 */
 		nla_nest_cancel(msg, start);
 
-		return 0;
+		/* Return error only if nlattr size was exceeded */
+		return (len == NLA_HDRLEN) ? 0 : -NLE_ATTRSIZE;
 	}
 
 	start->nla_len = len;
diff --git a/lib/error.c b/lib/error.c
index f30b9a5..7fbd389 100644
--- a/lib/error.c
+++ b/lib/error.c
@@ -47,6 +47,7 @@ static const char *errmsg[NLE_MAX+1] = {
 [NLE_NODEV]		= "No such device",
 [NLE_IMMUTABLE]		= "Immutable attribute",
 [NLE_DUMP_INTR]		= "Dump inconsistency detected, interrupted",
+[NLE_ATTRSIZE]		= "Attribute max length exceeded",
 };
 
 /**
-- 
2.7.4




More information about the libnl mailing list