On Tue, Apr 15, 2014 at 12:17:31AM +0200, Pablo Neira Ayuso wrote: > From: Thomas Graf <tgraf@xxxxxxx> > > upstream commit c58dd2dd443c26d856a168db108a0cd11c285bf3 > Thank you, I'll queue it for the 3.11 kernel as well. Cheers, -- Luís > All xtables variants suffer from the defect that the copy_to_user() > to copy the counters to user memory may fail after the table has > already been exchanged and thus exposed. Return an error at this > point will result in freeing the already exposed table. Any > subsequent packet processing will result in a kernel panic. > > We can't copy the counters before exposing the new tables as we > want provide the counter state after the old table has been > unhooked. Therefore convert this into a silent error. > > Cc: Florian Westphal <fw@xxxxxxxxx> > Signed-off-by: Thomas Graf <tgraf@xxxxxxx> > Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> > Cc: <stable@xxxxxxxxxxxxxxx> # 3.14.x > Cc: <stable@xxxxxxxxxxxxxxx> # 3.13.x > Cc: <stable@xxxxxxxxxxxxxxx> # 3.12.x > Cc: <stable@xxxxxxxxxxxxxxx> # 3.10.x > Cc: <stable@xxxxxxxxxxxxxxx> # 3.4.x > Cc: <stable@xxxxxxxxxxxxxxx> # 3.2.x > --- > net/bridge/netfilter/ebtables.c | 5 ++--- > net/ipv4/netfilter/arp_tables.c | 6 ++++-- > net/ipv4/netfilter/ip_tables.c | 6 ++++-- > net/ipv6/netfilter/ip6_tables.c | 6 ++++-- > 4 files changed, 14 insertions(+), 9 deletions(-) > > diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c > index 0e474b1..1059ed3 100644 > --- a/net/bridge/netfilter/ebtables.c > +++ b/net/bridge/netfilter/ebtables.c > @@ -1044,10 +1044,9 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl, > if (repl->num_counters && > copy_to_user(repl->counters, counterstmp, > repl->num_counters * sizeof(struct ebt_counter))) { > - ret = -EFAULT; > + /* Silent error, can't fail, new table is already in place */ > + net_warn_ratelimited("ebtables: counters copy to user failed while replacing table\n"); > } > - else > - ret = 0; > > /* decrease module count and free resources */ > EBT_ENTRY_ITERATE(table->entries, table->entries_size, > diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c > index 59da7cd..f95b6f9 100644 > --- a/net/ipv4/netfilter/arp_tables.c > +++ b/net/ipv4/netfilter/arp_tables.c > @@ -1044,8 +1044,10 @@ static int __do_replace(struct net *net, const char *name, > > xt_free_table_info(oldinfo); > if (copy_to_user(counters_ptr, counters, > - sizeof(struct xt_counters) * num_counters) != 0) > - ret = -EFAULT; > + sizeof(struct xt_counters) * num_counters) != 0) { > + /* Silent error, can't fail, new table is already in place */ > + net_warn_ratelimited("arptables: counters copy to user failed while replacing table\n"); > + } > vfree(counters); > xt_table_unlock(t); > return ret; > diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c > index 718dfbd..99e810f 100644 > --- a/net/ipv4/netfilter/ip_tables.c > +++ b/net/ipv4/netfilter/ip_tables.c > @@ -1231,8 +1231,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, > > xt_free_table_info(oldinfo); > if (copy_to_user(counters_ptr, counters, > - sizeof(struct xt_counters) * num_counters) != 0) > - ret = -EFAULT; > + sizeof(struct xt_counters) * num_counters) != 0) { > + /* Silent error, can't fail, new table is already in place */ > + net_warn_ratelimited("iptables: counters copy to user failed while replacing table\n"); > + } > vfree(counters); > xt_table_unlock(t); > return ret; > diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c > index 710238f..e080fbb 100644 > --- a/net/ipv6/netfilter/ip6_tables.c > +++ b/net/ipv6/netfilter/ip6_tables.c > @@ -1241,8 +1241,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, > > xt_free_table_info(oldinfo); > if (copy_to_user(counters_ptr, counters, > - sizeof(struct xt_counters) * num_counters) != 0) > - ret = -EFAULT; > + sizeof(struct xt_counters) * num_counters) != 0) { > + /* Silent error, can't fail, new table is already in place */ > + net_warn_ratelimited("ip6tables: counters copy to user failed while replacing table\n"); > + } > vfree(counters); > xt_table_unlock(t); > return ret; > -- > 1.7.10.4 > > -- > To unsubscribe from this list: send the line "unsubscribe stable" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html