| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 |
- 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]>
- ---
- net/core/gen_stats.c | 16 ++++++++++++++--
- 1 file changed, 14 insertions(+), 2 deletions(-)
- --- a/net/core/gen_stats.c
- +++ b/net/core/gen_stats.c
- @@ -77,8 +77,20 @@ gnet_stats_start_copy_compat(struct sk_b
- 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;
- }
|