Skip to content

Commit

Permalink
netlink: Refine calculation of maximum-length attributes.
Browse files Browse the repository at this point in the history
Until now the Netlink code has considered an attribute to exceed the
maximum length if the *padded* size of the attribute exceeds 65535 bytes.
For example, an attribute with a 65529-byte payload, together with 4-byte
header and 3 bytes of padding, takes up 65536 bytes and therefore the
existing code rejected it.

However, the restriction on Netlink attribute sizes is to ensure that the
length fits in the 16-bit nla_len field.  This field includes the 4-byte
header but not the padding, so a 65529-byte payload is acceptable because,
with the header but not the padding, it comes to only 65533 bytes.

Thus, this commit relaxes the restriction on Netlink attribute sizes by
omitting padding from size checks.  It also changes one piece of code that
inlined a size check to use the central function nl_attr_oversized().

This change should fix an assertion failure when OVS userspace passes a
maximum-size (65529+ byte) packet back to the kernel.

Reported-by: Shuping Cui <[email protected]>
Reported-by: Jiri Benc <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
Acked-by: Jesse Gross <[email protected]>
  • Loading branch information
blp committed Jan 11, 2015
1 parent 1808054 commit 9149630
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 5 deletions.
6 changes: 3 additions & 3 deletions lib/netlink.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -214,7 +214,7 @@ nl_msg_put_unspec_uninit(struct ofpbuf *msg, uint16_t type, size_t size)
{
size_t total_size = NLA_HDRLEN + size;
struct nlattr* nla = nl_msg_put_uninit(msg, total_size);
ovs_assert(NLA_ALIGN(total_size) <= UINT16_MAX);
ovs_assert(!nl_attr_oversized(size));
nla->nla_len = total_size;
nla->nla_type = type;
return nla + 1;
Expand Down Expand Up @@ -489,7 +489,7 @@ nl_msg_next(struct ofpbuf *buffer, struct ofpbuf *msg)
bool
nl_attr_oversized(size_t payload_size)
{
return NL_ATTR_SIZE(payload_size) > UINT16_MAX;
return payload_size > UINT16_MAX - NLA_HDRLEN;
}

/* Attributes. */
Expand Down
11 changes: 9 additions & 2 deletions lib/netlink.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2009, 2010, 2011, 2013 Nicira, Inc.
* Copyright (c) 2008, 2009, 2010, 2011, 2013, 2015 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -94,7 +94,14 @@ void nl_msg_push_string(struct ofpbuf *, uint16_t type, const char *value);
struct nlmsghdr *nl_msg_next(struct ofpbuf *buffer, struct ofpbuf *msg);

/* Sizes of various attribute types, in bytes, including the attribute header
* and padding. */
* and padding.
*
* A minimum-size attribute is 4 bytes long: 4 bytes of header, no bytes of
* payload, no padding.
*
* A maximum-size attribute is 65536 bytes long: 4 bytes of header, 65531 bytes
* of payload, 1 byte of padding. (Thus, NL_ATTR_SIZE() of a maximum length
* attribute payload does not fit in 16 bits.) */
#define NL_ATTR_SIZE(PAYLOAD_SIZE) (NLA_HDRLEN + NLA_ALIGN(PAYLOAD_SIZE))
#define NL_A_U8_SIZE NL_ATTR_SIZE(sizeof(uint8_t))
#define NL_A_U16_SIZE NL_ATTR_SIZE(sizeof(uint16_t))
Expand Down

0 comments on commit 9149630

Please sign in to comment.