From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965078AbcBQCbh (ORCPT ); Tue, 16 Feb 2016 21:31:37 -0500 Received: from zeniv.linux.org.uk ([195.92.253.2]:59267 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965026AbcBQCbg (ORCPT ); Tue, 16 Feb 2016 21:31:36 -0500 Date: Wed, 17 Feb 2016 02:31:27 +0000 From: Al Viro To: Andrzej Hajda Cc: linux-kernel@vger.kernel.org, Bartlomiej Zolnierkiewicz , Marek Szyprowski , Pablo Neira Ayuso , Patrick McHardy , Jozsef Kadlecsik , "David S. Miller" , Alexey Kuznetsov , James Morris , Hideaki YOSHIFUJI , netfilter-devel@vger.kernel.org, coreteam@netfilter.org Subject: Re: [PATCH 1/7] netfilter: fix IS_ERR_VALUE usage Message-ID: <20160217023127.GG17997@ZenIV.linux.org.uk> References: <1455546925-22119-1-git-send-email-a.hajda@samsung.com> <1455546925-22119-2-git-send-email-a.hajda@samsung.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1455546925-22119-2-git-send-email-a.hajda@samsung.com> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, Feb 15, 2016 at 03:35:19PM +0100, Andrzej Hajda wrote: > 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. Wrong fix, IMO. Just have an anon union of u64 pcnt and struct xt_counters __percpu *pcpu in there. And make this > +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; take struct xt_counters * and return 0 or -ENOMEM. Storing the result of allocation in ->pcpu of passed structure. I mean, look at the callers - > - 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; should be if (xt_percpu_counter_alloc(&e->counters) < 0) return -ENOMEM; and similar for the rest of callers. Moreover, if you look at the _users_ of that fields, you'll see that a bunch of those actually want to use ->pcpu instead of doing all those casts. Really, that's the point - IS_ERR_VALUE is a big red flag saying "we need to figure out what's going on in that place", which does include reading through the code. Mechanical "solutions" like that only hide the problem.