|
@@ -38,9 +38,8 @@ MODULE_DESCRIPTION("{ip,ip6,arp,eb}_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 {
|
|
- struct compat_delta *next;
|
|
|
|
- unsigned int offset;
|
|
|
|
- int delta;
|
|
|
|
|
|
+ unsigned int offset; /* offset in kernel */
|
|
|
|
+ int delta; /* delta in 32bit user land */
|
|
};
|
|
};
|
|
|
|
|
|
struct xt_af {
|
|
struct xt_af {
|
|
@@ -49,7 +48,9 @@ struct xt_af {
|
|
struct list_head target;
|
|
struct list_head target;
|
|
#ifdef CONFIG_COMPAT
|
|
#ifdef CONFIG_COMPAT
|
|
struct mutex compat_mutex;
|
|
struct mutex compat_mutex;
|
|
- struct compat_delta *compat_offsets;
|
|
|
|
|
|
+ struct compat_delta *compat_tab;
|
|
|
|
+ unsigned int number; /* number of slots in compat_tab[] */
|
|
|
|
+ unsigned int cur; /* number of used slots in compat_tab[] */
|
|
#endif
|
|
#endif
|
|
};
|
|
};
|
|
|
|
|
|
@@ -414,54 +415,67 @@ int xt_check_match(struct xt_mtchk_param *par,
|
|
EXPORT_SYMBOL_GPL(xt_check_match);
|
|
EXPORT_SYMBOL_GPL(xt_check_match);
|
|
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
#ifdef CONFIG_COMPAT
|
|
-int xt_compat_add_offset(u_int8_t af, unsigned int offset, short delta)
|
|
|
|
|
|
+int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta)
|
|
{
|
|
{
|
|
- struct compat_delta *tmp;
|
|
|
|
|
|
+ struct xt_af *xp = &xt[af];
|
|
|
|
|
|
- tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
|
|
|
|
- if (!tmp)
|
|
|
|
- return -ENOMEM;
|
|
|
|
|
|
+ if (!xp->compat_tab) {
|
|
|
|
+ if (!xp->number)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ xp->compat_tab = vmalloc(sizeof(struct compat_delta) * xp->number);
|
|
|
|
+ if (!xp->compat_tab)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ xp->cur = 0;
|
|
|
|
+ }
|
|
|
|
|
|
- tmp->offset = offset;
|
|
|
|
- tmp->delta = delta;
|
|
|
|
|
|
+ if (xp->cur >= xp->number)
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
- 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;
|
|
|
|
- }
|
|
|
|
|
|
+ if (xp->cur)
|
|
|
|
+ delta += xp->compat_tab[xp->cur - 1].delta;
|
|
|
|
+ xp->compat_tab[xp->cur].offset = offset;
|
|
|
|
+ xp->compat_tab[xp->cur].delta = delta;
|
|
|
|
+ xp->cur++;
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(xt_compat_add_offset);
|
|
EXPORT_SYMBOL_GPL(xt_compat_add_offset);
|
|
|
|
|
|
void xt_compat_flush_offsets(u_int8_t af)
|
|
void xt_compat_flush_offsets(u_int8_t 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;
|
|
|
|
|
|
+ if (xt[af].compat_tab) {
|
|
|
|
+ vfree(xt[af].compat_tab);
|
|
|
|
+ xt[af].compat_tab = NULL;
|
|
|
|
+ xt[af].number = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(xt_compat_flush_offsets);
|
|
EXPORT_SYMBOL_GPL(xt_compat_flush_offsets);
|
|
|
|
|
|
int xt_compat_calc_jump(u_int8_t af, unsigned int offset)
|
|
int xt_compat_calc_jump(u_int8_t af, unsigned int offset)
|
|
{
|
|
{
|
|
- struct compat_delta *tmp;
|
|
|
|
- int delta;
|
|
|
|
-
|
|
|
|
- for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next)
|
|
|
|
- if (tmp->offset < offset)
|
|
|
|
- delta += tmp->delta;
|
|
|
|
- return delta;
|
|
|
|
|
|
+ struct compat_delta *tmp = xt[af].compat_tab;
|
|
|
|
+ int mid, left = 0, right = xt[af].cur - 1;
|
|
|
|
+
|
|
|
|
+ while (left <= right) {
|
|
|
|
+ mid = (left + right) >> 1;
|
|
|
|
+ if (offset > tmp[mid].offset)
|
|
|
|
+ left = mid + 1;
|
|
|
|
+ else if (offset < tmp[mid].offset)
|
|
|
|
+ right = mid - 1;
|
|
|
|
+ else
|
|
|
|
+ return mid ? tmp[mid - 1].delta : 0;
|
|
|
|
+ }
|
|
|
|
+ WARN_ON_ONCE(1);
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(xt_compat_calc_jump);
|
|
EXPORT_SYMBOL_GPL(xt_compat_calc_jump);
|
|
|
|
|
|
|
|
+void xt_compat_init_offsets(u_int8_t af, unsigned int number)
|
|
|
|
+{
|
|
|
|
+ xt[af].number = number;
|
|
|
|
+ xt[af].cur = 0;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(xt_compat_init_offsets);
|
|
|
|
+
|
|
int xt_compat_match_offset(const struct xt_match *match)
|
|
int xt_compat_match_offset(const struct xt_match *match)
|
|
{
|
|
{
|
|
u_int16_t csize = match->compatsize ? : match->matchsize;
|
|
u_int16_t csize = match->compatsize ? : match->matchsize;
|
|
@@ -1337,7 +1351,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;
|
|
|
|
|
|
+ xt[i].compat_tab = 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);
|