Re: [PATCH] netfilter: Can't fail and free after table replacement

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]