]> git.hungrycats.org Git - linux/commitdiff
netfilter: fix IS_ERR_VALUE usage
authorPablo Neira Ayuso <pablo@netfilter.org>
Fri, 29 Apr 2016 08:39:34 +0000 (10:39 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 Jan 2018 11:06:10 +0000 (12:06 +0100)
commit 92b4423e3a0bc5d43ecde4bcad871f8b5ba04efd upstream.

This is a forward-port of the original patch from Andrzej Hajda,
he said:

"IS_ERR_VALUE should be used only with unsigned long type.
Otherwise it can work incorrectly. To achieve this function
xt_percpu_counter_alloc is modified to return unsigned long,
and its result is assigned to temporary variable to perform
error checking, before assigning to .pcnt field.

The patch follows conclusion from discussion on LKML [1][2].

[1]: http://permalink.gmane.org/gmane.linux.kernel/2120927
[2]: http://permalink.gmane.org/gmane.linux.kernel/2150581"

Original patch from Andrzej is here:

http://patchwork.ozlabs.org/patch/582970/

This patch has clashed with input validation fixes for x_tables.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Michal Kubecek <mkubecek@suse.cz>
include/linux/netfilter/x_tables.h
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_tables.c
net/ipv6/netfilter/ip6_tables.c

index 26a41ddd3dec0d07d4e69ec7806999ac76c9c778..d6c53fce006b688b8060a3708cbb6b780392beb3 100644 (file)
@@ -381,16 +381,16 @@ static inline unsigned long ifname_compare_aligned(const char *_a,
  * allows us to return 0 for single core systems without forcing
  * callers to deal with SMP vs. NONSMP issues.
  */
-static inline u64 xt_percpu_counter_alloc(void)
+static inline unsigned long xt_percpu_counter_alloc(void)
 {
        if (nr_cpu_ids > 1) {
                void __percpu *res = __alloc_percpu(sizeof(struct xt_counters),
                                                    sizeof(struct xt_counters));
 
                if (res == NULL)
-                       return (u64) -ENOMEM;
+                       return -ENOMEM;
 
-               return (u64) (__force unsigned long) res;
+               return (__force unsigned long) res;
        }
 
        return 0;
index c752115289911bedfb5bd7652763a848d40b07de..4cfcc22f7430d57cd6902a238a82a6b81f1f23ac 100644 (file)
@@ -511,11 +511,13 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)
 {
        struct xt_entry_target *t;
        struct xt_target *target;
+       unsigned long pcnt;
        int ret;
 
-       e->counters.pcnt = xt_percpu_counter_alloc();
-       if (IS_ERR_VALUE(e->counters.pcnt))
+       pcnt = xt_percpu_counter_alloc();
+       if (IS_ERR_VALUE(pcnt))
                return -ENOMEM;
+       e->counters.pcnt = pcnt;
 
        t = arpt_get_target(e);
        target = xt_request_find_target(NFPROTO_ARP, t->u.user.name,
index 2ba158f2cb729bb42c7741d30dfcbf4e0df188af..a98173d1ea97a73f8e31d4e29fc695f3500a09df 100644 (file)
@@ -653,10 +653,12 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
        unsigned int j;
        struct xt_mtchk_param mtpar;
        struct xt_entry_match *ematch;
+       unsigned long pcnt;
 
-       e->counters.pcnt = xt_percpu_counter_alloc();
-       if (IS_ERR_VALUE(e->counters.pcnt))
+       pcnt = xt_percpu_counter_alloc();
+       if (IS_ERR_VALUE(pcnt))
                return -ENOMEM;
+       e->counters.pcnt = pcnt;
 
        j = 0;
        mtpar.net       = net;
index c26bed92f523bb6df8063cdd3aca0cbd95526bad..bb1b5453a7a1ee7bf54b8763a4de6d54e18e9632 100644 (file)
@@ -666,10 +666,12 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
        unsigned int j;
        struct xt_mtchk_param mtpar;
        struct xt_entry_match *ematch;
+       unsigned long pcnt;
 
-       e->counters.pcnt = xt_percpu_counter_alloc();
-       if (IS_ERR_VALUE(e->counters.pcnt))
+       pcnt = xt_percpu_counter_alloc();
+       if (IS_ERR_VALUE(pcnt))
                return -ENOMEM;
+       e->counters.pcnt = pcnt;
 
        j = 0;
        mtpar.net       = net;