hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/of/overlay.c
....@@ -49,8 +49,8 @@
4949 * @overlay: pointer to the __overlay__ node
5050 */
5151 struct fragment {
52
- struct device_node *target;
5352 struct device_node *overlay;
53
+ struct device_node *target;
5454 };
5555
5656 /**
....@@ -170,9 +170,7 @@
170170
171171 ret = blocking_notifier_call_chain(&overlay_notify_chain,
172172 action, &nd);
173
- if (ret == NOTIFY_OK || ret == NOTIFY_STOP)
174
- return 0;
175
- if (ret) {
173
+ if (notifier_to_errno(ret)) {
176174 ret = notifier_to_errno(ret);
177175 pr_err("overlay changeset %s notifier error %d, target: %pOF\n",
178176 of_overlay_action_name[action], ret, nd.target);
....@@ -402,14 +400,6 @@
402400 * a live devicetree created from Open Firmware.
403401 *
404402 * NOTE_2: Multiple mods of created nodes not supported.
405
- * If more than one fragment contains a node that does not already exist
406
- * in the live tree, then for each fragment of_changeset_attach_node()
407
- * will add a changeset entry to add the node. When the changeset is
408
- * applied, __of_attach_node() will attach the node twice (once for
409
- * each fragment). At this point the device tree will be corrupted.
410
- *
411
- * TODO: add integrity check to ensure that multiple fragments do not
412
- * create the same node.
413403 *
414404 * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
415405 * invalid @overlay.
....@@ -436,12 +426,9 @@
436426
437427 tchild->parent = target->np;
438428 tchild->name = __of_get_property(node, "name", NULL);
439
- tchild->type = __of_get_property(node, "device_type", NULL);
440429
441430 if (!tchild->name)
442431 tchild->name = "<NULL>";
443
- if (!tchild->type)
444
- tchild->type = "<NULL>";
445432
446433 /* ignore obsolete "linux,phandle" */
447434 phandle = __of_get_property(node, "phandle", &size);
....@@ -531,13 +518,105 @@
531518 for_each_property_of_node(overlay_symbols_node, prop) {
532519 ret = add_changeset_property(ovcs, target, prop, 1);
533520 if (ret) {
534
- pr_debug("Failed to apply prop @%pOF/%s, err=%d\n",
521
+ pr_debug("Failed to apply symbols prop @%pOF/%s, err=%d\n",
535522 target->np, prop->name, ret);
536523 return ret;
537524 }
538525 }
539526
540527 return 0;
528
+}
529
+
530
+static int find_dup_cset_node_entry(struct overlay_changeset *ovcs,
531
+ struct of_changeset_entry *ce_1)
532
+{
533
+ struct of_changeset_entry *ce_2;
534
+ char *fn_1, *fn_2;
535
+ int node_path_match;
536
+
537
+ if (ce_1->action != OF_RECONFIG_ATTACH_NODE &&
538
+ ce_1->action != OF_RECONFIG_DETACH_NODE)
539
+ return 0;
540
+
541
+ ce_2 = ce_1;
542
+ list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) {
543
+ if ((ce_2->action != OF_RECONFIG_ATTACH_NODE &&
544
+ ce_2->action != OF_RECONFIG_DETACH_NODE) ||
545
+ of_node_cmp(ce_1->np->full_name, ce_2->np->full_name))
546
+ continue;
547
+
548
+ fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np);
549
+ fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np);
550
+ node_path_match = !strcmp(fn_1, fn_2);
551
+ kfree(fn_1);
552
+ kfree(fn_2);
553
+ if (node_path_match) {
554
+ pr_err("ERROR: multiple fragments add and/or delete node %pOF\n",
555
+ ce_1->np);
556
+ return -EINVAL;
557
+ }
558
+ }
559
+
560
+ return 0;
561
+}
562
+
563
+static int find_dup_cset_prop(struct overlay_changeset *ovcs,
564
+ struct of_changeset_entry *ce_1)
565
+{
566
+ struct of_changeset_entry *ce_2;
567
+ char *fn_1, *fn_2;
568
+ int node_path_match;
569
+
570
+ if (ce_1->action != OF_RECONFIG_ADD_PROPERTY &&
571
+ ce_1->action != OF_RECONFIG_REMOVE_PROPERTY &&
572
+ ce_1->action != OF_RECONFIG_UPDATE_PROPERTY)
573
+ return 0;
574
+
575
+ ce_2 = ce_1;
576
+ list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) {
577
+ if ((ce_2->action != OF_RECONFIG_ADD_PROPERTY &&
578
+ ce_2->action != OF_RECONFIG_REMOVE_PROPERTY &&
579
+ ce_2->action != OF_RECONFIG_UPDATE_PROPERTY) ||
580
+ of_node_cmp(ce_1->np->full_name, ce_2->np->full_name))
581
+ continue;
582
+
583
+ fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np);
584
+ fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np);
585
+ node_path_match = !strcmp(fn_1, fn_2);
586
+ kfree(fn_1);
587
+ kfree(fn_2);
588
+ if (node_path_match &&
589
+ !of_prop_cmp(ce_1->prop->name, ce_2->prop->name)) {
590
+ pr_err("ERROR: multiple fragments add, update, and/or delete property %pOF/%s\n",
591
+ ce_1->np, ce_1->prop->name);
592
+ return -EINVAL;
593
+ }
594
+ }
595
+
596
+ return 0;
597
+}
598
+
599
+/**
600
+ * changeset_dup_entry_check() - check for duplicate entries
601
+ * @ovcs: Overlay changeset
602
+ *
603
+ * Check changeset @ovcs->cset for multiple {add or delete} node entries for
604
+ * the same node or duplicate {add, delete, or update} properties entries
605
+ * for the same property.
606
+ *
607
+ * Returns 0 on success, or -EINVAL if duplicate changeset entry found.
608
+ */
609
+static int changeset_dup_entry_check(struct overlay_changeset *ovcs)
610
+{
611
+ struct of_changeset_entry *ce_1;
612
+ int dup_entry = 0;
613
+
614
+ list_for_each_entry(ce_1, &ovcs->cset.entries, node) {
615
+ dup_entry |= find_dup_cset_node_entry(ovcs, ce_1);
616
+ dup_entry |= find_dup_cset_prop(ovcs, ce_1);
617
+ }
618
+
619
+ return dup_entry ? -EINVAL : 0;
541620 }
542621
543622 /**
....@@ -575,7 +654,8 @@
575654 ret = build_changeset_next_level(ovcs, &target,
576655 fragment->overlay);
577656 if (ret) {
578
- pr_debug("apply failed '%pOF'\n", fragment->target);
657
+ pr_debug("fragment apply failed '%pOF'\n",
658
+ fragment->target);
579659 return ret;
580660 }
581661 }
....@@ -588,12 +668,13 @@
588668 ret = build_changeset_symbols_node(ovcs, &target,
589669 fragment->overlay);
590670 if (ret) {
591
- pr_debug("apply failed '%pOF'\n", fragment->target);
671
+ pr_debug("symbols fragment apply failed '%pOF'\n",
672
+ fragment->target);
592673 return ret;
593674 }
594675 }
595676
596
- return 0;
677
+ return changeset_dup_entry_check(ovcs);
597678 }
598679
599680 /*
....@@ -713,6 +794,7 @@
713794 if (!fragment->target) {
714795 of_node_put(fragment->overlay);
715796 ret = -EINVAL;
797
+ of_node_put(node);
716798 goto err_free_fragments;
717799 }
718800
....@@ -893,11 +975,9 @@
893975 goto err_free_overlay_changeset;
894976 }
895977
896
- of_populate_phandle_cache();
897
-
898978 ret = __of_changeset_apply_notify(&ovcs->cset);
899979 if (ret)
900
- pr_err("overlay changeset entry notify error %d\n", ret);
980
+ pr_err("overlay apply changeset entry notify error %d\n", ret);
901981 /* notify failure is not fatal, continue */
902982
903983 list_add_tail(&ovcs->ovcs_list, &ovcs_list);
....@@ -1137,17 +1217,8 @@
11371217
11381218 list_del(&ovcs->ovcs_list);
11391219
1140
- /*
1141
- * Disable phandle cache. Avoids race condition that would arise
1142
- * from removing cache entry when the associated node is deleted.
1143
- */
1144
- of_free_phandle_cache();
1145
-
11461220 ret_apply = 0;
11471221 ret = __of_changeset_revert_entries(&ovcs->cset, &ret_apply);
1148
-
1149
- of_populate_phandle_cache();
1150
-
11511222 if (ret) {
11521223 if (ret_apply)
11531224 devicetree_state_flags |= DTSF_REVERT_FAIL;
....@@ -1156,7 +1227,7 @@
11561227
11571228 ret = __of_changeset_revert_notify(&ovcs->cset);
11581229 if (ret)
1159
- pr_err("overlay changeset entry notify error %d\n", ret);
1230
+ pr_err("overlay remove changeset entry notify error %d\n", ret);
11601231 /* notify failure is not fatal, continue */
11611232
11621233 *ovcs_id = 0;