diff options
| author | Ignacy Gawędzki <ignacy.gawedzki@green-communications.fr> | 2015-02-13 17:47:05 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-02-19 15:45:53 -0500 |
| commit | 1c4cff0cf55011792125b6041bc4e9713e46240f (patch) | |
| tree | ecc9dc4e465d69c6e6afff06c6a473af7a6cc65a /net | |
| parent | 5c2770079fb9b8c5bfb7113d9e76de66e77a0e24 (diff) | |
gen_stats.c: Duplicate xstats buffer for later use
The gnet_stats_copy_app() function gets called, more often than not, with its
second argument a pointer to an automatic variable in the caller's stack.
Therefore, to avoid copying garbage afterwards when calling
gnet_stats_finish_copy(), this data is better copied to a dynamically allocated
memory that gets freed after use.
[xiyou.wangcong@gmail.com: remove a useless kfree()]
Signed-off-by: Ignacy Gawędzki <ignacy.gawedzki@green-communications.fr>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
| -rw-r--r-- | net/core/gen_stats.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c index 0c08062d1796..1e2f46a69d50 100644 --- a/net/core/gen_stats.c +++ b/net/core/gen_stats.c | |||
| @@ -32,6 +32,9 @@ gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size) | |||
| 32 | return 0; | 32 | return 0; |
| 33 | 33 | ||
| 34 | nla_put_failure: | 34 | nla_put_failure: |
| 35 | kfree(d->xstats); | ||
| 36 | d->xstats = NULL; | ||
| 37 | d->xstats_len = 0; | ||
| 35 | spin_unlock_bh(d->lock); | 38 | spin_unlock_bh(d->lock); |
| 36 | return -1; | 39 | return -1; |
| 37 | } | 40 | } |
| @@ -305,7 +308,9 @@ int | |||
| 305 | gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) | 308 | gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) |
| 306 | { | 309 | { |
| 307 | if (d->compat_xstats) { | 310 | if (d->compat_xstats) { |
| 308 | d->xstats = st; | 311 | d->xstats = kmemdup(st, len, GFP_ATOMIC); |
| 312 | if (!d->xstats) | ||
| 313 | goto err_out; | ||
| 309 | d->xstats_len = len; | 314 | d->xstats_len = len; |
| 310 | } | 315 | } |
| 311 | 316 | ||
| @@ -313,6 +318,11 @@ gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) | |||
| 313 | return gnet_stats_copy(d, TCA_STATS_APP, st, len); | 318 | return gnet_stats_copy(d, TCA_STATS_APP, st, len); |
| 314 | 319 | ||
| 315 | return 0; | 320 | return 0; |
| 321 | |||
| 322 | err_out: | ||
| 323 | d->xstats_len = 0; | ||
| 324 | spin_unlock_bh(d->lock); | ||
| 325 | return -1; | ||
| 316 | } | 326 | } |
| 317 | EXPORT_SYMBOL(gnet_stats_copy_app); | 327 | EXPORT_SYMBOL(gnet_stats_copy_app); |
| 318 | 328 | ||
| @@ -345,6 +355,9 @@ gnet_stats_finish_copy(struct gnet_dump *d) | |||
| 345 | return -1; | 355 | return -1; |
| 346 | } | 356 | } |
| 347 | 357 | ||
| 358 | kfree(d->xstats); | ||
| 359 | d->xstats = NULL; | ||
| 360 | d->xstats_len = 0; | ||
| 348 | spin_unlock_bh(d->lock); | 361 | spin_unlock_bh(d->lock); |
| 349 | return 0; | 362 | return 0; |
| 350 | } | 363 | } |
