aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-02-18 05:41:39 -0500
committerPatrick McHardy <kaber@trash.net>2010-02-18 05:41:39 -0500
commit477c608673526afc094be521086fed186c7ccf7d (patch)
tree7a4dd0165afa6c1cddadf4c88eeca07c861031ce
parent6457d26bd40077238799e31df2b800bcf4ef9177 (diff)
parent6e705f56a181118f6fbd35e6b443eab33df07290 (diff)
Merge branch 'ebt_config_compat_v4' of git://git.breakpoint.cc/fw/nf-next-2.6
-rw-r--r--net/bridge/netfilter/ebt_limit.c16
-rw-r--r--net/bridge/netfilter/ebt_mark.c31
-rw-r--r--net/bridge/netfilter/ebt_mark_m.c37
-rw-r--r--net/bridge/netfilter/ebtables.c1159
4 files changed, 1124 insertions, 119 deletions
diff --git a/net/bridge/netfilter/ebt_limit.c b/net/bridge/netfilter/ebt_limit.c
index 9dd16e6b10e7..7a8182710eb3 100644
--- a/net/bridge/netfilter/ebt_limit.c
+++ b/net/bridge/netfilter/ebt_limit.c
@@ -84,6 +84,19 @@ static bool ebt_limit_mt_check(const struct xt_mtchk_param *par)
84 return true; 84 return true;
85} 85}
86 86
87
88#ifdef CONFIG_COMPAT
89/*
90 * no conversion function needed --
91 * only avg/burst have meaningful values in userspace.
92 */
93struct ebt_compat_limit_info {
94 compat_uint_t avg, burst;
95 compat_ulong_t prev;
96 compat_uint_t credit, credit_cap, cost;
97};
98#endif
99
87static struct xt_match ebt_limit_mt_reg __read_mostly = { 100static struct xt_match ebt_limit_mt_reg __read_mostly = {
88 .name = "limit", 101 .name = "limit",
89 .revision = 0, 102 .revision = 0,
@@ -91,6 +104,9 @@ static struct xt_match ebt_limit_mt_reg __read_mostly = {
91 .match = ebt_limit_mt, 104 .match = ebt_limit_mt,
92 .checkentry = ebt_limit_mt_check, 105 .checkentry = ebt_limit_mt_check,
93 .matchsize = sizeof(struct ebt_limit_info), 106 .matchsize = sizeof(struct ebt_limit_info),
107#ifdef CONFIG_COMPAT
108 .compatsize = sizeof(struct ebt_compat_limit_info),
109#endif
94 .me = THIS_MODULE, 110 .me = THIS_MODULE,
95}; 111};
96 112
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index 153e167374a2..2b5ce533d6b9 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -52,6 +52,32 @@ static bool ebt_mark_tg_check(const struct xt_tgchk_param *par)
52 return false; 52 return false;
53 return true; 53 return true;
54} 54}
55#ifdef CONFIG_COMPAT
56struct compat_ebt_mark_t_info {
57 compat_ulong_t mark;
58 compat_uint_t target;
59};
60
61static void mark_tg_compat_from_user(void *dst, const void *src)
62{
63 const struct compat_ebt_mark_t_info *user = src;
64 struct ebt_mark_t_info *kern = dst;
65
66 kern->mark = user->mark;
67 kern->target = user->target;
68}
69
70static int mark_tg_compat_to_user(void __user *dst, const void *src)
71{
72 struct compat_ebt_mark_t_info __user *user = dst;
73 const struct ebt_mark_t_info *kern = src;
74
75 if (put_user(kern->mark, &user->mark) ||
76 put_user(kern->target, &user->target))
77 return -EFAULT;
78 return 0;
79}
80#endif
55 81
56static struct xt_target ebt_mark_tg_reg __read_mostly = { 82static struct xt_target ebt_mark_tg_reg __read_mostly = {
57 .name = "mark", 83 .name = "mark",
@@ -60,6 +86,11 @@ static struct xt_target ebt_mark_tg_reg __read_mostly = {
60 .target = ebt_mark_tg, 86 .target = ebt_mark_tg,
61 .checkentry = ebt_mark_tg_check, 87 .checkentry = ebt_mark_tg_check,
62 .targetsize = sizeof(struct ebt_mark_t_info), 88 .targetsize = sizeof(struct ebt_mark_t_info),
89#ifdef CONFIG_COMPAT
90 .compatsize = sizeof(struct compat_ebt_mark_t_info),
91 .compat_from_user = mark_tg_compat_from_user,
92 .compat_to_user = mark_tg_compat_to_user,
93#endif
63 .me = THIS_MODULE, 94 .me = THIS_MODULE,
64}; 95};
65 96
diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c
index 89abf4030399..8de8c396d913 100644
--- a/net/bridge/netfilter/ebt_mark_m.c
+++ b/net/bridge/netfilter/ebt_mark_m.c
@@ -35,6 +35,38 @@ static bool ebt_mark_mt_check(const struct xt_mtchk_param *par)
35 return true; 35 return true;
36} 36}
37 37
38
39#ifdef CONFIG_COMPAT
40struct compat_ebt_mark_m_info {
41 compat_ulong_t mark, mask;
42 uint8_t invert, bitmask;
43};
44
45static void mark_mt_compat_from_user(void *dst, const void *src)
46{
47 const struct compat_ebt_mark_m_info *user = src;
48 struct ebt_mark_m_info *kern = dst;
49
50 kern->mark = user->mark;
51 kern->mask = user->mask;
52 kern->invert = user->invert;
53 kern->bitmask = user->bitmask;
54}
55
56static int mark_mt_compat_to_user(void __user *dst, const void *src)
57{
58 struct compat_ebt_mark_m_info __user *user = dst;
59 const struct ebt_mark_m_info *kern = src;
60
61 if (put_user(kern->mark, &user->mark) ||
62 put_user(kern->mask, &user->mask) ||
63 put_user(kern->invert, &user->invert) ||
64 put_user(kern->bitmask, &user->bitmask))
65 return -EFAULT;
66 return 0;
67}
68#endif
69
38static struct xt_match ebt_mark_mt_reg __read_mostly = { 70static struct xt_match ebt_mark_mt_reg __read_mostly = {
39 .name = "mark_m", 71 .name = "mark_m",
40 .revision = 0, 72 .revision = 0,
@@ -42,6 +74,11 @@ static struct xt_match ebt_mark_mt_reg __read_mostly = {
42 .match = ebt_mark_mt, 74 .match = ebt_mark_mt,
43 .checkentry = ebt_mark_mt_check, 75 .checkentry = ebt_mark_mt_check,
44 .matchsize = sizeof(struct ebt_mark_m_info), 76 .matchsize = sizeof(struct ebt_mark_m_info),
77#ifdef CONFIG_COMPAT
78 .compatsize = sizeof(struct compat_ebt_mark_m_info),
79 .compat_from_user = mark_mt_compat_from_user,
80 .compat_to_user = mark_mt_compat_to_user,
81#endif
45 .me = THIS_MODULE, 82 .me = THIS_MODULE,
46}; 83};
47 84
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 4370e9680487..dfb58056a89a 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
@@ -56,11 +51,37 @@
56 51
57static DEFINE_MUTEX(ebt_mutex); 52static DEFINE_MUTEX(ebt_mutex);
58 53
54#ifdef CONFIG_COMPAT
55static void ebt_standard_compat_from_user(void *dst, const void *src)
56{
57 int v = *(compat_int_t *)src;
58
59 if (v >= 0)
60 v += xt_compat_calc_jump(NFPROTO_BRIDGE, v);
61 memcpy(dst, &v, sizeof(v));
62}
63
64static int ebt_standard_compat_to_user(void __user *dst, const void *src)
65{
66 compat_int_t cv = *(int *)src;
67
68 if (cv >= 0)
69 cv -= xt_compat_calc_jump(NFPROTO_BRIDGE, cv);
70 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
71}
72#endif
73
74
59static struct xt_target ebt_standard_target = { 75static struct xt_target ebt_standard_target = {
60 .name = "standard", 76 .name = "standard",
61 .revision = 0, 77 .revision = 0,
62 .family = NFPROTO_BRIDGE, 78 .family = NFPROTO_BRIDGE,
63 .targetsize = sizeof(int), 79 .targetsize = sizeof(int),
80#ifdef CONFIG_COMPAT
81 .compatsize = sizeof(compat_int_t),
82 .compat_from_user = ebt_standard_compat_from_user,
83 .compat_to_user = ebt_standard_compat_to_user,
84#endif
64}; 85};
65 86
66static inline int 87static inline int
@@ -959,91 +980,45 @@ static void get_counters(const struct ebt_counter *oldcounters,
959 } 980 }
960} 981}
961 982
962/* replace the table */ 983static int do_replace_finish(struct net *net, struct ebt_replace *repl,
963static int do_replace(struct net *net, const void __user *user, 984 struct ebt_table_info *newinfo)
964 unsigned int len)
965{ 985{
966 int ret, i, countersize; 986 int ret, i;
967 struct ebt_table_info *newinfo;
968 struct ebt_replace tmp;
969 struct ebt_table *t;
970 struct ebt_counter *counterstmp = NULL; 987 struct ebt_counter *counterstmp = NULL;
971 /* used to be able to unlock earlier */ 988 /* used to be able to unlock earlier */
972 struct ebt_table_info *table; 989 struct ebt_table_info *table;
973 990 struct ebt_table *t;
974 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
975 return -EFAULT;
976
977 if (len != sizeof(tmp) + tmp.entries_size) {
978 BUGPRINT("Wrong len argument\n");
979 return -EINVAL;
980 }
981
982 if (tmp.entries_size == 0) {
983 BUGPRINT("Entries_size never zero\n");
984 return -EINVAL;
985 }
986 /* overflow check */
987 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS -
988 SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
989 return -ENOMEM;
990 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
991 return -ENOMEM;
992
993 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
994 newinfo = vmalloc(sizeof(*newinfo) + countersize);
995 if (!newinfo)
996 return -ENOMEM;
997
998 if (countersize)
999 memset(newinfo->counters, 0, countersize);
1000
1001 newinfo->entries = vmalloc(tmp.entries_size);
1002 if (!newinfo->entries) {
1003 ret = -ENOMEM;
1004 goto free_newinfo;
1005 }
1006 if (copy_from_user(
1007 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
1008 BUGPRINT("Couldn't copy entries from userspace\n");
1009 ret = -EFAULT;
1010 goto free_entries;
1011 }
1012 991
1013 /* the user wants counters back 992 /* the user wants counters back
1014 the check on the size is done later, when we have the lock */ 993 the check on the size is done later, when we have the lock */
1015 if (tmp.num_counters) { 994 if (repl->num_counters) {
1016 counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp)); 995 unsigned long size = repl->num_counters * sizeof(*counterstmp);
1017 if (!counterstmp) { 996 counterstmp = vmalloc(size);
1018 ret = -ENOMEM; 997 if (!counterstmp)
1019 goto free_entries; 998 return -ENOMEM;
1020 }
1021 } 999 }
1022 else
1023 counterstmp = NULL;
1024 1000
1025 /* this can get initialized by translate_table() */
1026 newinfo->chainstack = NULL; 1001 newinfo->chainstack = NULL;
1027 ret = ebt_verify_pointers(&tmp, newinfo); 1002 ret = ebt_verify_pointers(repl, newinfo);
1028 if (ret != 0) 1003 if (ret != 0)
1029 goto free_counterstmp; 1004 goto free_counterstmp;
1030 1005
1031 ret = translate_table(net, tmp.name, newinfo); 1006 ret = translate_table(net, repl->name, newinfo);
1032 1007
1033 if (ret != 0) 1008 if (ret != 0)
1034 goto free_counterstmp; 1009 goto free_counterstmp;
1035 1010
1036 t = find_table_lock(net, tmp.name, &ret, &ebt_mutex); 1011 t = find_table_lock(net, repl->name, &ret, &ebt_mutex);
1037 if (!t) { 1012 if (!t) {
1038 ret = -ENOENT; 1013 ret = -ENOENT;
1039 goto free_iterate; 1014 goto free_iterate;
1040 } 1015 }
1041 1016
1042 /* the table doesn't like it */ 1017 /* the table doesn't like it */
1043 if (t->check && (ret = t->check(newinfo, tmp.valid_hooks))) 1018 if (t->check && (ret = t->check(newinfo, repl->valid_hooks)))
1044 goto free_unlock; 1019 goto free_unlock;
1045 1020
1046 if (tmp.num_counters && tmp.num_counters != t->private->nentries) { 1021 if (repl->num_counters && repl->num_counters != t->private->nentries) {
1047 BUGPRINT("Wrong nr. of counters requested\n"); 1022 BUGPRINT("Wrong nr. of counters requested\n");
1048 ret = -EINVAL; 1023 ret = -EINVAL;
1049 goto free_unlock; 1024 goto free_unlock;
@@ -1059,7 +1034,7 @@ static int do_replace(struct net *net, const void __user *user,
1059 module_put(t->me); 1034 module_put(t->me);
1060 /* we need an atomic snapshot of the counters */ 1035 /* we need an atomic snapshot of the counters */
1061 write_lock_bh(&t->lock); 1036 write_lock_bh(&t->lock);
1062 if (tmp.num_counters) 1037 if (repl->num_counters)
1063 get_counters(t->private->counters, counterstmp, 1038 get_counters(t->private->counters, counterstmp,
1064 t->private->nentries); 1039 t->private->nentries);
1065 1040
@@ -1070,10 +1045,9 @@ static int do_replace(struct net *net, const void __user *user,
1070 allocation. Only reason why this is done is because this way the lock 1045 allocation. Only reason why this is done is because this way the lock
1071 is held only once, while this doesn't bring the kernel into a 1046 is held only once, while this doesn't bring the kernel into a
1072 dangerous state. */ 1047 dangerous state. */
1073 if (tmp.num_counters && 1048 if (repl->num_counters &&
1074 copy_to_user(tmp.counters, counterstmp, 1049 copy_to_user(repl->counters, counterstmp,
1075 tmp.num_counters * sizeof(struct ebt_counter))) { 1050 repl->num_counters * sizeof(struct ebt_counter))) {
1076 BUGPRINT("Couldn't copy counters to userspace\n");
1077 ret = -EFAULT; 1051 ret = -EFAULT;
1078 } 1052 }
1079 else 1053 else
@@ -1107,6 +1081,59 @@ free_counterstmp:
1107 vfree(newinfo->chainstack[i]); 1081 vfree(newinfo->chainstack[i]);
1108 vfree(newinfo->chainstack); 1082 vfree(newinfo->chainstack);
1109 } 1083 }
1084 return ret;
1085}
1086
1087/* replace the table */
1088static int do_replace(struct net *net, const void __user *user,
1089 unsigned int len)
1090{
1091 int ret, countersize;
1092 struct ebt_table_info *newinfo;
1093 struct ebt_replace tmp;
1094
1095 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1096 return -EFAULT;
1097
1098 if (len != sizeof(tmp) + tmp.entries_size) {
1099 BUGPRINT("Wrong len argument\n");
1100 return -EINVAL;
1101 }
1102
1103 if (tmp.entries_size == 0) {
1104 BUGPRINT("Entries_size never zero\n");
1105 return -EINVAL;
1106 }
1107 /* overflow check */
1108 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) /
1109 NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
1110 return -ENOMEM;
1111 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
1112 return -ENOMEM;
1113
1114 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
1115 newinfo = vmalloc(sizeof(*newinfo) + countersize);
1116 if (!newinfo)
1117 return -ENOMEM;
1118
1119 if (countersize)
1120 memset(newinfo->counters, 0, countersize);
1121
1122 newinfo->entries = vmalloc(tmp.entries_size);
1123 if (!newinfo->entries) {
1124 ret = -ENOMEM;
1125 goto free_newinfo;
1126 }
1127 if (copy_from_user(
1128 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
1129 BUGPRINT("Couldn't copy entries from userspace\n");
1130 ret = -EFAULT;
1131 goto free_entries;
1132 }
1133
1134 ret = do_replace_finish(net, &tmp, newinfo);
1135 if (ret == 0)
1136 return ret;
1110free_entries: 1137free_entries:
1111 vfree(newinfo->entries); 1138 vfree(newinfo->entries);
1112free_newinfo: 1139free_newinfo:
@@ -1241,40 +1268,33 @@ void ebt_unregister_table(struct net *net, struct ebt_table *table)
1241} 1268}
1242 1269
1243/* userspace just supplied us with counters */ 1270/* userspace just supplied us with counters */
1244static int update_counters(struct net *net, const void __user *user, 1271static int do_update_counters(struct net *net, const char *name,
1245 unsigned int len) 1272 struct ebt_counter __user *counters,
1273 unsigned int num_counters,
1274 const void __user *user, unsigned int len)
1246{ 1275{
1247 int i, ret; 1276 int i, ret;
1248 struct ebt_counter *tmp; 1277 struct ebt_counter *tmp;
1249 struct ebt_replace hlp;
1250 struct ebt_table *t; 1278 struct ebt_table *t;
1251 1279
1252 if (copy_from_user(&hlp, user, sizeof(hlp))) 1280 if (num_counters == 0)
1253 return -EFAULT;
1254
1255 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1256 return -EINVAL;
1257 if (hlp.num_counters == 0)
1258 return -EINVAL; 1281 return -EINVAL;
1259 1282
1260 if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) { 1283 tmp = vmalloc(num_counters * sizeof(*tmp));
1261 MEMPRINT("Update_counters && nomemory\n"); 1284 if (!tmp)
1262 return -ENOMEM; 1285 return -ENOMEM;
1263 }
1264 1286
1265 t = find_table_lock(net, hlp.name, &ret, &ebt_mutex); 1287 t = find_table_lock(net, name, &ret, &ebt_mutex);
1266 if (!t) 1288 if (!t)
1267 goto free_tmp; 1289 goto free_tmp;
1268 1290
1269 if (hlp.num_counters != t->private->nentries) { 1291 if (num_counters != t->private->nentries) {
1270 BUGPRINT("Wrong nr of counters\n"); 1292 BUGPRINT("Wrong nr of counters\n");
1271 ret = -EINVAL; 1293 ret = -EINVAL;
1272 goto unlock_mutex; 1294 goto unlock_mutex;
1273 } 1295 }
1274 1296
1275 if ( copy_from_user(tmp, hlp.counters, 1297 if (copy_from_user(tmp, counters, num_counters * sizeof(*counters))) {
1276 hlp.num_counters * sizeof(struct ebt_counter)) ) {
1277 BUGPRINT("Updata_counters && !cfu\n");
1278 ret = -EFAULT; 1298 ret = -EFAULT;
1279 goto unlock_mutex; 1299 goto unlock_mutex;
1280 } 1300 }
@@ -1283,7 +1303,7 @@ static int update_counters(struct net *net, const void __user *user,
1283 write_lock_bh(&t->lock); 1303 write_lock_bh(&t->lock);
1284 1304
1285 /* we add to the counters of the first cpu */ 1305 /* we add to the counters of the first cpu */
1286 for (i = 0; i < hlp.num_counters; i++) { 1306 for (i = 0; i < num_counters; i++) {
1287 t->private->counters[i].pcnt += tmp[i].pcnt; 1307 t->private->counters[i].pcnt += tmp[i].pcnt;
1288 t->private->counters[i].bcnt += tmp[i].bcnt; 1308 t->private->counters[i].bcnt += tmp[i].bcnt;
1289 } 1309 }
@@ -1297,6 +1317,21 @@ free_tmp:
1297 return ret; 1317 return ret;
1298} 1318}
1299 1319
1320static int update_counters(struct net *net, const void __user *user,
1321 unsigned int len)
1322{
1323 struct ebt_replace hlp;
1324
1325 if (copy_from_user(&hlp, user, sizeof(hlp)))
1326 return -EFAULT;
1327
1328 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1329 return -EINVAL;
1330
1331 return do_update_counters(net, hlp.name, hlp.counters,
1332 hlp.num_counters, user, len);
1333}
1334
1300static inline int ebt_make_matchname(const struct ebt_entry_match *m, 1335static inline int ebt_make_matchname(const struct ebt_entry_match *m,
1301 const char *base, char __user *ubase) 1336 const char *base, char __user *ubase)
1302{ 1337{
@@ -1339,14 +1374,46 @@ ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase)
1339 return 0; 1374 return 0;
1340} 1375}
1341 1376
1377static int copy_counters_to_user(struct ebt_table *t,
1378 const struct ebt_counter *oldcounters,
1379 void __user *user, unsigned int num_counters,
1380 unsigned int nentries)
1381{
1382 struct ebt_counter *counterstmp;
1383 int ret = 0;
1384
1385 /* userspace might not need the counters */
1386 if (num_counters == 0)
1387 return 0;
1388
1389 if (num_counters != nentries) {
1390 BUGPRINT("Num_counters wrong\n");
1391 return -EINVAL;
1392 }
1393
1394 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
1395 if (!counterstmp)
1396 return -ENOMEM;
1397
1398 write_lock_bh(&t->lock);
1399 get_counters(oldcounters, counterstmp, nentries);
1400 write_unlock_bh(&t->lock);
1401
1402 if (copy_to_user(user, counterstmp,
1403 nentries * sizeof(struct ebt_counter)))
1404 ret = -EFAULT;
1405 vfree(counterstmp);
1406 return ret;
1407}
1408
1342/* called with ebt_mutex locked */ 1409/* called with ebt_mutex locked */
1343static int copy_everything_to_user(struct ebt_table *t, void __user *user, 1410static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1344 const int *len, int cmd) 1411 const int *len, int cmd)
1345{ 1412{
1346 struct ebt_replace tmp; 1413 struct ebt_replace tmp;
1347 struct ebt_counter *counterstmp;
1348 const struct ebt_counter *oldcounters; 1414 const struct ebt_counter *oldcounters;
1349 unsigned int entries_size, nentries; 1415 unsigned int entries_size, nentries;
1416 int ret;
1350 char *entries; 1417 char *entries;
1351 1418
1352 if (cmd == EBT_SO_GET_ENTRIES) { 1419 if (cmd == EBT_SO_GET_ENTRIES) {
@@ -1361,16 +1428,12 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1361 oldcounters = t->table->counters; 1428 oldcounters = t->table->counters;
1362 } 1429 }
1363 1430
1364 if (copy_from_user(&tmp, user, sizeof(tmp))) { 1431 if (copy_from_user(&tmp, user, sizeof(tmp)))
1365 BUGPRINT("Cfu didn't work\n");
1366 return -EFAULT; 1432 return -EFAULT;
1367 }
1368 1433
1369 if (*len != sizeof(struct ebt_replace) + entries_size + 1434 if (*len != sizeof(struct ebt_replace) + entries_size +
1370 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) { 1435 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0))
1371 BUGPRINT("Wrong size\n");
1372 return -EINVAL; 1436 return -EINVAL;
1373 }
1374 1437
1375 if (tmp.nentries != nentries) { 1438 if (tmp.nentries != nentries) {
1376 BUGPRINT("Nentries wrong\n"); 1439 BUGPRINT("Nentries wrong\n");
@@ -1382,29 +1445,10 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1382 return -EINVAL; 1445 return -EINVAL;
1383 } 1446 }
1384 1447
1385 /* userspace might not need the counters */ 1448 ret = copy_counters_to_user(t, oldcounters, tmp.counters,
1386 if (tmp.num_counters) { 1449 tmp.num_counters, nentries);
1387 if (tmp.num_counters != nentries) { 1450 if (ret)
1388 BUGPRINT("Num_counters wrong\n"); 1451 return ret;
1389 return -EINVAL;
1390 }
1391 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
1392 if (!counterstmp) {
1393 MEMPRINT("Couldn't copy counters, out of memory\n");
1394 return -ENOMEM;
1395 }
1396 write_lock_bh(&t->lock);
1397 get_counters(oldcounters, counterstmp, nentries);
1398 write_unlock_bh(&t->lock);
1399
1400 if (copy_to_user(tmp.counters, counterstmp,
1401 nentries * sizeof(struct ebt_counter))) {
1402 BUGPRINT("Couldn't copy counters to userspace\n");
1403 vfree(counterstmp);
1404 return -EFAULT;
1405 }
1406 vfree(counterstmp);
1407 }
1408 1452
1409 if (copy_to_user(tmp.entries, entries, entries_size)) { 1453 if (copy_to_user(tmp.entries, entries, entries_size)) {
1410 BUGPRINT("Couldn't copy entries to userspace\n"); 1454 BUGPRINT("Couldn't copy entries to userspace\n");
@@ -1432,7 +1476,7 @@ static int do_ebt_set_ctl(struct sock *sk,
1432 break; 1476 break;
1433 default: 1477 default:
1434 ret = -EINVAL; 1478 ret = -EINVAL;
1435 } 1479 }
1436 return ret; 1480 return ret;
1437} 1481}
1438 1482
@@ -1492,15 +1536,892 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1492 return ret; 1536 return ret;
1493} 1537}
1494 1538
1539#ifdef CONFIG_COMPAT
1540/* 32 bit-userspace compatibility definitions. */
1541struct compat_ebt_replace {
1542 char name[EBT_TABLE_MAXNAMELEN];
1543 compat_uint_t valid_hooks;
1544 compat_uint_t nentries;
1545 compat_uint_t entries_size;
1546 /* start of the chains */
1547 compat_uptr_t hook_entry[NF_BR_NUMHOOKS];
1548 /* nr of counters userspace expects back */
1549 compat_uint_t num_counters;
1550 /* where the kernel will put the old counters. */
1551 compat_uptr_t counters;
1552 compat_uptr_t entries;
1553};
1554
1555/* struct ebt_entry_match, _target and _watcher have same layout */
1556struct compat_ebt_entry_mwt {
1557 union {
1558 char name[EBT_FUNCTION_MAXNAMELEN];
1559 compat_uptr_t ptr;
1560 } u;
1561 compat_uint_t match_size;
1562 compat_uint_t data[0];
1563};
1564
1565/* account for possible padding between match_size and ->data */
1566static int ebt_compat_entry_padsize(void)
1567{
1568 BUILD_BUG_ON(XT_ALIGN(sizeof(struct ebt_entry_match)) <
1569 COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt)));
1570 return (int) XT_ALIGN(sizeof(struct ebt_entry_match)) -
1571 COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt));
1572}
1573
1574static int ebt_compat_match_offset(const struct xt_match *match,
1575 unsigned int userlen)
1576{
1577 /*
1578 * ebt_among needs special handling. The kernel .matchsize is
1579 * set to -1 at registration time; at runtime an EBT_ALIGN()ed
1580 * value is expected.
1581 * Example: userspace sends 4500, ebt_among.c wants 4504.
1582 */
1583 if (unlikely(match->matchsize == -1))
1584 return XT_ALIGN(userlen) - COMPAT_XT_ALIGN(userlen);
1585 return xt_compat_match_offset(match);
1586}
1587
1588static int compat_match_to_user(struct ebt_entry_match *m, void __user **dstptr,
1589 unsigned int *size)
1590{
1591 const struct xt_match *match = m->u.match;
1592 struct compat_ebt_entry_mwt __user *cm = *dstptr;
1593 int off = ebt_compat_match_offset(match, m->match_size);
1594 compat_uint_t msize = m->match_size - off;
1595
1596 BUG_ON(off >= m->match_size);
1597
1598 if (copy_to_user(cm->u.name, match->name,
1599 strlen(match->name) + 1) || put_user(msize, &cm->match_size))
1600 return -EFAULT;
1601
1602 if (match->compat_to_user) {
1603 if (match->compat_to_user(cm->data, m->data))
1604 return -EFAULT;
1605 } else if (copy_to_user(cm->data, m->data, msize))
1606 return -EFAULT;
1607
1608 *size -= ebt_compat_entry_padsize() + off;
1609 *dstptr = cm->data;
1610 *dstptr += msize;
1611 return 0;
1612}
1613
1614static int compat_target_to_user(struct ebt_entry_target *t,
1615 void __user **dstptr,
1616 unsigned int *size)
1617{
1618 const struct xt_target *target = t->u.target;
1619 struct compat_ebt_entry_mwt __user *cm = *dstptr;
1620 int off = xt_compat_target_offset(target);
1621 compat_uint_t tsize = t->target_size - off;
1622
1623 BUG_ON(off >= t->target_size);
1624
1625 if (copy_to_user(cm->u.name, target->name,
1626 strlen(target->name) + 1) || put_user(tsize, &cm->match_size))
1627 return -EFAULT;
1628
1629 if (target->compat_to_user) {
1630 if (target->compat_to_user(cm->data, t->data))
1631 return -EFAULT;
1632 } else if (copy_to_user(cm->data, t->data, tsize))
1633 return -EFAULT;
1634
1635 *size -= ebt_compat_entry_padsize() + off;
1636 *dstptr = cm->data;
1637 *dstptr += tsize;
1638 return 0;
1639}
1640
1641static int compat_watcher_to_user(struct ebt_entry_watcher *w,
1642 void __user **dstptr,
1643 unsigned int *size)
1644{
1645 return compat_target_to_user((struct ebt_entry_target *)w,
1646 dstptr, size);
1647}
1648
1649static int compat_copy_entry_to_user(struct ebt_entry *e, void __user **dstptr,
1650 unsigned int *size)
1651{
1652 struct ebt_entry_target *t;
1653 struct ebt_entry __user *ce;
1654 u32 watchers_offset, target_offset, next_offset;
1655 compat_uint_t origsize;
1656 int ret;
1657
1658 if (e->bitmask == 0) {
1659 if (*size < sizeof(struct ebt_entries))
1660 return -EINVAL;
1661 if (copy_to_user(*dstptr, e, sizeof(struct ebt_entries)))
1662 return -EFAULT;
1663
1664 *dstptr += sizeof(struct ebt_entries);
1665 *size -= sizeof(struct ebt_entries);
1666 return 0;
1667 }
1668
1669 if (*size < sizeof(*ce))
1670 return -EINVAL;
1671
1672 ce = (struct ebt_entry __user *)*dstptr;
1673 if (copy_to_user(ce, e, sizeof(*ce)))
1674 return -EFAULT;
1675
1676 origsize = *size;
1677 *dstptr += sizeof(*ce);
1678
1679 ret = EBT_MATCH_ITERATE(e, compat_match_to_user, dstptr, size);
1680 if (ret)
1681 return ret;
1682 watchers_offset = e->watchers_offset - (origsize - *size);
1683
1684 ret = EBT_WATCHER_ITERATE(e, compat_watcher_to_user, dstptr, size);
1685 if (ret)
1686 return ret;
1687 target_offset = e->target_offset - (origsize - *size);
1688
1689 t = (struct ebt_entry_target *) ((char *) e + e->target_offset);
1690
1691 ret = compat_target_to_user(t, dstptr, size);
1692 if (ret)
1693 return ret;
1694 next_offset = e->next_offset - (origsize - *size);
1695
1696 if (put_user(watchers_offset, &ce->watchers_offset) ||
1697 put_user(target_offset, &ce->target_offset) ||
1698 put_user(next_offset, &ce->next_offset))
1699 return -EFAULT;
1700
1701 *size -= sizeof(*ce);
1702 return 0;
1703}
1704
1705static int compat_calc_match(struct ebt_entry_match *m, int *off)
1706{
1707 *off += ebt_compat_match_offset(m->u.match, m->match_size);
1708 *off += ebt_compat_entry_padsize();
1709 return 0;
1710}
1711
1712static int compat_calc_watcher(struct ebt_entry_watcher *w, int *off)
1713{
1714 *off += xt_compat_target_offset(w->u.watcher);
1715 *off += ebt_compat_entry_padsize();
1716 return 0;
1717}
1718
1719static int compat_calc_entry(const struct ebt_entry *e,
1720 const struct ebt_table_info *info,
1721 const void *base,
1722 struct compat_ebt_replace *newinfo)
1723{
1724 const struct ebt_entry_target *t;
1725 unsigned int entry_offset;
1726 int off, ret, i;
1727
1728 if (e->bitmask == 0)
1729 return 0;
1730
1731 off = 0;
1732 entry_offset = (void *)e - base;
1733
1734 EBT_MATCH_ITERATE(e, compat_calc_match, &off);
1735 EBT_WATCHER_ITERATE(e, compat_calc_watcher, &off);
1736
1737 t = (const struct ebt_entry_target *) ((char *) e + e->target_offset);
1738
1739 off += xt_compat_target_offset(t->u.target);
1740 off += ebt_compat_entry_padsize();
1741
1742 newinfo->entries_size -= off;
1743
1744 ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset, off);
1745 if (ret)
1746 return ret;
1747
1748 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1749 const void *hookptr = info->hook_entry[i];
1750 if (info->hook_entry[i] &&
1751 (e < (struct ebt_entry *)(base - hookptr))) {
1752 newinfo->hook_entry[i] -= off;
1753 pr_debug("0x%08X -> 0x%08X\n",
1754 newinfo->hook_entry[i] + off,
1755 newinfo->hook_entry[i]);
1756 }
1757 }
1758
1759 return 0;
1760}
1761
1762
1763static int compat_table_info(const struct ebt_table_info *info,
1764 struct compat_ebt_replace *newinfo)
1765{
1766 unsigned int size = info->entries_size;
1767 const void *entries = info->entries;
1768
1769 newinfo->entries_size = size;
1770
1771 return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info,
1772 entries, newinfo);
1773}
1774
1775static int compat_copy_everything_to_user(struct ebt_table *t,
1776 void __user *user, int *len, int cmd)
1777{
1778 struct compat_ebt_replace repl, tmp;
1779 struct ebt_counter *oldcounters;
1780 struct ebt_table_info tinfo;
1781 int ret;
1782 void __user *pos;
1783
1784 memset(&tinfo, 0, sizeof(tinfo));
1785
1786 if (cmd == EBT_SO_GET_ENTRIES) {
1787 tinfo.entries_size = t->private->entries_size;
1788 tinfo.nentries = t->private->nentries;
1789 tinfo.entries = t->private->entries;
1790 oldcounters = t->private->counters;
1791 } else {
1792 tinfo.entries_size = t->table->entries_size;
1793 tinfo.nentries = t->table->nentries;
1794 tinfo.entries = t->table->entries;
1795 oldcounters = t->table->counters;
1796 }
1797
1798 if (copy_from_user(&tmp, user, sizeof(tmp)))
1799 return -EFAULT;
1800
1801 if (tmp.nentries != tinfo.nentries ||
1802 (tmp.num_counters && tmp.num_counters != tinfo.nentries))
1803 return -EINVAL;
1804
1805 memcpy(&repl, &tmp, sizeof(repl));
1806 if (cmd == EBT_SO_GET_ENTRIES)
1807 ret = compat_table_info(t->private, &repl);
1808 else
1809 ret = compat_table_info(&tinfo, &repl);
1810 if (ret)
1811 return ret;
1812
1813 if (*len != sizeof(tmp) + repl.entries_size +
1814 (tmp.num_counters? tinfo.nentries * sizeof(struct ebt_counter): 0)) {
1815 pr_err("wrong size: *len %d, entries_size %u, replsz %d\n",
1816 *len, tinfo.entries_size, repl.entries_size);
1817 return -EINVAL;
1818 }
1819
1820 /* userspace might not need the counters */
1821 ret = copy_counters_to_user(t, oldcounters, compat_ptr(tmp.counters),
1822 tmp.num_counters, tinfo.nentries);
1823 if (ret)
1824 return ret;
1825
1826 pos = compat_ptr(tmp.entries);
1827 return EBT_ENTRY_ITERATE(tinfo.entries, tinfo.entries_size,
1828 compat_copy_entry_to_user, &pos, &tmp.entries_size);
1829}
1830
1831struct ebt_entries_buf_state {
1832 char *buf_kern_start; /* kernel buffer to copy (translated) data to */
1833 u32 buf_kern_len; /* total size of kernel buffer */
1834 u32 buf_kern_offset; /* amount of data copied so far */
1835 u32 buf_user_offset; /* read position in userspace buffer */
1836};
1837
1838static int ebt_buf_count(struct ebt_entries_buf_state *state, unsigned int sz)
1839{
1840 state->buf_kern_offset += sz;
1841 return state->buf_kern_offset >= sz ? 0 : -EINVAL;
1842}
1843
1844static int ebt_buf_add(struct ebt_entries_buf_state *state,
1845 void *data, unsigned int sz)
1846{
1847 if (state->buf_kern_start == NULL)
1848 goto count_only;
1849
1850 BUG_ON(state->buf_kern_offset + sz > state->buf_kern_len);
1851
1852 memcpy(state->buf_kern_start + state->buf_kern_offset, data, sz);
1853
1854 count_only:
1855 state->buf_user_offset += sz;
1856 return ebt_buf_count(state, sz);
1857}
1858
1859static int ebt_buf_add_pad(struct ebt_entries_buf_state *state, unsigned int sz)
1860{
1861 char *b = state->buf_kern_start;
1862
1863 BUG_ON(b && state->buf_kern_offset > state->buf_kern_len);
1864
1865 if (b != NULL && sz > 0)
1866 memset(b + state->buf_kern_offset, 0, sz);
1867 /* do not adjust ->buf_user_offset here, we added kernel-side padding */
1868 return ebt_buf_count(state, sz);
1869}
1870
1871enum compat_mwt {
1872 EBT_COMPAT_MATCH,
1873 EBT_COMPAT_WATCHER,
1874 EBT_COMPAT_TARGET,
1875};
1876
1877static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
1878 enum compat_mwt compat_mwt,
1879 struct ebt_entries_buf_state *state,
1880 const unsigned char *base)
1881{
1882 char name[EBT_FUNCTION_MAXNAMELEN];
1883 struct xt_match *match;
1884 struct xt_target *wt;
1885 void *dst = NULL;
1886 int off, pad = 0, ret = 0;
1887 unsigned int size_kern, entry_offset, match_size = mwt->match_size;
1888
1889 strlcpy(name, mwt->u.name, sizeof(name));
1890
1891 if (state->buf_kern_start)
1892 dst = state->buf_kern_start + state->buf_kern_offset;
1893
1894 entry_offset = (unsigned char *) mwt - base;
1895 switch (compat_mwt) {
1896 case EBT_COMPAT_MATCH:
1897 match = try_then_request_module(xt_find_match(NFPROTO_BRIDGE,
1898 name, 0), "ebt_%s", name);
1899 if (match == NULL)
1900 return -ENOENT;
1901 if (IS_ERR(match))
1902 return PTR_ERR(match);
1903
1904 off = ebt_compat_match_offset(match, match_size);
1905 if (dst) {
1906 if (match->compat_from_user)
1907 match->compat_from_user(dst, mwt->data);
1908 else
1909 memcpy(dst, mwt->data, match_size);
1910 }
1911
1912 size_kern = match->matchsize;
1913 if (unlikely(size_kern == -1))
1914 size_kern = match_size;
1915 module_put(match->me);
1916 break;
1917 case EBT_COMPAT_WATCHER: /* fallthrough */
1918 case EBT_COMPAT_TARGET:
1919 wt = try_then_request_module(xt_find_target(NFPROTO_BRIDGE,
1920 name, 0), "ebt_%s", name);
1921 if (wt == NULL)
1922 return -ENOENT;
1923 if (IS_ERR(wt))
1924 return PTR_ERR(wt);
1925 off = xt_compat_target_offset(wt);
1926
1927 if (dst) {
1928 if (wt->compat_from_user)
1929 wt->compat_from_user(dst, mwt->data);
1930 else
1931 memcpy(dst, mwt->data, match_size);
1932 }
1933
1934 size_kern = wt->targetsize;
1935 module_put(wt->me);
1936 break;
1937 }
1938
1939 if (!dst) {
1940 ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset,
1941 off + ebt_compat_entry_padsize());
1942 if (ret < 0)
1943 return ret;
1944 }
1945
1946 state->buf_kern_offset += match_size + off;
1947 state->buf_user_offset += match_size;
1948 pad = XT_ALIGN(size_kern) - size_kern;
1949
1950 if (pad > 0 && dst) {
1951 BUG_ON(state->buf_kern_len <= pad);
1952 BUG_ON(state->buf_kern_offset - (match_size + off) + size_kern > state->buf_kern_len - pad);
1953 memset(dst + size_kern, 0, pad);
1954 }
1955 return off + match_size;
1956}
1957
1958/*
1959 * return size of all matches, watchers or target, including necessary
1960 * alignment and padding.
1961 */
1962static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
1963 unsigned int size_left, enum compat_mwt type,
1964 struct ebt_entries_buf_state *state, const void *base)
1965{
1966 int growth = 0;
1967 char *buf;
1968
1969 if (size_left == 0)
1970 return 0;
1971
1972 buf = (char *) match32;
1973
1974 while (size_left >= sizeof(*match32)) {
1975 struct ebt_entry_match *match_kern;
1976 int ret;
1977
1978 match_kern = (struct ebt_entry_match *) state->buf_kern_start;
1979 if (match_kern) {
1980 char *tmp;
1981 tmp = state->buf_kern_start + state->buf_kern_offset;
1982 match_kern = (struct ebt_entry_match *) tmp;
1983 }
1984 ret = ebt_buf_add(state, buf, sizeof(*match32));
1985 if (ret < 0)
1986 return ret;
1987 size_left -= sizeof(*match32);
1988
1989 /* add padding before match->data (if any) */
1990 ret = ebt_buf_add_pad(state, ebt_compat_entry_padsize());
1991 if (ret < 0)
1992 return ret;
1993
1994 if (match32->match_size > size_left)
1995 return -EINVAL;
1996
1997 size_left -= match32->match_size;
1998
1999 ret = compat_mtw_from_user(match32, type, state, base);
2000 if (ret < 0)
2001 return ret;
2002
2003 BUG_ON(ret < match32->match_size);
2004 growth += ret - match32->match_size;
2005 growth += ebt_compat_entry_padsize();
2006
2007 buf += sizeof(*match32);
2008 buf += match32->match_size;
2009
2010 if (match_kern)
2011 match_kern->match_size = ret;
2012
2013 WARN_ON(type == EBT_COMPAT_TARGET && size_left);
2014 match32 = (struct compat_ebt_entry_mwt *) buf;
2015 }
2016
2017 return growth;
2018}
2019
2020#define EBT_COMPAT_WATCHER_ITERATE(e, fn, args...) \
2021({ \
2022 unsigned int __i; \
2023 int __ret = 0; \
2024 struct compat_ebt_entry_mwt *__watcher; \
2025 \
2026 for (__i = e->watchers_offset; \
2027 __i < (e)->target_offset; \
2028 __i += __watcher->watcher_size + \
2029 sizeof(struct compat_ebt_entry_mwt)) { \
2030 __watcher = (void *)(e) + __i; \
2031 __ret = fn(__watcher , ## args); \
2032 if (__ret != 0) \
2033 break; \
2034 } \
2035 if (__ret == 0) { \
2036 if (__i != (e)->target_offset) \
2037 __ret = -EINVAL; \
2038 } \
2039 __ret; \
2040})
2041
2042#define EBT_COMPAT_MATCH_ITERATE(e, fn, args...) \
2043({ \
2044 unsigned int __i; \
2045 int __ret = 0; \
2046 struct compat_ebt_entry_mwt *__match; \
2047 \
2048 for (__i = sizeof(struct ebt_entry); \
2049 __i < (e)->watchers_offset; \
2050 __i += __match->match_size + \
2051 sizeof(struct compat_ebt_entry_mwt)) { \
2052 __match = (void *)(e) + __i; \
2053 __ret = fn(__match , ## args); \
2054 if (__ret != 0) \
2055 break; \
2056 } \
2057 if (__ret == 0) { \
2058 if (__i != (e)->watchers_offset) \
2059 __ret = -EINVAL; \
2060 } \
2061 __ret; \
2062})
2063
2064/* called for all ebt_entry structures. */
2065static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
2066 unsigned int *total,
2067 struct ebt_entries_buf_state *state)
2068{
2069 unsigned int i, j, startoff, new_offset = 0;
2070 /* stores match/watchers/targets & offset of next struct ebt_entry: */
2071 unsigned int offsets[4];
2072 unsigned int *offsets_update = NULL;
2073 int ret;
2074 char *buf_start;
2075
2076 if (*total < sizeof(struct ebt_entries))
2077 return -EINVAL;
2078
2079 if (!entry->bitmask) {
2080 *total -= sizeof(struct ebt_entries);
2081 return ebt_buf_add(state, entry, sizeof(struct ebt_entries));
2082 }
2083 if (*total < sizeof(*entry) || entry->next_offset < sizeof(*entry))
2084 return -EINVAL;
2085
2086 startoff = state->buf_user_offset;
2087 /* pull in most part of ebt_entry, it does not need to be changed. */
2088 ret = ebt_buf_add(state, entry,
2089 offsetof(struct ebt_entry, watchers_offset));
2090 if (ret < 0)
2091 return ret;
2092
2093 offsets[0] = sizeof(struct ebt_entry); /* matches come first */
2094 memcpy(&offsets[1], &entry->watchers_offset,
2095 sizeof(offsets) - sizeof(offsets[0]));
2096
2097 if (state->buf_kern_start) {
2098 buf_start = state->buf_kern_start + state->buf_kern_offset;
2099 offsets_update = (unsigned int *) buf_start;
2100 }
2101 ret = ebt_buf_add(state, &offsets[1],
2102 sizeof(offsets) - sizeof(offsets[0]));
2103 if (ret < 0)
2104 return ret;
2105 buf_start = (char *) entry;
2106 /*
2107 * 0: matches offset, always follows ebt_entry.
2108 * 1: watchers offset, from ebt_entry structure
2109 * 2: target offset, from ebt_entry structure
2110 * 3: next ebt_entry offset, from ebt_entry structure
2111 *
2112 * offsets are relative to beginning of struct ebt_entry (i.e., 0).
2113 */
2114 for (i = 0, j = 1 ; j < 4 ; j++, i++) {
2115 struct compat_ebt_entry_mwt *match32;
2116 unsigned int size;
2117 char *buf = buf_start;
2118
2119 buf = buf_start + offsets[i];
2120 if (offsets[i] > offsets[j])
2121 return -EINVAL;
2122
2123 match32 = (struct compat_ebt_entry_mwt *) buf;
2124 size = offsets[j] - offsets[i];
2125 ret = ebt_size_mwt(match32, size, i, state, base);
2126 if (ret < 0)
2127 return ret;
2128 new_offset += ret;
2129 if (offsets_update && new_offset) {
2130 pr_debug("ebtables: change offset %d to %d\n",
2131 offsets_update[i], offsets[j] + new_offset);
2132 offsets_update[i] = offsets[j] + new_offset;
2133 }
2134 }
2135
2136 startoff = state->buf_user_offset - startoff;
2137
2138 BUG_ON(*total < startoff);
2139 *total -= startoff;
2140 return 0;
2141}
2142
2143/*
2144 * repl->entries_size is the size of the ebt_entry blob in userspace.
2145 * It might need more memory when copied to a 64 bit kernel in case
2146 * userspace is 32-bit. So, first task: find out how much memory is needed.
2147 *
2148 * Called before validation is performed.
2149 */
2150static int compat_copy_entries(unsigned char *data, unsigned int size_user,
2151 struct ebt_entries_buf_state *state)
2152{
2153 unsigned int size_remaining = size_user;
2154 int ret;
2155
2156 ret = EBT_ENTRY_ITERATE(data, size_user, size_entry_mwt, data,
2157 &size_remaining, state);
2158 if (ret < 0)
2159 return ret;
2160
2161 WARN_ON(size_remaining);
2162 return state->buf_kern_offset;
2163}
2164
2165
2166static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl,
2167 void __user *user, unsigned int len)
2168{
2169 struct compat_ebt_replace tmp;
2170 int i;
2171
2172 if (len < sizeof(tmp))
2173 return -EINVAL;
2174
2175 if (copy_from_user(&tmp, user, sizeof(tmp)))
2176 return -EFAULT;
2177
2178 if (len != sizeof(tmp) + tmp.entries_size)
2179 return -EINVAL;
2180
2181 if (tmp.entries_size == 0)
2182 return -EINVAL;
2183
2184 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) /
2185 NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
2186 return -ENOMEM;
2187 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
2188 return -ENOMEM;
2189
2190 memcpy(repl, &tmp, offsetof(struct ebt_replace, hook_entry));
2191
2192 /* starting with hook_entry, 32 vs. 64 bit structures are different */
2193 for (i = 0; i < NF_BR_NUMHOOKS; i++)
2194 repl->hook_entry[i] = compat_ptr(tmp.hook_entry[i]);
2195
2196 repl->num_counters = tmp.num_counters;
2197 repl->counters = compat_ptr(tmp.counters);
2198 repl->entries = compat_ptr(tmp.entries);
2199 return 0;
2200}
2201
2202static int compat_do_replace(struct net *net, void __user *user,
2203 unsigned int len)
2204{
2205 int ret, i, countersize, size64;
2206 struct ebt_table_info *newinfo;
2207 struct ebt_replace tmp;
2208 struct ebt_entries_buf_state state;
2209 void *entries_tmp;
2210
2211 ret = compat_copy_ebt_replace_from_user(&tmp, user, len);
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;
2216 return ret;
2217 }
2218
2219 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
2220 newinfo = vmalloc(sizeof(*newinfo) + countersize);
2221 if (!newinfo)
2222 return -ENOMEM;
2223
2224 if (countersize)
2225 memset(newinfo->counters, 0, countersize);
2226
2227 memset(&state, 0, sizeof(state));
2228
2229 newinfo->entries = vmalloc(tmp.entries_size);
2230 if (!newinfo->entries) {
2231 ret = -ENOMEM;
2232 goto free_newinfo;
2233 }
2234 if (copy_from_user(
2235 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
2236 ret = -EFAULT;
2237 goto free_entries;
2238 }
2239
2240 entries_tmp = newinfo->entries;
2241
2242 xt_compat_lock(NFPROTO_BRIDGE);
2243
2244 ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
2245 if (ret < 0)
2246 goto out_unlock;
2247
2248 pr_debug("tmp.entries_size %d, kern off %d, user off %d delta %d\n",
2249 tmp.entries_size, state.buf_kern_offset, state.buf_user_offset,
2250 xt_compat_calc_jump(NFPROTO_BRIDGE, tmp.entries_size));
2251
2252 size64 = ret;
2253 newinfo->entries = vmalloc(size64);
2254 if (!newinfo->entries) {
2255 vfree(entries_tmp);
2256 ret = -ENOMEM;
2257 goto out_unlock;
2258 }
2259
2260 memset(&state, 0, sizeof(state));
2261 state.buf_kern_start = newinfo->entries;
2262 state.buf_kern_len = size64;
2263
2264 ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
2265 BUG_ON(ret < 0); /* parses same data again */
2266
2267 vfree(entries_tmp);
2268 tmp.entries_size = size64;
2269
2270 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
2271 char __user *usrptr;
2272 if (tmp.hook_entry[i]) {
2273 unsigned int delta;
2274 usrptr = (char __user *) tmp.hook_entry[i];
2275 delta = usrptr - tmp.entries;
2276 usrptr += xt_compat_calc_jump(NFPROTO_BRIDGE, delta);
2277 tmp.hook_entry[i] = (struct ebt_entries __user *)usrptr;
2278 }
2279 }
2280
2281 xt_compat_flush_offsets(NFPROTO_BRIDGE);
2282 xt_compat_unlock(NFPROTO_BRIDGE);
2283
2284 ret = do_replace_finish(net, &tmp, newinfo);
2285 if (ret == 0)
2286 return ret;
2287free_entries:
2288 vfree(newinfo->entries);
2289free_newinfo:
2290 vfree(newinfo);
2291 return ret;
2292out_unlock:
2293 xt_compat_flush_offsets(NFPROTO_BRIDGE);
2294 xt_compat_unlock(NFPROTO_BRIDGE);
2295 goto free_entries;
2296}
2297
2298static int compat_update_counters(struct net *net, void __user *user,
2299 unsigned int len)
2300{
2301 struct compat_ebt_replace hlp;
2302
2303 if (copy_from_user(&hlp, user, sizeof(hlp)))
2304 return -EFAULT;
2305
2306 /* try real handler in case userland supplied needed padding */
2307 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
2308 return update_counters(net, user, len);
2309
2310 return do_update_counters(net, hlp.name, compat_ptr(hlp.counters),
2311 hlp.num_counters, user, len);
2312}
2313
2314static int compat_do_ebt_set_ctl(struct sock *sk,
2315 int cmd, void __user *user, unsigned int len)
2316{
2317 int ret;
2318
2319 if (!capable(CAP_NET_ADMIN))
2320 return -EPERM;
2321
2322 switch (cmd) {
2323 case EBT_SO_SET_ENTRIES:
2324 ret = compat_do_replace(sock_net(sk), user, len);
2325 break;
2326 case EBT_SO_SET_COUNTERS:
2327 ret = compat_update_counters(sock_net(sk), user, len);
2328 break;
2329 default:
2330 ret = -EINVAL;
2331 }
2332 return ret;
2333}
2334
2335static int compat_do_ebt_get_ctl(struct sock *sk, int cmd,
2336 void __user *user, int *len)
2337{
2338 int ret;
2339 struct compat_ebt_replace tmp;
2340 struct ebt_table *t;
2341
2342 if (!capable(CAP_NET_ADMIN))
2343 return -EPERM;
2344
2345 /* try real handler in case userland supplied needed padding */
2346 if ((cmd == EBT_SO_GET_INFO ||
2347 cmd == EBT_SO_GET_INIT_INFO) && *len != sizeof(tmp))
2348 return do_ebt_get_ctl(sk, cmd, user, len);
2349
2350 if (copy_from_user(&tmp, user, sizeof(tmp)))
2351 return -EFAULT;
2352
2353 t = find_table_lock(sock_net(sk), tmp.name, &ret, &ebt_mutex);
2354 if (!t)
2355 return ret;
2356
2357 xt_compat_lock(NFPROTO_BRIDGE);
2358 switch (cmd) {
2359 case EBT_SO_GET_INFO:
2360 tmp.nentries = t->private->nentries;
2361 ret = compat_table_info(t->private, &tmp);
2362 if (ret)
2363 goto out;
2364 tmp.valid_hooks = t->valid_hooks;
2365
2366 if (copy_to_user(user, &tmp, *len) != 0) {
2367 ret = -EFAULT;
2368 break;
2369 }
2370 ret = 0;
2371 break;
2372 case EBT_SO_GET_INIT_INFO:
2373 tmp.nentries = t->table->nentries;
2374 tmp.entries_size = t->table->entries_size;
2375 tmp.valid_hooks = t->table->valid_hooks;
2376
2377 if (copy_to_user(user, &tmp, *len) != 0) {
2378 ret = -EFAULT;
2379 break;
2380 }
2381 ret = 0;
2382 break;
2383 case EBT_SO_GET_ENTRIES:
2384 case EBT_SO_GET_INIT_ENTRIES:
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);
2398 break;
2399 default:
2400 ret = -EINVAL;
2401 }
2402 out:
2403 xt_compat_flush_offsets(NFPROTO_BRIDGE);
2404 xt_compat_unlock(NFPROTO_BRIDGE);
2405 mutex_unlock(&ebt_mutex);
2406 return ret;
2407}
2408#endif
2409
1495static struct nf_sockopt_ops ebt_sockopts = 2410static struct nf_sockopt_ops ebt_sockopts =
1496{ 2411{
1497 .pf = PF_INET, 2412 .pf = PF_INET,
1498 .set_optmin = EBT_BASE_CTL, 2413 .set_optmin = EBT_BASE_CTL,
1499 .set_optmax = EBT_SO_SET_MAX + 1, 2414 .set_optmax = EBT_SO_SET_MAX + 1,
1500 .set = do_ebt_set_ctl, 2415 .set = do_ebt_set_ctl,
2416#ifdef CONFIG_COMPAT
2417 .compat_set = compat_do_ebt_set_ctl,
2418#endif
1501 .get_optmin = EBT_BASE_CTL, 2419 .get_optmin = EBT_BASE_CTL,
1502 .get_optmax = EBT_SO_GET_MAX + 1, 2420 .get_optmax = EBT_SO_GET_MAX + 1,
1503 .get = do_ebt_get_ctl, 2421 .get = do_ebt_get_ctl,
2422#ifdef CONFIG_COMPAT
2423 .compat_get = compat_do_ebt_get_ctl,
2424#endif
1504 .owner = THIS_MODULE, 2425 .owner = THIS_MODULE,
1505}; 2426};
1506 2427