From patchwork Wed Aug 16 23:19:59 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Dumazet X-Patchwork-Id: 802274 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="JbXhakQi"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3xXlgS3Rdwz9t31 for ; Thu, 17 Aug 2017 09:20:04 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752524AbdHPXUC (ORCPT ); Wed, 16 Aug 2017 19:20:02 -0400 Received: from mail-pg0-f65.google.com ([74.125.83.65]:36471 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752382AbdHPXUB (ORCPT ); Wed, 16 Aug 2017 19:20:01 -0400 Received: by mail-pg0-f65.google.com with SMTP id y129so6801522pgy.3 for ; Wed, 16 Aug 2017 16:20:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:subject:from:to:cc:date:in-reply-to:references :mime-version:content-transfer-encoding; bh=OQD2LxETcukR/cDI1aZokcIf1DR1Ie51Ryt3825kccg=; b=JbXhakQiOEHri5ovDj+srSGTBgXgYeJlQOqCzzza3evnSZccuWy/fDc//EB6O7g0LF t5ZmpXIRe9hlBAXPCw9R/yvyRT/iZmVBn+OKC8nP5I//zNDfJkRr7yDIh5A1ri/9wZ/I q+Na49+Ly2J+/WO7bV0pW6ZOfy1V/adxipVFYfIs5VcTJsH5lT36ODlojlLsMSwzE1Ga fZgIXjiOrUFvfTXmtdr/FEGs9zqUns6OdYb8r06Uwp6ixaoXRoZHCmifgi0fpL2FHODm 5D8rqXWiao6BOJJUWHeoQy6gIODaScuWt6Nj7XDvr20ya+vMee0shlBKNTfR212aMvAJ bSLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:subject:from:to:cc:date:in-reply-to :references:mime-version:content-transfer-encoding; bh=OQD2LxETcukR/cDI1aZokcIf1DR1Ie51Ryt3825kccg=; b=TfFoM23i15qKMtiju1Bi0yvZLRz7Q9QKJQCp1n48ucCyB0UvPDIEJv+0Br3J2NAVoI FYaluK4MBn/22NqBYFdQg0Eisf4v9lXNzsKt+KHfP1gOkWhSIh9NfpXuUcoJuRYqiytD 7+saPh9/pZC8EqFEW1RGZGcORQ83/OSFNljnMsWPIit6Xl1jTcXxzYzTpqK2K/YNG6zc O5kP2yZjX2RhQ3mrFCigJnPMiqGeuFUVsFueIrYVrQ0/9hu6WS4jNcW7cT8hsI+/dl/+ 5niu1T7gahMtq6ieDdvLAgRKNAqKVlNgHS7wJEP+fV6JqOHnmGKLPRXG8/QshmGik5IS Tisg== X-Gm-Message-State: AHYfb5iQz6UDqhhOajtnUe/02lz+2GegIjrHcqY31CovBNlE2NynSUxg 0OGa42TjOiB64H3U X-Received: by 10.99.155.10 with SMTP id r10mr3152809pgd.60.1502925600605; Wed, 16 Aug 2017 16:20:00 -0700 (PDT) Received: from ?IPv6:2620:15c:2c1:100:8493:de8d:b401:3f85? ([2620:15c:2c1:100:8493:de8d:b401:3f85]) by smtp.googlemail.com with ESMTPSA id j63sm3108505pge.88.2017.08.16.16.19.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 16 Aug 2017 16:19:59 -0700 (PDT) Message-ID: <1502925599.4936.153.camel@edumazet-glaptop3.roam.corp.google.com> Subject: [PATCH v2 net-next] ipv4: convert dst_metrics.refcnt from atomic_t to refcount_t From: Eric Dumazet To: David Miller Cc: netdev Date: Wed, 16 Aug 2017 16:19:59 -0700 In-Reply-To: <1502911469.4936.148.camel@edumazet-glaptop3.roam.corp.google.com> References: <1502911469.4936.148.camel@edumazet-glaptop3.roam.corp.google.com> X-Mailer: Evolution 3.10.4-0ubuntu2 Mime-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Eric Dumazet refcount_t type and corresponding API should be used instead of atomic_t when the variable is used as a reference counter. This allows to avoid accidental refcounter overflows that might lead to use-after-free situations. Signed-off-by: Eric Dumazet --- v2: fix a missing change in net/ipv4/fib_semantics.c include/net/dst.h | 2 +- net/core/dst.c | 6 +++--- net/ipv4/fib_semantics.c | 4 ++-- net/ipv4/route.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index f73611ec401754d4f52b5310a24da53566dafce6..dd38177c3a61f5c4e48be9d57d4d10d6b7d14672 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -107,7 +107,7 @@ struct dst_entry { struct dst_metrics { u32 metrics[RTAX_MAX]; - atomic_t refcnt; + refcount_t refcnt; }; extern const struct dst_metrics dst_default_metrics; diff --git a/net/core/dst.c b/net/core/dst.c index 00aa972ad1a1a451c24f3f8211243ad35c19433a..d6ead757c25895da01eb61bc9636c7e9b3cdfb3e 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -55,7 +55,7 @@ const struct dst_metrics dst_default_metrics = { * We really want to avoid false sharing on this variable, and catch * any writes on it. */ - .refcnt = ATOMIC_INIT(1), + .refcnt = REFCOUNT_INIT(1), }; void dst_init(struct dst_entry *dst, struct dst_ops *ops, @@ -213,7 +213,7 @@ u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old) struct dst_metrics *old_p = (struct dst_metrics *)__DST_METRICS_PTR(old); unsigned long prev, new; - atomic_set(&p->refcnt, 1); + refcount_set(&p->refcnt, 1); memcpy(p->metrics, old_p->metrics, sizeof(p->metrics)); new = (unsigned long) p; @@ -225,7 +225,7 @@ u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old) if (prev & DST_METRICS_READ_ONLY) p = NULL; } else if (prev & DST_METRICS_REFCOUNTED) { - if (atomic_dec_and_test(&old_p->refcnt)) + if (refcount_dec_and_test(&old_p->refcnt)) kfree(old_p); } } diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index d521caf57385fa05f76036708057b95052330cb1..394d800db50c77c21b65e14569eb4d8b5246406f 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -220,7 +220,7 @@ static void free_fib_info_rcu(struct rcu_head *head) } endfor_nexthops(fi); m = fi->fib_metrics; - if (m != &dst_default_metrics && atomic_dec_and_test(&m->refcnt)) + if (m != &dst_default_metrics && refcount_dec_and_test(&m->refcnt)) kfree(m); kfree(fi); } @@ -1090,7 +1090,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg, kfree(fi); return ERR_PTR(err); } - atomic_set(&fi->fib_metrics->refcnt, 1); + refcount_set(&fi->fib_metrics->refcnt, 1); } else { fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics; } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d400c05431063fc7bdd15b83ab540acc86decb3d..872b4cb136d3fa0cda403836cc83a156a65310a3 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1398,7 +1398,7 @@ static void ipv4_dst_destroy(struct dst_entry *dst) struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst); struct rtable *rt = (struct rtable *) dst; - if (p != &dst_default_metrics && atomic_dec_and_test(&p->refcnt)) + if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt)) kfree(p); if (!list_empty(&rt->rt_uncached)) { @@ -1456,7 +1456,7 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, dst_init_metrics(&rt->dst, fi->fib_metrics->metrics, true); if (fi->fib_metrics != &dst_default_metrics) { rt->dst._metrics |= DST_METRICS_REFCOUNTED; - atomic_inc(&fi->fib_metrics->refcnt); + refcount_inc(&fi->fib_metrics->refcnt); } #ifdef CONFIG_IP_ROUTE_CLASSID rt->dst.tclassid = nh->nh_tclassid;