aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-12-18 00:47:48 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:58:31 -0500
commitb386d9f5960a9afce7f077edf2095fccfbb1a8e6 (patch)
treec7ccccf204ef62c239a87943c160a3bf25f97895
parent73cd598df46a73d6f02063f2520df115a9b88aa5 (diff)
[NETFILTER]: ip_tables: move compat offset calculation to x_tables
Its needed by ip6_tables and arp_tables as well. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netfilter/x_tables.h4
-rw-r--r--net/ipv4/netfilter/ip_tables.c67
-rw-r--r--net/netfilter/x_tables.c58
3 files changed, 70 insertions, 59 deletions
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 8ab754e14ec0..b99ede51318a 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -424,6 +424,10 @@ struct compat_xt_counters_info
424extern void xt_compat_lock(int af); 424extern void xt_compat_lock(int af);
425extern void xt_compat_unlock(int af); 425extern void xt_compat_unlock(int af);
426 426
427extern int xt_compat_add_offset(int af, unsigned int offset, short delta);
428extern void xt_compat_flush_offsets(int af);
429extern short xt_compat_calc_jump(int af, unsigned int offset);
430
427extern int xt_compat_match_offset(struct xt_match *match); 431extern int xt_compat_match_offset(struct xt_match *match);
428extern int xt_compat_match_from_user(struct xt_entry_match *m, 432extern int xt_compat_match_from_user(struct xt_entry_match *m,
429 void **dstptr, int *size); 433 void **dstptr, int *size);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index d8caa1ed4879..07be12cc3fe3 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1014,63 +1014,12 @@ copy_entries_to_user(unsigned int total_size,
1014} 1014}
1015 1015
1016#ifdef CONFIG_COMPAT 1016#ifdef CONFIG_COMPAT
1017struct compat_delta {
1018 struct compat_delta *next;
1019 unsigned int offset;
1020 short delta;
1021};
1022
1023static struct compat_delta *compat_offsets;
1024
1025static int compat_add_offset(unsigned int offset, short delta)
1026{
1027 struct compat_delta *tmp;
1028
1029 tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
1030 if (!tmp)
1031 return -ENOMEM;
1032 tmp->offset = offset;
1033 tmp->delta = delta;
1034 if (compat_offsets) {
1035 tmp->next = compat_offsets->next;
1036 compat_offsets->next = tmp;
1037 } else {
1038 compat_offsets = tmp;
1039 tmp->next = NULL;
1040 }
1041 return 0;
1042}
1043
1044static void compat_flush_offsets(void)
1045{
1046 struct compat_delta *tmp, *next;
1047
1048 if (compat_offsets) {
1049 for (tmp = compat_offsets; tmp; tmp = next) {
1050 next = tmp->next;
1051 kfree(tmp);
1052 }
1053 compat_offsets = NULL;
1054 }
1055}
1056
1057static short compat_calc_jump(unsigned int offset)
1058{
1059 struct compat_delta *tmp;
1060 short delta;
1061
1062 for (tmp = compat_offsets, delta = 0; tmp; tmp = tmp->next)
1063 if (tmp->offset < offset)
1064 delta += tmp->delta;
1065 return delta;
1066}
1067
1068static void compat_standard_from_user(void *dst, void *src) 1017static void compat_standard_from_user(void *dst, void *src)
1069{ 1018{
1070 int v = *(compat_int_t *)src; 1019 int v = *(compat_int_t *)src;
1071 1020
1072 if (v > 0) 1021 if (v > 0)
1073 v += compat_calc_jump(v); 1022 v += xt_compat_calc_jump(AF_INET, v);
1074 memcpy(dst, &v, sizeof(v)); 1023 memcpy(dst, &v, sizeof(v));
1075} 1024}
1076 1025
@@ -1079,7 +1028,7 @@ static int compat_standard_to_user(void __user *dst, void *src)
1079 compat_int_t cv = *(int *)src; 1028 compat_int_t cv = *(int *)src;
1080 1029
1081 if (cv > 0) 1030 if (cv > 0)
1082 cv -= compat_calc_jump(cv); 1031 cv -= xt_compat_calc_jump(AF_INET, cv);
1083 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; 1032 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1084} 1033}
1085 1034
@@ -1104,7 +1053,7 @@ static int compat_calc_entry(struct ipt_entry *e,
1104 t = ipt_get_target(e); 1053 t = ipt_get_target(e);
1105 off += xt_compat_target_offset(t->u.kernel.target); 1054 off += xt_compat_target_offset(t->u.kernel.target);
1106 newinfo->size -= off; 1055 newinfo->size -= off;
1107 ret = compat_add_offset(entry_offset, off); 1056 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1108 if (ret) 1057 if (ret)
1109 return ret; 1058 return ret;
1110 1059
@@ -1167,7 +1116,7 @@ static int get_info(void __user *user, int *len, int compat)
1167 if (compat) { 1116 if (compat) {
1168 struct xt_table_info tmp; 1117 struct xt_table_info tmp;
1169 ret = compat_table_info(private, &tmp); 1118 ret = compat_table_info(private, &tmp);
1170 compat_flush_offsets(); 1119 xt_compat_flush_offsets(AF_INET);
1171 private = &tmp; 1120 private = &tmp;
1172 } 1121 }
1173#endif 1122#endif
@@ -1631,7 +1580,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1631 1580
1632 off += xt_compat_target_offset(target); 1581 off += xt_compat_target_offset(target);
1633 *size += off; 1582 *size += off;
1634 ret = compat_add_offset(entry_offset, off); 1583 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1635 if (ret) 1584 if (ret)
1636 goto out; 1585 goto out;
1637 1586
@@ -1797,7 +1746,7 @@ translate_compat_table(const char *name,
1797 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, 1746 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1798 compat_copy_entry_from_user, &pos, &size, 1747 compat_copy_entry_from_user, &pos, &size,
1799 name, newinfo, entry1); 1748 name, newinfo, entry1);
1800 compat_flush_offsets(); 1749 xt_compat_flush_offsets(AF_INET);
1801 xt_compat_unlock(AF_INET); 1750 xt_compat_unlock(AF_INET);
1802 if (ret) 1751 if (ret)
1803 goto free_newinfo; 1752 goto free_newinfo;
@@ -1834,7 +1783,7 @@ out:
1834 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); 1783 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1835 return ret; 1784 return ret;
1836out_unlock: 1785out_unlock:
1837 compat_flush_offsets(); 1786 xt_compat_flush_offsets(AF_INET);
1838 xt_compat_unlock(AF_INET); 1787 xt_compat_unlock(AF_INET);
1839 goto out; 1788 goto out;
1840} 1789}
@@ -1997,7 +1946,7 @@ compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len)
1997 get.size); 1946 get.size);
1998 ret = -EINVAL; 1947 ret = -EINVAL;
1999 } 1948 }
2000 compat_flush_offsets(); 1949 xt_compat_flush_offsets(AF_INET);
2001 module_put(t->me); 1950 module_put(t->me);
2002 xt_table_unlock(t); 1951 xt_table_unlock(t);
2003 } else 1952 } else
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index b95284ee4fd4..8d4fca96a4a7 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -34,12 +34,21 @@ MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
34 34
35#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) 35#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
36 36
37struct compat_delta {
38 struct compat_delta *next;
39 unsigned int offset;
40 short delta;
41};
42
37struct xt_af { 43struct xt_af {
38 struct mutex mutex; 44 struct mutex mutex;
39 struct list_head match; 45 struct list_head match;
40 struct list_head target; 46 struct list_head target;
41 struct list_head tables; 47 struct list_head tables;
48#ifdef CONFIG_COMPAT
42 struct mutex compat_mutex; 49 struct mutex compat_mutex;
50 struct compat_delta *compat_offsets;
51#endif
43}; 52};
44 53
45static struct xt_af *xt; 54static struct xt_af *xt;
@@ -335,6 +344,54 @@ int xt_check_match(const struct xt_match *match, unsigned short family,
335EXPORT_SYMBOL_GPL(xt_check_match); 344EXPORT_SYMBOL_GPL(xt_check_match);
336 345
337#ifdef CONFIG_COMPAT 346#ifdef CONFIG_COMPAT
347int xt_compat_add_offset(int af, unsigned int offset, short delta)
348{
349 struct compat_delta *tmp;
350
351 tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
352 if (!tmp)
353 return -ENOMEM;
354
355 tmp->offset = offset;
356 tmp->delta = delta;
357
358 if (xt[af].compat_offsets) {
359 tmp->next = xt[af].compat_offsets->next;
360 xt[af].compat_offsets->next = tmp;
361 } else {
362 xt[af].compat_offsets = tmp;
363 tmp->next = NULL;
364 }
365 return 0;
366}
367EXPORT_SYMBOL_GPL(xt_compat_add_offset);
368
369void xt_compat_flush_offsets(int af)
370{
371 struct compat_delta *tmp, *next;
372
373 if (xt[af].compat_offsets) {
374 for (tmp = xt[af].compat_offsets; tmp; tmp = next) {
375 next = tmp->next;
376 kfree(tmp);
377 }
378 xt[af].compat_offsets = NULL;
379 }
380}
381EXPORT_SYMBOL_GPL(xt_compat_flush_offsets);
382
383short xt_compat_calc_jump(int af, unsigned int offset)
384{
385 struct compat_delta *tmp;
386 short delta;
387
388 for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next)
389 if (tmp->offset < offset)
390 delta += tmp->delta;
391 return delta;
392}
393EXPORT_SYMBOL_GPL(xt_compat_calc_jump);
394
338int xt_compat_match_offset(struct xt_match *match) 395int xt_compat_match_offset(struct xt_match *match)
339{ 396{
340 u_int16_t csize = match->compatsize ? : match->matchsize; 397 u_int16_t csize = match->compatsize ? : match->matchsize;
@@ -873,6 +930,7 @@ static int __init xt_init(void)
873 mutex_init(&xt[i].mutex); 930 mutex_init(&xt[i].mutex);
874#ifdef CONFIG_COMPAT 931#ifdef CONFIG_COMPAT
875 mutex_init(&xt[i].compat_mutex); 932 mutex_init(&xt[i].compat_mutex);
933 xt[i].compat_offsets = NULL;
876#endif 934#endif
877 INIT_LIST_HEAD(&xt[i].target); 935 INIT_LIST_HEAD(&xt[i].target);
878 INIT_LIST_HEAD(&xt[i].match); 936 INIT_LIST_HEAD(&xt[i].match);