Skip to content

Commit

Permalink
gen_stats: Fix netlink stats dumping in the presence of padding
Browse files Browse the repository at this point in the history
The gen_stats facility will add a header for the toplevel nlattr of type
TCA_STATS2 that contains all stats added by qdisc callbacks. A reference
to this header is stored in the gnet_dump struct, and when all the
per-qdisc callbacks have finished adding their stats, the length of the
containing header will be adjusted to the right value.

However, on architectures that need padding (i.e., that don't set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), the padding nlattr is added
before the stats, which means that the stored pointer will point to the
padding, and so when the header is fixed up, the result is just a very
big padding nlattr. Because most qdiscs also supply the legacy TCA_STATS
struct, this problem has been mostly invisible, but we exposed it with
the netlink attribute-based statistics in CAKE.

Fix the issue by fixing up the stored pointer if it points to a padding
nlattr.

Tested-by: Pete Heist <[email protected]>
Tested-by: Kevin Darbyshire-Bryant <[email protected]>
Signed-off-by: Toke Høiland-Jørgensen <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
tohojo authored and davem330 committed Jul 4, 2018
1 parent 0777724 commit d5a672a
Showing 1 changed file with 14 additions and 2 deletions.
16 changes: 14 additions & 2 deletions net/core/gen_stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,20 @@ gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type,
d->lock = lock;
spin_lock_bh(lock);
}
if (d->tail)
return gnet_stats_copy(d, type, NULL, 0, padattr);
if (d->tail) {
int ret = gnet_stats_copy(d, type, NULL, 0, padattr);

/* The initial attribute added in gnet_stats_copy() may be
* preceded by a padding attribute, in which case d->tail will
* end up pointing at the padding instead of the real attribute.
* Fix this so gnet_stats_finish_copy() adjusts the length of
* the right attribute.
*/
if (ret == 0 && d->tail->nla_type == padattr)
d->tail = (struct nlattr *)((char *)d->tail +
NLA_ALIGN(d->tail->nla_len));
return ret;
}

return 0;
}
Expand Down

0 comments on commit d5a672a

Please sign in to comment.