diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/netfilter/ebtables.c | 70 |
1 files changed, 38 insertions, 32 deletions
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index a707dbdc0327..46030dc90845 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -33,11 +33,6 @@ | |||
33 | #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\ | 33 | #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\ |
34 | "report to author: "format, ## args) | 34 | "report to author: "format, ## args) |
35 | /* #define BUGPRINT(format, args...) */ | 35 | /* #define BUGPRINT(format, args...) */ |
36 | #define MEMPRINT(format, args...) printk("kernel msg: ebtables "\ | ||
37 | ": out of memory: "format, ## args) | ||
38 | /* #define MEMPRINT(format, args...) */ | ||
39 | |||
40 | |||
41 | 36 | ||
42 | /* | 37 | /* |
43 | * Each cpu has its own set of counters, so there is no need for write_lock in | 38 | * Each cpu has its own set of counters, so there is no need for write_lock in |
@@ -1263,10 +1258,8 @@ static int update_counters(struct net *net, const void __user *user, | |||
1263 | if (hlp.num_counters == 0) | 1258 | if (hlp.num_counters == 0) |
1264 | return -EINVAL; | 1259 | return -EINVAL; |
1265 | 1260 | ||
1266 | if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) { | 1261 | if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) |
1267 | MEMPRINT("Update_counters && nomemory\n"); | ||
1268 | return -ENOMEM; | 1262 | return -ENOMEM; |
1269 | } | ||
1270 | 1263 | ||
1271 | t = find_table_lock(net, hlp.name, &ret, &ebt_mutex); | 1264 | t = find_table_lock(net, hlp.name, &ret, &ebt_mutex); |
1272 | if (!t) | 1265 | if (!t) |
@@ -1345,14 +1338,46 @@ ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase) | |||
1345 | return 0; | 1338 | return 0; |
1346 | } | 1339 | } |
1347 | 1340 | ||
1341 | static int copy_counters_to_user(struct ebt_table *t, | ||
1342 | const struct ebt_counter *oldcounters, | ||
1343 | void __user *user, unsigned int num_counters, | ||
1344 | unsigned int nentries) | ||
1345 | { | ||
1346 | struct ebt_counter *counterstmp; | ||
1347 | int ret = 0; | ||
1348 | |||
1349 | /* userspace might not need the counters */ | ||
1350 | if (num_counters == 0) | ||
1351 | return 0; | ||
1352 | |||
1353 | if (num_counters != nentries) { | ||
1354 | BUGPRINT("Num_counters wrong\n"); | ||
1355 | return -EINVAL; | ||
1356 | } | ||
1357 | |||
1358 | counterstmp = vmalloc(nentries * sizeof(*counterstmp)); | ||
1359 | if (!counterstmp) | ||
1360 | return -ENOMEM; | ||
1361 | |||
1362 | write_lock_bh(&t->lock); | ||
1363 | get_counters(oldcounters, counterstmp, nentries); | ||
1364 | write_unlock_bh(&t->lock); | ||
1365 | |||
1366 | if (copy_to_user(user, counterstmp, | ||
1367 | nentries * sizeof(struct ebt_counter))) | ||
1368 | ret = -EFAULT; | ||
1369 | vfree(counterstmp); | ||
1370 | return ret; | ||
1371 | } | ||
1372 | |||
1348 | /* called with ebt_mutex locked */ | 1373 | /* called with ebt_mutex locked */ |
1349 | static int copy_everything_to_user(struct ebt_table *t, void __user *user, | 1374 | static int copy_everything_to_user(struct ebt_table *t, void __user *user, |
1350 | const int *len, int cmd) | 1375 | const int *len, int cmd) |
1351 | { | 1376 | { |
1352 | struct ebt_replace tmp; | 1377 | struct ebt_replace tmp; |
1353 | struct ebt_counter *counterstmp; | ||
1354 | const struct ebt_counter *oldcounters; | 1378 | const struct ebt_counter *oldcounters; |
1355 | unsigned int entries_size, nentries; | 1379 | unsigned int entries_size, nentries; |
1380 | int ret; | ||
1356 | char *entries; | 1381 | char *entries; |
1357 | 1382 | ||
1358 | if (cmd == EBT_SO_GET_ENTRIES) { | 1383 | if (cmd == EBT_SO_GET_ENTRIES) { |
@@ -1388,29 +1413,10 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user, | |||
1388 | return -EINVAL; | 1413 | return -EINVAL; |
1389 | } | 1414 | } |
1390 | 1415 | ||
1391 | /* userspace might not need the counters */ | 1416 | ret = copy_counters_to_user(t, oldcounters, tmp.counters, |
1392 | if (tmp.num_counters) { | 1417 | tmp.num_counters, nentries); |
1393 | if (tmp.num_counters != nentries) { | 1418 | if (ret) |
1394 | BUGPRINT("Num_counters wrong\n"); | 1419 | return ret; |
1395 | return -EINVAL; | ||
1396 | } | ||
1397 | counterstmp = vmalloc(nentries * sizeof(*counterstmp)); | ||
1398 | if (!counterstmp) { | ||
1399 | MEMPRINT("Couldn't copy counters, out of memory\n"); | ||
1400 | return -ENOMEM; | ||
1401 | } | ||
1402 | write_lock_bh(&t->lock); | ||
1403 | get_counters(oldcounters, counterstmp, nentries); | ||
1404 | write_unlock_bh(&t->lock); | ||
1405 | |||
1406 | if (copy_to_user(tmp.counters, counterstmp, | ||
1407 | nentries * sizeof(struct ebt_counter))) { | ||
1408 | BUGPRINT("Couldn't copy counters to userspace\n"); | ||
1409 | vfree(counterstmp); | ||
1410 | return -EFAULT; | ||
1411 | } | ||
1412 | vfree(counterstmp); | ||
1413 | } | ||
1414 | 1420 | ||
1415 | if (copy_to_user(tmp.entries, entries, entries_size)) { | 1421 | if (copy_to_user(tmp.entries, entries, entries_size)) { |
1416 | BUGPRINT("Couldn't copy entries to userspace\n"); | 1422 | BUGPRINT("Couldn't copy entries to userspace\n"); |