From patchwork Fri May 19 23:03:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 764908 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3wV3WR07Wfz9s7p for ; Sat, 20 May 2017 09:03:31 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Ghh/lf88"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753512AbdESXD3 (ORCPT ); Fri, 19 May 2017 19:03:29 -0400 Received: from mail-lf0-f42.google.com ([209.85.215.42]:34129 "EHLO mail-lf0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752414AbdESXD2 (ORCPT ); Fri, 19 May 2017 19:03:28 -0400 Received: by mail-lf0-f42.google.com with SMTP id 99so7938456lfu.1 for ; Fri, 19 May 2017 16:03:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=D0BaOJ4rADXrei1cgfB/wMonnCH2NdmwLckgXQXYKkk=; b=Ghh/lf88os3Vo6L/Nb0i58nuB+FsExYy5zfFQ0EFpHcSSsBb7eU6Izj28VYDns0Ner /TTgo0JfmkzMtQM8vK41Uvnax+bBAPujXLFmwIjW8ATXF2PACyg/TmNT0N3pobLAmwxy 8ETVlIjqrK861JGXpLXgiD+XPPm1lPeee9K0U= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=D0BaOJ4rADXrei1cgfB/wMonnCH2NdmwLckgXQXYKkk=; b=jO+bVlm8uZgq8ONX9sqcRxGu3KGCqdJizmlIws3SldGJXpJNRR76ef33I2034FdHzq xzL2x0VgxL+uKjtRVCU05F9to4c4QqRv9kFO4e/YXOyN4mAIVaD1bUyqT5LbNFb1eJ0v 5qXMi9tC5AbJbJW9gXE5Tpo/vifQ2HZH0SMjjYAwiNPpK91Arn+j4dOuUi0WlWIPcBvS Pw7XFAbTzwvGSdZT5vaF1hhVJkGaAMZqlsvGwnMuh09apt4rVpx5H1iaagZXHgsiroas 7prZSWS4hz+p6KbacqnaI4Wo9O4WCsWot1usb5GPz3Wxn3LZxK1YSpxl6zxyIPdMl6Vz 1AEw== X-Gm-Message-State: AODbwcCE4isyJoAdwuwzVvJa0dJCaJxA/CKumcgjt0KsCwu23x1u2tCE X9PzHvY0F09k2wsI X-Received: by 10.25.195.21 with SMTP id t21mr2781635lff.103.1495235006752; Fri, 19 May 2017 16:03:26 -0700 (PDT) Received: from fabina.bredbandsbolaget.se (c-787571d5.014-348-6c756e10.cust.bredbandsbolaget.se. [213.113.117.120]) by smtp.gmail.com with ESMTPSA id g42sm1750864ljg.35.2017.05.19.16.03.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 19 May 2017 16:03:25 -0700 (PDT) From: Linus Walleij To: Tejun Heo , Bartlomiej Zolnierkiewicz , linux-ide@vger.kernel.org Cc: Linus Walleij , stable@vger.kernel.org Subject: [PATCH] libata: Fix devres handling Date: Sat, 20 May 2017 01:03:14 +0200 Message-Id: <20170519230314.15718-1-linus.walleij@linaro.org> X-Mailer: git-send-email 2.9.4 Sender: linux-ide-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ide@vger.kernel.org The ATA hosts are allocated using devres with: host = devres_alloc(ata_host_release, sz, GFP_KERNEL); However in the ata_host_release() function the host is retrieved using dev_get_drvdata() which is not what other devres handlers do, instead we should probably use the passed resource. Before this my kernel crashes badly when I fail to start a host in ata_host_start() and need to bail out, because dev_get_drvdata() gets the wrong-but-almost-correct pointer (so on some systems it may by chance be the right pointer what do I know). On ARMv4 Gemini it is not: ------------[ cut here ]------------ WARNING: CPU: 0 PID: 1 at ../lib/refcount.c:184 refcount_sub_and_test+0x9c/0xac refcount_t: underflow; use-after-free. CPU: 0 PID: 1 Comm: swapper Not tainted 4.12.0-rc1+ #657 Hardware name: Gemini (Device Tree) [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (__warn+0xcc/0xf4) [] (__warn) from [] (warn_slowpath_fmt+0x38/0x48) [] (warn_slowpath_fmt) from [] (refcount_sub_and_test+0x9c/0xac) [] (refcount_sub_and_test) from [] (kobject_put+0x28/0xe0) [] (kobject_put) from [] (ata_host_release+0xb0/0x144) [] (ata_host_release) from [] (release_nodes+0x178/0x1fc) [] (release_nodes) from [] (driver_probe_device+0xd0/0x2dc) [] (driver_probe_device) from [] (__driver_attach+0xbc/0xc0) [] (__driver_attach) from [] (bus_for_each_dev+0x70/0xa0) [] (bus_for_each_dev) from [] (bus_add_driver+0x178/0x200) [] (bus_add_driver) from [] (driver_register+0x78/0xf8) [] (driver_register) from [] (do_one_initcall+0xac/0x174) [] (do_one_initcall) from [] (kernel_init_freeable+0x114/0x1cc) [] (kernel_init_freeable) from [] (kernel_init+0x8/0xf4) [] (kernel_init) from [] (ret_from_fork+0x14/0x24) ---[ end trace 0a4570446a019085 ]--- Then there is a second (worse) crash when it tries to iterate to the next port. But it is all because the host pointer is wrong. In this case, the host should be 0xc7a3f3d0 as it was when it got allocated but instead what dev_get_drvdata() returns is 0xc7a3f370. Using the passed resource gives the right pointer. Cc: stable@vger.kernel.org Signed-off-by: Linus Walleij --- drivers/ata/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 2d83b8c75965..5487c4a29bc3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5921,7 +5921,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host) static void ata_host_release(struct device *gendev, void *res) { - struct ata_host *host = dev_get_drvdata(gendev); + struct ata_host *host = res; int i; for (i = 0; i < host->n_ports; i++) {