aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorIgnacy Gawędzki <ignacy.gawedzki@green-communications.fr>2015-02-13 17:47:05 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-19 15:45:53 -0500
commit1c4cff0cf55011792125b6041bc4e9713e46240f (patch)
treeecc9dc4e465d69c6e6afff06c6a473af7a6cc65a /net
parent5c2770079fb9b8c5bfb7113d9e76de66e77a0e24 (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.c15
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
34nla_put_failure: 34nla_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
305gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) 308gnet_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
322err_out:
323 d->xstats_len = 0;
324 spin_unlock_bh(d->lock);
325 return -1;
316} 326}
317EXPORT_SYMBOL(gnet_stats_copy_app); 327EXPORT_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}