Received: by 2002:ac0:a582:0:0:0:0:0 with SMTP id m2-v6csp2488560imm; Thu, 18 Oct 2018 15:49:34 -0700 (PDT) X-Google-Smtp-Source: ACcGV62dQo6bf8sfdCUDO3W8JFQMltPEoH0rMr5fSgXSb6O+wnC23PDeoB8un/dX5ofursGx7EaU X-Received: by 2002:a17:902:167:: with SMTP id 94-v6mr30860597plb.142.1539902974492; Thu, 18 Oct 2018 15:49:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1539902974; cv=none; d=google.com; s=arc-20160816; b=PS/RQQ6e/5sRYM0vUPWE2jpSekCO2UXLDoZuqNJPMArpdoTiqGZnyNhBMJdOAwm2cy HYUfz1nZ7+2iukdJ1B+1nPHWC2jHPEi/+PPN9Snit6z41fV2yc8ZRsZqVHawNtrfoA9z T+s+N/gliYTldmon81b4yXFPICHB8mxHXKeLVOB+jWFI0pdqHIv5jt4GPmd0ghlI/2xC kfKZAnhLHQaYXp0vYm4bpa3WeUOwkyht7e5pECTLtoZMqoNy2Gss7SC+H8piswf78pe4 MYP7gvavLx4Jk2ucIQ1eBa8EtjwgzATvTCQcPVcW7+bxiNf8BWMdkwVasSeTjKfff7GJ VXHQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=FBP4hDQvyoNWRFBrCTkuGHkJzZo2uU0sSLnVkIQfb7A=; b=Z+oOtGc0Tg1vTZ1svAmjZGlJsj6jajhGzYnF2GdVNsd96R+HyWjKshxB+PFzJ+oD2e wbhxDZ7yB8wfIwDRxaiO1bEQVx5zQJETonzv+qSSe4uwe6eSyqV8oXxrpSaui6yOyr9S IjiACn5tOoKvxpsbutslYMMMEwNvcDvw7z04gJxOFRUsPD223Mk9OYiCNTXoSMvrPI1p DuY2yZ/W528QDRK7NcvV0V9LOTmO1t/HvK15PR+MZFbUX1c6a41D8B6hfdTQi8TE3IUD rcWRH4rdEECbE5bikhj7f8OkJZzHGFuvryTKzWKbI6R9py/QSFaAuqNPkr4UN2N/XKaB SMeg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b="kJN/J1Wn"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u127-v6si22372738pgc.234.2018.10.18.15.49.19; Thu, 18 Oct 2018 15:49:34 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b="kJN/J1Wn"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727682AbeJSGvb (ORCPT + 99 others); Fri, 19 Oct 2018 02:51:31 -0400 Received: from mail-pl1-f196.google.com ([209.85.214.196]:40076 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727474AbeJSGva (ORCPT ); Fri, 19 Oct 2018 02:51:30 -0400 Received: by mail-pl1-f196.google.com with SMTP id 1-v6so14959500plv.7; Thu, 18 Oct 2018 15:48:20 -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=FBP4hDQvyoNWRFBrCTkuGHkJzZo2uU0sSLnVkIQfb7A=; b=kJN/J1WnkSP4otV1/A8bRfPtne77uYe1xBp3CHaHC3nWg4TS//f2QbkrfXEBRcFvOx K+q777O/ese+U3IB8jA2lmB9aMReKvooDjK9vsq3wNOLiohipPpr67sZLtDf9xkSg+WW GJYWSeHgr4AGB991o8WrOu16W+Q7k4LUygD2JNfLtfHga5RMncha2q1UiGJjb1HD8qlQ NsUmjHP9N3R/0YWszbRV4NfIvKN5Gr6ObYHWi+3372wow/RmLqPafr+CofYrglIqDxT+ qDhB7mzd6XIJ0dpVit20HUgYbTZY1AMQmWX1HUg4E4F0ixXHndd7yC3vitFQLySqP0F+ mhlg== 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=FBP4hDQvyoNWRFBrCTkuGHkJzZo2uU0sSLnVkIQfb7A=; b=P3DT80C95XCnbDqHblypaOd2v2YaNouAtb/uc10jHlqRK8Ur6eV33/1zOunOaONt7D qa3dfFtpTKyqF5lsUT2lBf0iU5DKfXEmj0lxN05ZkyHv0VDJacR5t2COC18skPjUNuuc NCxpAm4qjrUR1ef60ksuKyWUFeStvA8QtqZMPF00xsniz4iEAYdO27Nv4VYrA4VQ5rFW wnDgu2WMNKhwOH/V04Q7rUMUSpAtTS+RSiR11N3jABB2FiSt5MLrpGjqknqk7fg8JqWN /dxE32dee5K2zEvRdHz56pvLOd4ovdEph6kVJDi7kwYDfoCKDLDwppWF8cImNYcmaaci BmTA== X-Gm-Message-State: ABuFfoiPq23xR5vqB/L0NA2zUyvdqhY/Y7HYmlqm5PadSL5+9iFGqq6f hcFPna2f+Oj6XpiP7W/zIopHjeqI X-Received: by 2002:a17:902:b287:: with SMTP id u7-v6mr31286238plr.123.1539902900090; Thu, 18 Oct 2018 15:48:20 -0700 (PDT) Received: from localhost.localdomain (c-24-6-192-50.hsd1.ca.comcast.net. [24.6.192.50]) by smtp.gmail.com with ESMTPSA id v81-v6sm38129268pfj.25.2018.10.18.15.48.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 18 Oct 2018 15:48:19 -0700 (PDT) From: frowand.list@gmail.com To: Rob Herring , Pantelis Antoniou , Michael Ellerman , Benjamin Herrenschmidt , Paul Mackerras , Alan Tull , Moritz Fischer Cc: linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-fpga@vger.kernel.org Subject: [PATCH v5 13/18] of: overlay: check prevents multiple fragments touching same property Date: Thu, 18 Oct 2018 15:46:31 -0700 Message-Id: <1539902796-8382-14-git-send-email-frowand.list@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1539902796-8382-1-git-send-email-frowand.list@gmail.com> References: <1539902796-8382-1-git-send-email-frowand.list@gmail.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Frank Rowand Add test case of two fragments updating the same property. After adding the test case, the system hangs at end of boot, after after slub stack dumps from kfree() in crypto modprobe code. Multiple overlay fragments adding, modifying, or deleting the same property is not supported. Add check to detect the attempt and fail the overlay apply. Before this patch, the first fragment error would terminate processing. Allow fragment checking to proceed and report all of the fragment errors before terminating the overlay apply. This is not a hot path, thus not a performance issue (the error is not transient and requires fixing the overlay before attempting to apply it again). After applying this patch, the devicetree unittest messages will include: OF: overlay: ERROR: multiple fragments add, update, and/or delete property /testcase-data-2/substation@100/motor-1/rpm_avail ... ### dt-test ### end of unittest - 212 passed, 0 failed The check to detect two fragments updating the same property is folded into the patch that created the test case to maintain bisectability. Signed-off-by: Frank Rowand --- drivers/of/overlay.c | 118 ++++++++++++++------- drivers/of/unittest-data/Makefile | 1 + .../of/unittest-data/overlay_bad_add_dup_prop.dts | 24 +++++ drivers/of/unittest-data/overlay_base.dts | 1 + drivers/of/unittest.c | 5 + 5 files changed, 112 insertions(+), 37 deletions(-) create mode 100644 drivers/of/unittest-data/overlay_bad_add_dup_prop.dts diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index e12f2c28a36a..9e4af83c8c62 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -508,52 +508,96 @@ static int build_changeset_symbols_node(struct overlay_changeset *ovcs, return 0; } +static int find_dup_cset_node_entry(struct overlay_changeset *ovcs, + struct of_changeset_entry *ce_1) +{ + struct of_changeset_entry *ce_2; + char *fn_1, *fn_2; + int node_path_match; + + if (ce_1->action != OF_RECONFIG_ATTACH_NODE && + ce_1->action != OF_RECONFIG_DETACH_NODE) + return 0; + + ce_2 = ce_1; + list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) { + if ((ce_2->action != OF_RECONFIG_ATTACH_NODE && + ce_2->action != OF_RECONFIG_DETACH_NODE) || + of_node_cmp(ce_1->np->full_name, ce_2->np->full_name)) + continue; + + fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np); + fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np); + node_path_match = !strcmp(fn_1, fn_2); + kfree(fn_1); + kfree(fn_2); + if (node_path_match) { + pr_err("ERROR: multiple fragments add and/or delete node %pOF\n", + ce_1->np); + return -EINVAL; + } + } + + return 0; +} + +static int find_dup_cset_prop(struct overlay_changeset *ovcs, + struct of_changeset_entry *ce_1) +{ + struct of_changeset_entry *ce_2; + char *fn_1, *fn_2; + int node_path_match; + + if (ce_1->action != OF_RECONFIG_ADD_PROPERTY && + ce_1->action != OF_RECONFIG_REMOVE_PROPERTY && + ce_1->action != OF_RECONFIG_UPDATE_PROPERTY) + return 0; + + ce_2 = ce_1; + list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) { + if ((ce_2->action != OF_RECONFIG_ADD_PROPERTY && + ce_2->action != OF_RECONFIG_REMOVE_PROPERTY && + ce_2->action != OF_RECONFIG_UPDATE_PROPERTY) || + of_node_cmp(ce_1->np->full_name, ce_2->np->full_name)) + continue; + + fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np); + fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np); + node_path_match = !strcmp(fn_1, fn_2); + kfree(fn_1); + kfree(fn_2); + if (node_path_match && + !of_prop_cmp(ce_1->prop->name, ce_2->prop->name)) { + pr_err("ERROR: multiple fragments add, update, and/or delete property %pOF/%s\n", + ce_1->np, ce_1->prop->name); + return -EINVAL; + } + } + + return 0; +} + /** - * check_changeset_dup_add_node() - changeset validation: duplicate add node + * changeset_dup_entry_check() - check for duplicate entries * @ovcs: Overlay changeset * - * Check changeset @ovcs->cset for multiple add node entries for the same - * node. + * Check changeset @ovcs->cset for multiple {add or delete} node entries for + * the same node or duplicate {add, delete, or update} properties entries + * for the same property. * - * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if - * invalid overlay in @ovcs->fragments[]. + * Returns 0 on success, or -EINVAL if duplicate changeset entry found. */ -static int check_changeset_dup_add_node(struct overlay_changeset *ovcs) +static int changeset_dup_entry_check(struct overlay_changeset *ovcs) { - struct of_changeset_entry *ce_1, *ce_2; - char *fn_1, *fn_2; - int name_match; + struct of_changeset_entry *ce_1; + int dup_entry = 0; list_for_each_entry(ce_1, &ovcs->cset.entries, node) { - - if (ce_1->action == OF_RECONFIG_ATTACH_NODE || - ce_1->action == OF_RECONFIG_DETACH_NODE) { - - ce_2 = ce_1; - list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) { - if (ce_2->action == OF_RECONFIG_ATTACH_NODE || - ce_2->action == OF_RECONFIG_DETACH_NODE) { - /* inexpensive name compare */ - if (!of_node_cmp(ce_1->np->full_name, - ce_2->np->full_name)) { - /* expensive full path name compare */ - fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np); - fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np); - name_match = !strcmp(fn_1, fn_2); - kfree(fn_1); - kfree(fn_2); - if (name_match) { - pr_err("ERROR: multiple overlay fragments add and/or delete node %pOF\n", - ce_1->np); - return -EINVAL; - } - } - } - } - } + dup_entry |= find_dup_cset_node_entry(ovcs, ce_1); + dup_entry |= find_dup_cset_prop(ovcs, ce_1); } - return 0; + return dup_entry ? -EINVAL : 0; } /** @@ -611,7 +655,7 @@ static int build_changeset(struct overlay_changeset *ovcs) } } - return check_changeset_dup_add_node(ovcs); + return changeset_dup_entry_check(ovcs); } /* diff --git a/drivers/of/unittest-data/Makefile b/drivers/of/unittest-data/Makefile index 166dbdbfd1c5..9b6807065827 100644 --- a/drivers/of/unittest-data/Makefile +++ b/drivers/of/unittest-data/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_OF_OVERLAY) += overlay.dtb.o \ overlay_13.dtb.o \ overlay_15.dtb.o \ overlay_bad_add_dup_node.dtb.o \ + overlay_bad_add_dup_prop.dtb.o \ overlay_bad_phandle.dtb.o \ overlay_bad_symbol.dtb.o \ overlay_base.dtb.o diff --git a/drivers/of/unittest-data/overlay_bad_add_dup_prop.dts b/drivers/of/unittest-data/overlay_bad_add_dup_prop.dts new file mode 100644 index 000000000000..c190da54f175 --- /dev/null +++ b/drivers/of/unittest-data/overlay_bad_add_dup_prop.dts @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; +/plugin/; + +/* + * &electric_1/motor-1 and &spin_ctrl_1 are the same node: + * /testcase-data-2/substation@100/motor-1 + * + * Thus the property "rpm_avail" in each fragment will + * result in an attempt to update the same property twice. + * This will result in an error and the overlay apply + * will fail. + */ + +&electric_1 { + + motor-1 { + rpm_avail = < 100 >; + }; +}; + +&spin_ctrl_1 { + rpm_avail = < 100 200 >; +}; diff --git a/drivers/of/unittest-data/overlay_base.dts b/drivers/of/unittest-data/overlay_base.dts index 820b79ca378a..99ab9d12d00b 100644 --- a/drivers/of/unittest-data/overlay_base.dts +++ b/drivers/of/unittest-data/overlay_base.dts @@ -30,6 +30,7 @@ spin_ctrl_1: motor-1 { compatible = "ot,ferris-wheel-motor"; spin = "clockwise"; + rpm_avail = < 50 >; }; spin_ctrl_2: motor-8 { diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 471b8eb6e842..efd9c947f192 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -2148,6 +2148,7 @@ struct overlay_info { OVERLAY_INFO_EXTERN(overlay_13); OVERLAY_INFO_EXTERN(overlay_15); OVERLAY_INFO_EXTERN(overlay_bad_add_dup_node); +OVERLAY_INFO_EXTERN(overlay_bad_add_dup_prop); OVERLAY_INFO_EXTERN(overlay_bad_phandle); OVERLAY_INFO_EXTERN(overlay_bad_symbol); @@ -2171,6 +2172,7 @@ struct overlay_info { OVERLAY_INFO(overlay_13, 0), OVERLAY_INFO(overlay_15, 0), OVERLAY_INFO(overlay_bad_add_dup_node, -EINVAL), + OVERLAY_INFO(overlay_bad_add_dup_prop, -EINVAL), OVERLAY_INFO(overlay_bad_phandle, -EINVAL), OVERLAY_INFO(overlay_bad_symbol, -EINVAL), {} @@ -2418,6 +2420,9 @@ static __init void of_unittest_overlay_high_level(void) unittest(overlay_data_apply("overlay_bad_add_dup_node", NULL), "Adding overlay 'overlay_bad_add_dup_node' failed\n"); + unittest(overlay_data_apply("overlay_bad_add_dup_prop", NULL), + "Adding overlay 'overlay_bad_add_dup_prop' failed\n"); + unittest(overlay_data_apply("overlay_bad_phandle", NULL), "Adding overlay 'overlay_bad_phandle' failed\n"); -- Frank Rowand