From patchwork Tue Oct 3 03:53:43 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Rowand X-Patchwork-Id: 9981877 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B554C60291 for ; Tue, 3 Oct 2017 07:20:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A790C28249 for ; Tue, 3 Oct 2017 07:20:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9C748286C1; Tue, 3 Oct 2017 07:20:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 32FF528249 for ; Tue, 3 Oct 2017 07:20:39 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 499016E400; Tue, 3 Oct 2017 07:19:41 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-pg0-x244.google.com (mail-pg0-x244.google.com [IPv6:2607:f8b0:400e:c05::244]) by gabe.freedesktop.org (Postfix) with ESMTPS id 8D0DD6E3A1 for ; Tue, 3 Oct 2017 03:54:14 +0000 (UTC) Received: by mail-pg0-x244.google.com with SMTP id o1so6859215pga.4 for ; Mon, 02 Oct 2017 20:54:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=bGzBPWGH5UYnzTDxEUtIjyIiPoajQsDnmQv6FkuHZFA=; b=L9BS7PwjFlXiqbyBgaYB1xcT9K9AkvMz519QtqgNgkb9WJkKY+WVczafsuyGnm2aaR Vuawc26DuhGdSKEoHwlgADFUIqH1n60Q33pwab10cg+QYe1QcK9yKqEUUZCSbLBvCp6S ShrglW1YUFqC1UhMdr6w+MWOPpx4CNiyPC2Xj0+kw9oPsU9c3wJEPtHm1fHZi9wd/VSJ UMKbbeFUjsjCy8ueIWwJXmwc91FqbJW2uQQRLNbdsAnl6zIvMD9gouvMbQEaVIkh4Fg7 w4FaTpdDs5JAQYyU+iU5IQGak6sXH3xRk+1lpmsKrAMBZJAJsWwMGdNR8Kq7eSU7YMSa FAcQ== 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:in-reply-to :references; bh=bGzBPWGH5UYnzTDxEUtIjyIiPoajQsDnmQv6FkuHZFA=; b=UrSUQ5d68QHPbjs/hgD5Zg1UhCGuVabkrFRX0xz6flL3dYbywgrYsAmgxt/UVwHdQF D5OjB/TSPdyPQqHUPgof3YHW7joZggY7C3dWHXRpOwZmTtj/y82vhkxbXuDF5lk+vvbL /uohiIU9XCOZiZKer8EF+SHDZjlFDRs5JA/u+IzoJ6Y4G5VNv1IIMoYbYcP5maiPrNRg qlElxHHwT3pibiMkx2RYHOPmEK8yacD3+HaR82P4UAEcAXUYUo/BiMwpDi6v83x/TSUy ElWEWoDtH7ojhoHlmLzjTsnUbbaYSeYJich59IxD+xgrBcgmhtX48EYD3YcGeBGlLAWm uElA== X-Gm-Message-State: AMCzsaXq4wQI/katnB1W/c5RePONeFFTvKmQLtcLpi32KQEoholMrgPz xbkAvq0EhJfVg6OfDb9nQoU= X-Google-Smtp-Source: AOwi7QAVm+g8qDnL9blXAPex356ICCqe9IULrGV/p1bGYJVDSakfDRO3m5NR6R3MDoR5qTaZbwYtCg== X-Received: by 10.99.109.67 with SMTP id i64mr6422164pgc.241.1507002854158; Mon, 02 Oct 2017 20:54:14 -0700 (PDT) Received: from localhost.localdomain (c-73-93-215-6.hsd1.ca.comcast.net. [73.93.215.6]) by smtp.gmail.com with ESMTPSA id c16sm18609930pfj.123.2017.10.02.20.54.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 02 Oct 2017 20:54:13 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , David Airlie , Jyri Sarha Subject: [PATCH 09/12] of: overlay: avoid race condition between applying multiple overlays Date: Mon, 2 Oct 2017 20:53:43 -0700 Message-Id: <1507002826-16393-10-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1507002826-16393-1-git-send-email-frowand.list@gmail.com> References: <1507002826-16393-1-git-send-email-frowand.list@gmail.com> X-Mailman-Approved-At: Tue, 03 Oct 2017 07:19:35 +0000 Cc: Mark Rutland , devicetree@vger.kernel.org, Tomi Valkeinen , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Frank Rowand The process of applying an overlay consists of: - unflatten an overlay FDT (flattened device tree) into an EDT (expanded device tree) - fixup the phandle values in the overlay EDT to fit in a range above the phandle values in the live device tree - create the overlay changeset to reflect the contents of the overlay EDT - apply the overlay changeset, to modify the live device tree, potentially changing the maximum phandle value in the live device tree There is currently no protection against two overlay applies concurrently determining what range of phandle values are in use in the live device tree, and subsequently changing that range. Add a mutex to prevent multiple overlay applies from occurring simultaneously. Ignoring 2 checkpatch warnings: Prefer using '"%s...", __func__' so that the WARN() string will be more easily grepped. Signed-off-by: Frank Rowand --- drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c | 7 +++++++ drivers/of/overlay.c | 22 ++++++++++++++++++++++ drivers/of/unittest.c | 21 +++++++++++++++++++++ include/linux/of.h | 19 +++++++++++++++++++ 4 files changed, 69 insertions(+) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c index 7a7be0515bfd..c99f7924b1c6 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c @@ -221,6 +221,11 @@ static void __init tilcdc_convert_slave_node(void) goto out; } + /* + * protect from of_resolve_phandles() through of_overlay_apply() + */ + of_overlay_mutex_lock(); + overlay = tilcdc_get_overlay(&kft); if (!overlay) goto out; @@ -256,6 +261,8 @@ static void __init tilcdc_convert_slave_node(void) pr_info("%s: ti,tilcdc,slave node successfully converted\n", __func__); out: + of_overlay_mutex_unlock(); + kfree_table_free(&kft); of_node_put(i2c); of_node_put(slave); diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index a0d3222febdc..4ed372af6ce7 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -71,6 +71,28 @@ static int build_changeset_next_level(struct overlay_changeset *ovcs, const struct device_node *overlay_node, bool is_symbols_node); +/* + * of_resolve_phandles() finds the largest phandle in the live tree. + * of_overlay_apply() may add a larger phandle to the live tree. + * Do not allow race between two overlays being applied simultaneously: + * mutex_lock(&of_overlay_phandle_mutex) + * of_resolve_phandles() + * of_overlay_apply() + * mutex_unlock(&of_overlay_phandle_mutex) + */ +static DEFINE_MUTEX(of_overlay_phandle_mutex); + +void of_overlay_mutex_lock(void) +{ + mutex_lock(&of_overlay_phandle_mutex); +} + +void of_overlay_mutex_unlock(void) +{ + mutex_unlock(&of_overlay_phandle_mutex); +} + + static LIST_HEAD(ovcs_list); static DEFINE_IDR(ovcs_idr); diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index db2f170186de..f4c8aff21320 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -994,9 +994,17 @@ static int __init unittest_data_add(void) return -ENODATA; } of_node_set_flag(unittest_data_node, OF_DETACHED); + + /* + * This lock normally encloses of_overlay_apply() as well as + * of_resolve_phandles(). + */ + of_overlay_mutex_lock(); + rc = of_resolve_phandles(unittest_data_node); if (rc) { pr_err("%s: Failed to resolve phandles (rc=%i)\n", __func__, rc); + of_overlay_mutex_unlock(); return -EINVAL; } @@ -1006,6 +1014,7 @@ static int __init unittest_data_add(void) __of_attach_node_sysfs(np); of_aliases = of_find_node_by_path("/aliases"); of_chosen = of_find_node_by_path("/chosen"); + of_overlay_mutex_unlock(); return 0; } @@ -1018,6 +1027,9 @@ static int __init unittest_data_add(void) attach_node_and_children(np); np = next; } + + of_overlay_mutex_unlock(); + return 0; } @@ -2150,9 +2162,12 @@ static int __init overlay_data_add(int onum) } of_node_set_flag(info->np_overlay, OF_DETACHED); + of_overlay_mutex_lock(); + ret = of_resolve_phandles(info->np_overlay); if (ret) { pr_err("resolve ot phandles (ret=%d), %d\n", ret, onum); + of_overlay_mutex_unlock(); goto out_free_np_overlay; } @@ -2160,9 +2175,12 @@ static int __init overlay_data_add(int onum) ret = of_overlay_apply(info->np_overlay, &info->overlay_id); if (ret < 0) { pr_err("of_overlay_apply() (ret=%d), %d\n", ret, onum); + of_overlay_mutex_unlock(); goto out_free_np_overlay; } + of_overlay_mutex_unlock(); + pr_debug("__dtb_overlay_begin applied, overlay id %d\n", ret); goto out; @@ -2209,7 +2227,10 @@ static __init void of_unittest_overlay_high_level(void) * Could not fixup phandles in unittest_unflatten_overlay_base() * because kmalloc() was not yet available. */ + of_overlay_mutex_lock(); of_resolve_phandles(overlay_base_root); + of_overlay_mutex_unlock(); + /* * do not allow overlay_base to duplicate any node already in diff --git a/include/linux/of.h b/include/linux/of.h index 49e5f24fb390..eb60eddf83c2 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -1306,6 +1306,9 @@ struct of_overlay_notify_data { #ifdef CONFIG_OF_OVERLAY /* ID based overlays; the API for external users */ +void of_overlay_mutex_lock(void); +void of_overlay_mutex_unlock(void); + int of_overlay_apply(struct device_node *tree, int *ovcs_id); int of_overlay_remove(int *ovcs_id); int of_overlay_remove_all(void); @@ -1315,6 +1318,22 @@ struct of_overlay_notify_data { #else +static inline void of_overlay_mutex_lock(void) +{ +#ifndef CONFIG_OF_RESOLVE + /* avoid warning in unittest.c */ + WARN(1, "of_overlay_mutex_lock() ifdef'ed out\n"); +#endif +} + +static inline void of_overlay_mutex_unlock(void) +{ +#ifndef CONFIG_OF_RESOLVE + /* avoid warning in unittest.c */ + WARN(1, "of_overlay_mutex_unlock() ifdef'ed out\n"); +#endif +} + static inline int of_overlay_apply(struct device_node *tree, int *ovcs_id) { return -ENOTSUPP;