Skip to content

Commit

Permalink
netfilter: fix IS_ERR_VALUE usage
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Pablo Neira Ayuso committed Apr 29, 2016
1 parent 6cd54fc commit 92b4423
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 9 deletions.
6 changes: 3 additions & 3 deletions include/linux/netfilter/x_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions net/ipv4/netfilter/arp_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 4 additions & 2 deletions net/ipv4/netfilter/ip_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions net/ipv6/netfilter/ip6_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 92b4423

Please sign in to comment.