mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-16 03:28:40 +00:00
[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>
This commit is contained in:
parent
73cd598df4
commit
b386d9f596
3 changed files with 70 additions and 59 deletions
|
@ -424,6 +424,10 @@ struct compat_xt_counters_info
|
||||||
extern void xt_compat_lock(int af);
|
extern void xt_compat_lock(int af);
|
||||||
extern void xt_compat_unlock(int af);
|
extern void xt_compat_unlock(int af);
|
||||||
|
|
||||||
|
extern int xt_compat_add_offset(int af, unsigned int offset, short delta);
|
||||||
|
extern void xt_compat_flush_offsets(int af);
|
||||||
|
extern short xt_compat_calc_jump(int af, unsigned int offset);
|
||||||
|
|
||||||
extern int xt_compat_match_offset(struct xt_match *match);
|
extern int xt_compat_match_offset(struct xt_match *match);
|
||||||
extern int xt_compat_match_from_user(struct xt_entry_match *m,
|
extern int xt_compat_match_from_user(struct xt_entry_match *m,
|
||||||
void **dstptr, int *size);
|
void **dstptr, int *size);
|
||||||
|
|
|
@ -1014,63 +1014,12 @@ copy_entries_to_user(unsigned int total_size,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
struct compat_delta {
|
|
||||||
struct compat_delta *next;
|
|
||||||
unsigned int offset;
|
|
||||||
short delta;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct compat_delta *compat_offsets;
|
|
||||||
|
|
||||||
static int compat_add_offset(unsigned int offset, short delta)
|
|
||||||
{
|
|
||||||
struct compat_delta *tmp;
|
|
||||||
|
|
||||||
tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
|
|
||||||
if (!tmp)
|
|
||||||
return -ENOMEM;
|
|
||||||
tmp->offset = offset;
|
|
||||||
tmp->delta = delta;
|
|
||||||
if (compat_offsets) {
|
|
||||||
tmp->next = compat_offsets->next;
|
|
||||||
compat_offsets->next = tmp;
|
|
||||||
} else {
|
|
||||||
compat_offsets = tmp;
|
|
||||||
tmp->next = NULL;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void compat_flush_offsets(void)
|
|
||||||
{
|
|
||||||
struct compat_delta *tmp, *next;
|
|
||||||
|
|
||||||
if (compat_offsets) {
|
|
||||||
for (tmp = compat_offsets; tmp; tmp = next) {
|
|
||||||
next = tmp->next;
|
|
||||||
kfree(tmp);
|
|
||||||
}
|
|
||||||
compat_offsets = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static short compat_calc_jump(unsigned int offset)
|
|
||||||
{
|
|
||||||
struct compat_delta *tmp;
|
|
||||||
short delta;
|
|
||||||
|
|
||||||
for (tmp = compat_offsets, delta = 0; tmp; tmp = tmp->next)
|
|
||||||
if (tmp->offset < offset)
|
|
||||||
delta += tmp->delta;
|
|
||||||
return delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void compat_standard_from_user(void *dst, void *src)
|
static void compat_standard_from_user(void *dst, void *src)
|
||||||
{
|
{
|
||||||
int v = *(compat_int_t *)src;
|
int v = *(compat_int_t *)src;
|
||||||
|
|
||||||
if (v > 0)
|
if (v > 0)
|
||||||
v += compat_calc_jump(v);
|
v += xt_compat_calc_jump(AF_INET, v);
|
||||||
memcpy(dst, &v, sizeof(v));
|
memcpy(dst, &v, sizeof(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1079,7 +1028,7 @@ static int compat_standard_to_user(void __user *dst, void *src)
|
||||||
compat_int_t cv = *(int *)src;
|
compat_int_t cv = *(int *)src;
|
||||||
|
|
||||||
if (cv > 0)
|
if (cv > 0)
|
||||||
cv -= compat_calc_jump(cv);
|
cv -= xt_compat_calc_jump(AF_INET, cv);
|
||||||
return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
|
return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1104,7 +1053,7 @@ static int compat_calc_entry(struct ipt_entry *e,
|
||||||
t = ipt_get_target(e);
|
t = ipt_get_target(e);
|
||||||
off += xt_compat_target_offset(t->u.kernel.target);
|
off += xt_compat_target_offset(t->u.kernel.target);
|
||||||
newinfo->size -= off;
|
newinfo->size -= off;
|
||||||
ret = compat_add_offset(entry_offset, off);
|
ret = xt_compat_add_offset(AF_INET, entry_offset, off);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -1167,7 +1116,7 @@ static int get_info(void __user *user, int *len, int compat)
|
||||||
if (compat) {
|
if (compat) {
|
||||||
struct xt_table_info tmp;
|
struct xt_table_info tmp;
|
||||||
ret = compat_table_info(private, &tmp);
|
ret = compat_table_info(private, &tmp);
|
||||||
compat_flush_offsets();
|
xt_compat_flush_offsets(AF_INET);
|
||||||
private = &tmp;
|
private = &tmp;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1631,7 +1580,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
|
||||||
|
|
||||||
off += xt_compat_target_offset(target);
|
off += xt_compat_target_offset(target);
|
||||||
*size += off;
|
*size += off;
|
||||||
ret = compat_add_offset(entry_offset, off);
|
ret = xt_compat_add_offset(AF_INET, entry_offset, off);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1797,7 +1746,7 @@ translate_compat_table(const char *name,
|
||||||
ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
|
ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
|
||||||
compat_copy_entry_from_user, &pos, &size,
|
compat_copy_entry_from_user, &pos, &size,
|
||||||
name, newinfo, entry1);
|
name, newinfo, entry1);
|
||||||
compat_flush_offsets();
|
xt_compat_flush_offsets(AF_INET);
|
||||||
xt_compat_unlock(AF_INET);
|
xt_compat_unlock(AF_INET);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto free_newinfo;
|
goto free_newinfo;
|
||||||
|
@ -1834,7 +1783,7 @@ out:
|
||||||
COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
|
COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
|
||||||
return ret;
|
return ret;
|
||||||
out_unlock:
|
out_unlock:
|
||||||
compat_flush_offsets();
|
xt_compat_flush_offsets(AF_INET);
|
||||||
xt_compat_unlock(AF_INET);
|
xt_compat_unlock(AF_INET);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1997,7 +1946,7 @@ compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len)
|
||||||
get.size);
|
get.size);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
compat_flush_offsets();
|
xt_compat_flush_offsets(AF_INET);
|
||||||
module_put(t->me);
|
module_put(t->me);
|
||||||
xt_table_unlock(t);
|
xt_table_unlock(t);
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -34,12 +34,21 @@ MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
|
||||||
|
|
||||||
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
|
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
|
||||||
|
|
||||||
|
struct compat_delta {
|
||||||
|
struct compat_delta *next;
|
||||||
|
unsigned int offset;
|
||||||
|
short delta;
|
||||||
|
};
|
||||||
|
|
||||||
struct xt_af {
|
struct xt_af {
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
struct list_head match;
|
struct list_head match;
|
||||||
struct list_head target;
|
struct list_head target;
|
||||||
struct list_head tables;
|
struct list_head tables;
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
struct mutex compat_mutex;
|
struct mutex compat_mutex;
|
||||||
|
struct compat_delta *compat_offsets;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct xt_af *xt;
|
static struct xt_af *xt;
|
||||||
|
@ -335,6 +344,54 @@ int xt_check_match(const struct xt_match *match, unsigned short family,
|
||||||
EXPORT_SYMBOL_GPL(xt_check_match);
|
EXPORT_SYMBOL_GPL(xt_check_match);
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
|
int xt_compat_add_offset(int af, unsigned int offset, short delta)
|
||||||
|
{
|
||||||
|
struct compat_delta *tmp;
|
||||||
|
|
||||||
|
tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
|
||||||
|
if (!tmp)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
tmp->offset = offset;
|
||||||
|
tmp->delta = delta;
|
||||||
|
|
||||||
|
if (xt[af].compat_offsets) {
|
||||||
|
tmp->next = xt[af].compat_offsets->next;
|
||||||
|
xt[af].compat_offsets->next = tmp;
|
||||||
|
} else {
|
||||||
|
xt[af].compat_offsets = tmp;
|
||||||
|
tmp->next = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(xt_compat_add_offset);
|
||||||
|
|
||||||
|
void xt_compat_flush_offsets(int af)
|
||||||
|
{
|
||||||
|
struct compat_delta *tmp, *next;
|
||||||
|
|
||||||
|
if (xt[af].compat_offsets) {
|
||||||
|
for (tmp = xt[af].compat_offsets; tmp; tmp = next) {
|
||||||
|
next = tmp->next;
|
||||||
|
kfree(tmp);
|
||||||
|
}
|
||||||
|
xt[af].compat_offsets = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(xt_compat_flush_offsets);
|
||||||
|
|
||||||
|
short xt_compat_calc_jump(int af, unsigned int offset)
|
||||||
|
{
|
||||||
|
struct compat_delta *tmp;
|
||||||
|
short delta;
|
||||||
|
|
||||||
|
for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next)
|
||||||
|
if (tmp->offset < offset)
|
||||||
|
delta += tmp->delta;
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(xt_compat_calc_jump);
|
||||||
|
|
||||||
int xt_compat_match_offset(struct xt_match *match)
|
int xt_compat_match_offset(struct xt_match *match)
|
||||||
{
|
{
|
||||||
u_int16_t csize = match->compatsize ? : match->matchsize;
|
u_int16_t csize = match->compatsize ? : match->matchsize;
|
||||||
|
@ -873,6 +930,7 @@ static int __init xt_init(void)
|
||||||
mutex_init(&xt[i].mutex);
|
mutex_init(&xt[i].mutex);
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
mutex_init(&xt[i].compat_mutex);
|
mutex_init(&xt[i].compat_mutex);
|
||||||
|
xt[i].compat_offsets = NULL;
|
||||||
#endif
|
#endif
|
||||||
INIT_LIST_HEAD(&xt[i].target);
|
INIT_LIST_HEAD(&xt[i].target);
|
||||||
INIT_LIST_HEAD(&xt[i].match);
|
INIT_LIST_HEAD(&xt[i].match);
|
||||||
|
|
Loading…
Add table
Reference in a new issue