Received: by 10.223.185.116 with SMTP id b49csp7887040wrg; Thu, 1 Mar 2018 12:59:35 -0800 (PST) X-Google-Smtp-Source: AG47ELsyeWA/FQWOV5WEO3Pk67S5N5wVdLhl+d0XxoQsBj4i//2EwZaJwihsLFlYflCnooMOw+Dr X-Received: by 10.101.99.205 with SMTP id n13mr2609428pgv.345.1519937975597; Thu, 01 Mar 2018 12:59:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519937975; cv=none; d=google.com; s=arc-20160816; b=DvsPrkSc53ORjGAOvieefDAyGUEjZDEvC8xRyjMXCQ7KTEQnXHw6iKiephqGLQk8M/ gmODgEosluxnfRIw1TbYd6FD9OVHaUWLkZS5Sjben54bbtcvJZLMv0dgcyYTnNBv7Z0k Dm1enFK81BqJmiYpJ4hMc8xUpeCQlchWEQnaEA4jHYyhQuAmAtny8G6lj+bvyr4fHy7D hjZ98jLlHoI+cEPIDfa0TmSH0VwxdLB+OExNCmYAbIvoanRgAb5+uaoT3N7nXexB5DRn C9tWybuGNptY+93xmDrB9TY9geC89keVxZkg5O5U1yU9hjSVHhfDQlV3wFVA54OxPn+f 4jYw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:organization:message-id:date:subject:cc:to :from:dkim-signature:arc-authentication-results; bh=PC/4dOUUF1dIVFky2SvJjf5iXUyLAiv5fkkvCHib16o=; b=ZNFIjAAp3Llzb6CPEVvrM0ACaG1x6g1cGizLJSREMq6I6SGv/Sl3NvXM1ZzpbV1NGE c3Wn5HgVwPp5NnbGV0kOdat4cwV19OmfrM4BagioDD1FnkTj4NY1Vl9W2mL2nopGvOIH LdUFzgQUs7mGpDMSV1/7Odo2KI0whAMkn/SBOJ5wDlMdYKKymkiub2EPS070ZUOCU999 SvjZClOC5Zzu125RdbAD8qiJgZQ9MRYfGja7yiEeJw/7y/mwjs88dO/J7wLufE1zSR9X KIzWCsQcpZKgPcNPHG9fn6Z+ml/pyBQMkb3Z+tFNY1ryYvKk7K7smw6FKjMg6zv/8LbU gY7A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=tZfJpZJ1; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i5si2939430pgc.521.2018.03.01.12.59.21; Thu, 01 Mar 2018 12:59:35 -0800 (PST) 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 (test mode) header.i=@ideasonboard.com header.s=mail header.b=tZfJpZJ1; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1161818AbeCAU6W (ORCPT + 99 others); Thu, 1 Mar 2018 15:58:22 -0500 Received: from galahad.ideasonboard.com ([185.26.127.97]:49998 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1161721AbeCAU6U (ORCPT ); Thu, 1 Mar 2018 15:58:20 -0500 Received: from avalon.localnet (dfj612ybrt5fhg77mgycy-3.rev.dnainternet.fi [IPv6:2001:14ba:21f5:5b00:2e86:4862:ef6a:2804]) by galahad.ideasonboard.com (Postfix) with ESMTPSA id 86C34202B7; Thu, 1 Mar 2018 21:56:24 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1519937784; bh=C9TqL1/pYSV5wet2aVgopOXsJg+AsCm5llGVn6jZObc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tZfJpZJ1V5q4ZqRljVf7ITuNs5jCVY+zhdMx5GACOFld98SUIPnN9DUBVIgHsMINw tzZGQLVupVYhl4EWGIb3cYpJXBJVLPJeJ59mQ5ILPB/18oA22/NZolTeNKsdtcPno9 eAbVizNkQRZqmKFvwyr9UowXPgtZ/JX5j/Jd0rUY= From: Laurent Pinchart To: frowand.list@gmail.com Cc: Rob Herring , pantelis.antoniou@konsulko.com, Pantelis Antoniou , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, geert@linux-m68k.org, laurent.pinchart+renesas@ideasonboard.com Subject: Re: [PATCH v4 1/4] of: change overlay apply input data from unflattened to FDT Date: Thu, 01 Mar 2018 22:59:08 +0200 Message-ID: <18109035.ZrMSJvtVAx@avalon> Organization: Ideas on Board Oy In-Reply-To: <1519927256-4868-2-git-send-email-frowand.list@gmail.com> References: <1519927256-4868-1-git-send-email-frowand.list@gmail.com> <1519927256-4868-2-git-send-email-frowand.list@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Frank, Thank you for the patch. On Thursday, 1 March 2018 20:00:53 EET frowand.list@gmail.com wrote: > From: Frank Rowand > > Move duplicating and unflattening of an overlay flattened devicetree > (FDT) into the overlay application code. To accomplish this, > of_overlay_apply() is replaced by of_overlay_fdt_apply(). > > The copy of the FDT (aka "duplicate FDT") now belongs to devicetree > code, which is thus responsible for freeing the duplicate FDT. The > caller of of_overlay_fdt_apply() remains responsible for freeing the > original FDT. > > The unflattened devicetree now belongs to devicetree code, which is > thus responsible for freeing the unflattened devicetree. > > These ownership changes prevent early freeing of the duplicated FDT > or the unflattened devicetree, which could result in use after free > errors. > > of_overlay_fdt_apply() is a private function for the anticipated > overlay loader. > > Update unittest.c to use of_overlay_fdt_apply() instead of > of_overlay_apply(). > > Move overlay fragments from artificial locations in > drivers/of/unittest-data/tests-overlay.dtsi into one devicetree > source file per overlay. This led to changes in > drivers/of/unitest-data/Makefile and drivers/of/unitest.c. > > - Add overlay directives to the overlay devicetree source files so > that dtc will compile them as true overlays into one FDT data > chunk per overlay. > > - Set CFLAGS for drivers/of/unittest-data/testcases.dts so that > symbols will be generated for overlay resolution of overlays > that are no longer artificially contained in testcases.dts > > - Unflatten and apply each unittest overlay FDT using > of_overlay_fdt_apply(). > > - Enable the of_resolve_phandles() check for whether the unflattened > overlay is detached. This check was previously disabled because the > overlays from tests-overlay.dtsi were not unflattened into detached > trees. > > - Other changes to unittest.c infrastructure to manage multiple test > FDTs built into the kernel image (access by name instead of > arbitrary number). > > - of_unittest_overlay_high_level(): previously unused code to add > properties from the overlay_base devicetree to the live tree > was triggered by the restructuring of tests-overlay.dtsi and thus > testcases.dts. This exposed two bugs: (1) the need to dup a > property before adding it, and (2) property 'name' is > auto-generated in the unflatten code and thus will be a duplicate > in the __symbols__ node - do not treat this duplicate as an error. > > Signed-off-by: Frank Rowand > --- > > There are checkpatch warnings. I have reviewed them and feel they > can be ignored. They are "line over 80 characters" for either > pre-existing long lines, or lines in devicetree source files. > > Changes from v3: > - OF_OVERLAY: add select OF_FLATTREE > > Changes from v1: > - rebase on v4.16-rc1 > > drivers/of/Kconfig | 1 + > drivers/of/of_private.h | 1 + > drivers/of/overlay.c | 107 +++++++++- > drivers/of/resolver.c | 6 - > drivers/of/unittest-data/Makefile | 28 ++- > drivers/of/unittest-data/overlay_0.dts | 14 ++ > drivers/of/unittest-data/overlay_1.dts | 14 ++ > drivers/of/unittest-data/overlay_10.dts | 34 ++++ > drivers/of/unittest-data/overlay_11.dts | 34 ++++ > drivers/of/unittest-data/overlay_12.dts | 14 ++ > drivers/of/unittest-data/overlay_13.dts | 14 ++ > drivers/of/unittest-data/overlay_15.dts | 35 ++++ > drivers/of/unittest-data/overlay_2.dts | 14 ++ > drivers/of/unittest-data/overlay_3.dts | 14 ++ > drivers/of/unittest-data/overlay_4.dts | 23 +++ > drivers/of/unittest-data/overlay_5.dts | 14 ++ > drivers/of/unittest-data/overlay_6.dts | 15 ++ > drivers/of/unittest-data/overlay_7.dts | 15 ++ > drivers/of/unittest-data/overlay_8.dts | 15 ++ > drivers/of/unittest-data/overlay_9.dts | 15 ++ > drivers/of/unittest-data/tests-overlay.dtsi | 213 -------------------- > drivers/of/unittest.c | 294 ++++++++++++------------ > include/linux/of.h | 7 - > 23 files changed, 552 insertions(+), 389 deletions(-) > create mode 100644 drivers/of/unittest-data/overlay_0.dts > create mode 100644 drivers/of/unittest-data/overlay_1.dts > create mode 100644 drivers/of/unittest-data/overlay_10.dts > create mode 100644 drivers/of/unittest-data/overlay_11.dts > create mode 100644 drivers/of/unittest-data/overlay_12.dts > create mode 100644 drivers/of/unittest-data/overlay_13.dts > create mode 100644 drivers/of/unittest-data/overlay_15.dts > create mode 100644 drivers/of/unittest-data/overlay_2.dts > create mode 100644 drivers/of/unittest-data/overlay_3.dts > create mode 100644 drivers/of/unittest-data/overlay_4.dts > create mode 100644 drivers/of/unittest-data/overlay_5.dts > create mode 100644 drivers/of/unittest-data/overlay_6.dts > create mode 100644 drivers/of/unittest-data/overlay_7.dts > create mode 100644 drivers/of/unittest-data/overlay_8.dts > create mode 100644 drivers/of/unittest-data/overlay_9.dts > > diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig > index 783e0870bd22..ad3fcad4d75b 100644 > --- a/drivers/of/Kconfig > +++ b/drivers/of/Kconfig > @@ -92,6 +92,7 @@ config OF_RESOLVE > config OF_OVERLAY > bool "Device Tree overlays" > select OF_DYNAMIC > + select OF_FLATTREE > select OF_RESOLVE > help > Overlays are a method to dynamically modify part of the kernel's > diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h > index 0c609e7d0334..6e39dce3a979 100644 > --- a/drivers/of/of_private.h > +++ b/drivers/of/of_private.h > @@ -77,6 +77,7 @@ static inline void __of_detach_node_sysfs(struct > device_node *np) {} #endif > > #if defined(CONFIG_OF_OVERLAY) > +int of_overlay_fdt_apply(void *overlay_fdt, int *ovcs_id); As discussed on IRC, could you move this to include/linux/of.h ? > void of_overlay_mutex_lock(void); > void of_overlay_mutex_unlock(void); > #else > diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c > index 3397d7642958..5f6c5569e97d 100644 > --- a/drivers/of/overlay.c > +++ b/drivers/of/overlay.c > @@ -12,10 +12,12 @@ > #include > #include > #include > +#include > #include > #include > #include > #include > +#include > #include > #include > > @@ -33,7 +35,9 @@ struct fragment { > > /** > * struct overlay_changeset > + * @id: changeset identifier > * @ovcs_list: list on which we are located > + * @fdt: FDT that was unflattened to create @overlay_tree > * @overlay_tree: expanded device tree that contains the fragment nodes > * @count: count of fragment structures > * @fragments: fragment nodes in the overlay expanded device tree > @@ -43,6 +47,7 @@ struct fragment { > struct overlay_changeset { > int id; > struct list_head ovcs_list; > + const void *fdt; > struct device_node *overlay_tree; > int count; > struct fragment *fragments; > @@ -503,7 +508,8 @@ static struct device_node *find_target_node(struct > device_node *info_node) > > /** > * init_overlay_changeset() - initialize overlay changeset from overlay > tree > - * @ovcs Overlay changeset to build > + * @ovcs: Overlay changeset to build > + * @fdt: the FDT that was unflattened to create @tree > * @tree: Contains all the overlay fragments and overlay fixup nodes > * > * Initialize @ovcs. Populate @ovcs->fragments with node information from > @@ -514,7 +520,7 @@ static struct device_node *find_target_node(struct > device_node *info_node) * detected in @tree, or -ENOSPC if idr_alloc() > error. > */ > static int init_overlay_changeset(struct overlay_changeset *ovcs, > - struct device_node *tree) > + const void *fdt, struct device_node *tree) > { > struct device_node *node, *overlay_node; > struct fragment *fragment; > @@ -535,6 +541,7 @@ static int init_overlay_changeset(struct > overlay_changeset *ovcs, pr_debug("%s() tree is not root\n", __func__); > > ovcs->overlay_tree = tree; > + ovcs->fdt = fdt; > > INIT_LIST_HEAD(&ovcs->ovcs_list); > > @@ -606,6 +613,7 @@ static int init_overlay_changeset(struct > overlay_changeset *ovcs, } > > if (!cnt) { > + pr_err("no fragments or symbols in overlay\n"); > ret = -EINVAL; > goto err_free_fragments; > } > @@ -642,11 +650,24 @@ static void free_overlay_changeset(struct > overlay_changeset *ovcs) } > kfree(ovcs->fragments); > > + /* > + * TODO > + * > + * would like to: kfree(ovcs->overlay_tree); > + * but can not since drivers may have pointers into this data > + * > + * would like to: kfree(ovcs->fdt); > + * but can not since drivers may have pointers into this data > + */ > + I assume you'll fix it at some point ? :-) > kfree(ovcs); > } > > -/** > +/* > + * internal documentation > + * > * of_overlay_apply() - Create and apply an overlay changeset > + * @fdt: the FDT that was unflattened to create @tree > * @tree: Expanded overlay device tree > * @ovcs_id: Pointer to overlay changeset id > * > @@ -685,21 +706,29 @@ static void free_overlay_changeset(struct > overlay_changeset *ovcs) * id is returned to *ovcs_id. > */ > > -int of_overlay_apply(struct device_node *tree, int *ovcs_id) > +static int of_overlay_apply(const void *fdt, struct device_node *tree, > + int *ovcs_id) > { > struct overlay_changeset *ovcs; > int ret = 0, ret_revert, ret_tmp; > > - *ovcs_id = 0; > + /* > + * As of this point, fdt and tree belong to the overlay changeset. > + * overlay changeset code is responsible for freeing them. > + */ > > if (devicetree_corrupt()) { > pr_err("devicetree state suspect, refuse to apply overlay\n"); > + kfree(fdt); > + kfree(tree); > ret = -EBUSY; > goto out; > } > > ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL); > if (!ovcs) { > + kfree(fdt); > + kfree(tree); > ret = -ENOMEM; > goto out; > } > @@ -709,12 +738,17 @@ int of_overlay_apply(struct device_node *tree, int > *ovcs_id) > > ret = of_resolve_phandles(tree); > if (ret) > - goto err_free_overlay_changeset; > + goto err_free_tree; > > - ret = init_overlay_changeset(ovcs, tree); > + ret = init_overlay_changeset(ovcs, fdt, tree); > if (ret) > - goto err_free_overlay_changeset; > + goto err_free_tree; > > + /* > + * after overlay_notify(), ovcs->overlay_tree related pointers may have > + * leaked to drivers, so can not kfree() tree, aka ovcs->overlay_tree; > + * and can not free fdt, aka ovcs->fdt > + */ > ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY); > if (ret) { > pr_err("overlay changeset pre-apply notify error %d\n", ret); > @@ -754,6 +788,9 @@ int of_overlay_apply(struct device_node *tree, int > *ovcs_id) > > goto out_unlock; > > +err_free_tree: > + kfree(tree); > + > err_free_overlay_changeset: > free_overlay_changeset(ovcs); > > @@ -766,7 +803,59 @@ int of_overlay_apply(struct device_node *tree, int > *ovcs_id) > > return ret; > } > -EXPORT_SYMBOL_GPL(of_overlay_apply); > + > +int of_overlay_fdt_apply(void *overlay_fdt, int *ovcs_id) Can you make the overlay_fdt pointer const ? Apart from that the patch looks OK to me. > +{ > + const void *new_fdt; > + int ret; > + u32 size; > + struct device_node *overlay_root; > + > + *ovcs_id = 0; > + ret = 0; > + > + if (fdt_check_header(overlay_fdt)) { > + pr_err("Invalid overlay_fdt header\n"); > + return -EINVAL; > + } > + > + size = fdt_totalsize(overlay_fdt); > + > + /* > + * Must create permanent copy of FDT because of_fdt_unflatten_tree() > + * will create pointers to the passed in FDT in the unflattened tree. > + */ > + new_fdt = kmemdup(overlay_fdt, size, GFP_KERNEL); > + if (!new_fdt) > + return -ENOMEM; > + > + of_fdt_unflatten_tree(new_fdt, NULL, &overlay_root); > + if (!overlay_root) { > + pr_err("unable to unflatten overlay_fdt\n"); > + ret = -EINVAL; > + goto out_free_new_fdt; > + } > + > + ret = of_overlay_apply(new_fdt, overlay_root, ovcs_id); > + if (ret < 0) { > + /* > + * new_fdt and overlay_root now belong to the overlay > + * changeset. > + * overlay changeset code is responsible for freeing them. > + */ > + goto out; > + } > + > + return 0; > + > + > +out_free_new_fdt: > + kfree(new_fdt); > + > +out: > + return ret; > +} > +EXPORT_SYMBOL_GPL(of_overlay_fdt_apply); > > /* > * Find @np in @tree. -- Regards, Laurent Pinchart