EXPORT_SYMBOL_GPL(xt_compat_match_offset);
int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
- int *size)
+ unsigned int *size)
{
struct xt_match *match = m->u.kernel.match;
struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr,
- int *size)
+ unsigned int *size)
{
struct xt_match *match = m->u.kernel.match;
struct compat_xt_entry_match __user *cm = *dstptr;
EXPORT_SYMBOL_GPL(xt_compat_target_offset);
void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
- int *size)
+ unsigned int *size)
{
struct xt_target *target = t->u.kernel.target;
struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
EXPORT_SYMBOL_GPL(xt_compat_target_from_user);
int xt_compat_target_to_user(struct xt_entry_target *t, void __user **dstptr,
- int *size)
+ unsigned int *size)
{
struct xt_target *target = t->u.kernel.target;
struct compat_xt_entry_target __user *ct = *dstptr;
struct xt_table_info *private;
struct xt_table *t;
+ /* Don't add one object to multiple lists. */
+ table = kmemdup(table, sizeof(struct xt_table), GFP_KERNEL);
+ if (!table) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
ret = mutex_lock_interruptible(&xt[table->af].mutex);
if (ret != 0)
- goto out;
+ goto out_free;
/* Don't autoload: we'd eat our tail... */
list_for_each_entry(t, &net->xt.tables[table->af], list) {
unlock:
mutex_unlock(&xt[table->af].mutex);
+out_free:
+ kfree(table);
out:
return ERR_PTR(ret);
}
private = table->private;
list_del(&table->list);
mutex_unlock(&xt[table->af].mutex);
+ kfree(table);
return private;
}