]> git.karo-electronics.de Git - linux-beck.git/commitdiff
netfilter: fix IS_ERR_VALUE usage
authorPablo Neira Ayuso <pablo@netfilter.org>
Fri, 29 Apr 2016 08:39:34 +0000 (10:39 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 29 Apr 2016 09:02:33 +0000 (11:02 +0200)
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>
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 4dd9306c9d5623b4f35c9c8a85297ef5ec7cfa8f..dc4f58a3cdcc7a635b2c6da55fc0f727b7b7827b 100644 (file)
@@ -380,16 +380,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 60f5161abcb43a7dbe5cad53069d400ebe8df36e..3355ed72051d5bdafb580dbc6188991e3e6c1525 100644 (file)
@@ -513,11 +513,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 735d1ee8c1ab64cdcdb363ce7b47636b4388227d..21ccc19e1e6f504526cf38dca358f3dba3b2c398 100644 (file)
@@ -656,10 +656,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 73e606c719ef43e418a8ffd215f87e7a4bfede79..17874e83a9509b9d0b2c978e60ba4f1accc9a5ee 100644 (file)
@@ -669,10 +669,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;