aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/bridge/netfilter/ebtables.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index fcaefdd6200b..dfb58056a89a 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1428,16 +1428,12 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1428 oldcounters = t->table->counters; 1428 oldcounters = t->table->counters;
1429 } 1429 }
1430 1430
1431 if (copy_from_user(&tmp, user, sizeof(tmp))) { 1431 if (copy_from_user(&tmp, user, sizeof(tmp)))
1432 BUGPRINT("Cfu didn't work\n");
1433 return -EFAULT; 1432 return -EFAULT;
1434 }
1435 1433
1436 if (*len != sizeof(struct ebt_replace) + entries_size + 1434 if (*len != sizeof(struct ebt_replace) + entries_size +
1437 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) { 1435 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0))
1438 BUGPRINT("Wrong size\n");
1439 return -EINVAL; 1436 return -EINVAL;
1440 }
1441 1437
1442 if (tmp.nentries != nentries) { 1438 if (tmp.nentries != nentries) {
1443 BUGPRINT("Nentries wrong\n"); 1439 BUGPRINT("Nentries wrong\n");
@@ -2213,8 +2209,12 @@ static int compat_do_replace(struct net *net, void __user *user,
2213 void *entries_tmp; 2209 void *entries_tmp;
2214 2210
2215 ret = compat_copy_ebt_replace_from_user(&tmp, user, len); 2211 ret = compat_copy_ebt_replace_from_user(&tmp, user, len);
2216 if (ret) 2212 if (ret) {
2213 /* try real handler in case userland supplied needed padding */
2214 if (ret == -EINVAL && do_replace(net, user, len) == 0)
2215 ret = 0;
2217 return ret; 2216 return ret;
2217 }
2218 2218
2219 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids; 2219 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
2220 newinfo = vmalloc(sizeof(*newinfo) + countersize); 2220 newinfo = vmalloc(sizeof(*newinfo) + countersize);
@@ -2303,8 +2303,9 @@ static int compat_update_counters(struct net *net, void __user *user,
2303 if (copy_from_user(&hlp, user, sizeof(hlp))) 2303 if (copy_from_user(&hlp, user, sizeof(hlp)))
2304 return -EFAULT; 2304 return -EFAULT;
2305 2305
2306 /* try real handler in case userland supplied needed padding */
2306 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter)) 2307 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
2307 return -EINVAL; 2308 return update_counters(net, user, len);
2308 2309
2309 return do_update_counters(net, hlp.name, compat_ptr(hlp.counters), 2310 return do_update_counters(net, hlp.name, compat_ptr(hlp.counters),
2310 hlp.num_counters, user, len); 2311 hlp.num_counters, user, len);
@@ -2341,9 +2342,10 @@ static int compat_do_ebt_get_ctl(struct sock *sk, int cmd,
2341 if (!capable(CAP_NET_ADMIN)) 2342 if (!capable(CAP_NET_ADMIN))
2342 return -EPERM; 2343 return -EPERM;
2343 2344
2345 /* try real handler in case userland supplied needed padding */
2344 if ((cmd == EBT_SO_GET_INFO || 2346 if ((cmd == EBT_SO_GET_INFO ||
2345 cmd == EBT_SO_GET_INIT_INFO) && *len != sizeof(tmp)) 2347 cmd == EBT_SO_GET_INIT_INFO) && *len != sizeof(tmp))
2346 return -EINVAL; 2348 return do_ebt_get_ctl(sk, cmd, user, len);
2347 2349
2348 if (copy_from_user(&tmp, user, sizeof(tmp))) 2350 if (copy_from_user(&tmp, user, sizeof(tmp)))
2349 return -EFAULT; 2351 return -EFAULT;
@@ -2380,7 +2382,19 @@ static int compat_do_ebt_get_ctl(struct sock *sk, int cmd,
2380 break; 2382 break;
2381 case EBT_SO_GET_ENTRIES: 2383 case EBT_SO_GET_ENTRIES:
2382 case EBT_SO_GET_INIT_ENTRIES: 2384 case EBT_SO_GET_INIT_ENTRIES:
2383 ret = compat_copy_everything_to_user(t, user, len, cmd); 2385 /*
2386 * try real handler first in case of userland-side padding.
2387 * in case we are dealing with an 'ordinary' 32 bit binary
2388 * without 64bit compatibility padding, this will fail right
2389 * after copy_from_user when the *len argument is validated.
2390 *
2391 * the compat_ variant needs to do one pass over the kernel
2392 * data set to adjust for size differences before it the check.
2393 */
2394 if (copy_everything_to_user(t, user, len, cmd) == 0)
2395 ret = 0;
2396 else
2397 ret = compat_copy_everything_to_user(t, user, len, cmd);
2384 break; 2398 break;
2385 default: 2399 default:
2386 ret = -EINVAL; 2400 ret = -EINVAL;