From patchwork Mon Dec 24 20:57:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Oskolkov X-Patchwork-Id: 1018304 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@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; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="KCkMWFbx"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43Ns4b0H05z9sBZ for ; Tue, 25 Dec 2018 07:57:35 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725820AbeLXU5Y (ORCPT ); Mon, 24 Dec 2018 15:57:24 -0500 Received: from mail-pf1-f202.google.com ([209.85.210.202]:45896 "EHLO mail-pf1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725788AbeLXU5Y (ORCPT ); Mon, 24 Dec 2018 15:57:24 -0500 Received: by mail-pf1-f202.google.com with SMTP id 74so13277207pfk.12 for ; Mon, 24 Dec 2018 12:57:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=jlwcp0/bXseFlL5DxvcPLz2FIrkGtfHG7UPZLQI/Sbs=; b=KCkMWFbxvPVvrJIJIwGtVFZz+weCGurV74CmdoLXVlF4I/U9V0OnKuPMzNTXjAvpNd 8MBH5q3Nwyva19QikbHUbjIi6+OyqAkTmTsQ6kAovi7auPu2gsASbCJR4vtILm4PYwqI HSvdQxiMolqQgDf29wdMuR01JM8CS1MoX356k1UCOWGC7heJtT91n25vOxDEWfisB/KK U4A6AsJFqvPJxJpJSPeYSvXEULbbIfYJMmTibD2B8sWKJvCERJyhMVdaluAX68ywAlux gcCXRceGHTXANK7rbm3SbS71iLoPrMsGdoCiwoQSFMHcgW8c6zrmAsf5uHNwjt+LHkKf Ut3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=jlwcp0/bXseFlL5DxvcPLz2FIrkGtfHG7UPZLQI/Sbs=; b=UkKx6+mPoWzkGC75V0iaspYn/v6WljbeqbHau9Eq1Ur3FH5Hwou9b24Et+8HpMMMe5 OMps6Cwyp4kzVk4XUfRU4uWSAcNfQVfFM+jUYPQEqvvemQPU2lL0GUxLDzonmrZIo86u yczEqW2plaHogk6uvVlV4DwYcfm7GiqnhFDZ+ULhVAviN4Jh3pnPGmkPNcfHYq+79qkM bcweGSbYmm9XhVvSqI40uq9VEAzQYVipULZ58PGXVtuO7Ey7HmEsnwbzGzqlvO9m/byF 6UK7w1xgjfWnsHkXLfLdX3TWSHzJGHq4V6bTXzD6vI91ucKmNGYjpkh/d7i2ntMELYfl XO5Q== X-Gm-Message-State: AJcUukdAeeHUv+pOwaWcDlMvZWvz5yUBheOc6bUqpNav3V0O29Q9jqRI JkT47BV/pa2tuSU9hkXmrDn+FRaT X-Google-Smtp-Source: ALg8bN6+vdAiceZMMwczi9r7+pqN82ZDchtL3/xorPoMxfaGFd0EdvErb5P0JOZMvIuuO4O+lOMpUzaM X-Received: by 2002:a63:914c:: with SMTP id l73mr6981804pge.86.1545685042908; Mon, 24 Dec 2018 12:57:22 -0800 (PST) Date: Mon, 24 Dec 2018 12:57:17 -0800 Message-Id: <20181224205717.245485-1-posk@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.20.1.415.g653613c723-goog Subject: [PATCH net] net: dccp: fix kernel crash on module load From: Peter Oskolkov To: David Miller , netdev@vger.kernel.org Cc: Peter Oskolkov , Peter Oskolkov , kernel test robot Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Patch eedbbb0d98b2 "net: dccp: initialize (addr,port) ..." added calling to inet_hashinfo2_init() from dccp_init(). However, inet_hashinfo2_init() is marked as __init(), and thus the kernel panics when dccp is loaded as module. Removing __init() tag from inet_hashinfo2_init() is not feasible because it calls into __init functions in mm. This patch adds inet_hashinfo2_init_mod() function that can be called after the init phase is done; changes dccp_init() to call the new function; un-marks inet_hashinfo2_init() as exported. Fixes: eedbbb0d98b2 ("net: dccp: initialize (addr,port) ...") Reported-by: kernel test robot Signed-off-by: Peter Oskolkov --- include/net/inet_hashtables.h | 1 + net/dccp/proto.c | 8 ++++---- net/ipv4/inet_hashtables.c | 34 ++++++++++++++++++++++++++-------- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 0ce460e93dc4..babb14136705 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -237,6 +237,7 @@ void inet_hashinfo2_init(struct inet_hashinfo *h, const char *name, unsigned long numentries, int scale, unsigned long low_limit, unsigned long high_limit); +int inet_hashinfo2_init_mod(struct inet_hashinfo *h); bool inet_ehash_insert(struct sock *sk, struct sock *osk); bool inet_ehash_nolisten(struct sock *sk, struct sock *osk); diff --git a/net/dccp/proto.c b/net/dccp/proto.c index be0b223aa862..2cc5fbb1b29e 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -1139,11 +1139,11 @@ static int __init dccp_init(void) rc = percpu_counter_init(&dccp_orphan_count, 0, GFP_KERNEL); if (rc) goto out_fail; - rc = -ENOBUFS; inet_hashinfo_init(&dccp_hashinfo); - inet_hashinfo2_init(&dccp_hashinfo, "dccp_listen_portaddr_hash", - INET_LHTABLE_SIZE, 21, /* one slot per 2 MB*/ - 0, 64 * 1024); + rc = inet_hashinfo2_init_mod(&dccp_hashinfo); + if (rc) + goto out_fail; + rc = -ENOBUFS; dccp_hashinfo.bind_bucket_cachep = kmem_cache_create("dccp_bind_bucket", sizeof(struct inet_bind_bucket), 0, diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 2445614de6a7..942265d65eb3 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -762,13 +762,22 @@ void inet_hashinfo_init(struct inet_hashinfo *h) } EXPORT_SYMBOL_GPL(inet_hashinfo_init); +static void init_hashinfo_lhash2(struct inet_hashinfo *h) +{ + int i; + + for (i = 0; i <= h->lhash2_mask; i++) { + spin_lock_init(&h->lhash2[i].lock); + INIT_HLIST_HEAD(&h->lhash2[i].head); + h->lhash2[i].count = 0; + } +} + void __init inet_hashinfo2_init(struct inet_hashinfo *h, const char *name, unsigned long numentries, int scale, unsigned long low_limit, unsigned long high_limit) { - unsigned int i; - h->lhash2 = alloc_large_system_hash(name, sizeof(*h->lhash2), numentries, @@ -778,14 +787,23 @@ void __init inet_hashinfo2_init(struct inet_hashinfo *h, const char *name, &h->lhash2_mask, low_limit, high_limit); + init_hashinfo_lhash2(h); +} - for (i = 0; i <= h->lhash2_mask; i++) { - spin_lock_init(&h->lhash2[i].lock); - INIT_HLIST_HEAD(&h->lhash2[i].head); - h->lhash2[i].count = 0; - } +int inet_hashinfo2_init_mod(struct inet_hashinfo *h) +{ + h->lhash2 = kmalloc_array(INET_LHTABLE_SIZE, sizeof(*h->lhash2), GFP_KERNEL); + if (!h->lhash2) + return -ENOMEM; + + h->lhash2_mask = INET_LHTABLE_SIZE - 1; + /* INET_LHTABLE_SIZE must be a power of 2 */ + BUG_ON(INET_LHTABLE_SIZE & h->lhash2_mask); + + init_hashinfo_lhash2(h); + return 0; } -EXPORT_SYMBOL_GPL(inet_hashinfo2_init); +EXPORT_SYMBOL_GPL(inet_hashinfo2_init_mod); int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo) {