Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'kfree_validate_v7-for-4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/frowand/linux into dt/next

Pull overlay validation checks from Frank Rowand:

"Add checks to (1) overlay apply process and (2) memory freeing
triggered by overlay release. The checks are intended to detect
possible memory leaks and invalid overlays.

The checks revealed bugs in existing code. Fixed the bugs.

While fixing bugs, noted other issues, which are fixed in
separate patches."

Signed-off-by: Rob Herring <robh@kernel.org>

+431 -96
+2
arch/powerpc/platforms/pseries/dlpar.c
··· 270 270 if (rc) 271 271 return rc; 272 272 273 + of_node_put(dn); 274 + 273 275 return 0; 274 276 } 275 277
+46 -11
drivers/of/dynamic.c
··· 205 205 const __be32 *phandle; 206 206 int sz; 207 207 208 - np->name = __of_get_property(np, "name", NULL) ? : "<NULL>"; 209 - np->type = __of_get_property(np, "device_type", NULL) ? : "<NULL>"; 208 + if (!of_node_check_flag(np, OF_OVERLAY)) { 209 + np->name = __of_get_property(np, "name", NULL); 210 + np->type = __of_get_property(np, "device_type", NULL); 211 + if (!np->name) 212 + np->name = "<NULL>"; 213 + if (!np->type) 214 + np->type = "<NULL>"; 210 215 211 - phandle = __of_get_property(np, "phandle", &sz); 212 - if (!phandle) 213 - phandle = __of_get_property(np, "linux,phandle", &sz); 214 - if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle) 215 - phandle = __of_get_property(np, "ibm,phandle", &sz); 216 - np->phandle = (phandle && (sz >= 4)) ? be32_to_cpup(phandle) : 0; 216 + phandle = __of_get_property(np, "phandle", &sz); 217 + if (!phandle) 218 + phandle = __of_get_property(np, "linux,phandle", &sz); 219 + if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle) 220 + phandle = __of_get_property(np, "ibm,phandle", &sz); 221 + if (phandle && (sz >= 4)) 222 + np->phandle = be32_to_cpup(phandle); 223 + else 224 + np->phandle = 0; 225 + } 217 226 218 227 np->child = NULL; 219 228 np->sibling = np->parent->child; ··· 281 272 282 273 /** 283 274 * of_detach_node() - "Unplug" a node from the device tree. 284 - * 285 - * The caller must hold a reference to the node. The memory associated with 286 - * the node is not freed until its refcount goes to zero. 287 275 */ 288 276 int of_detach_node(struct device_node *np) 289 277 { ··· 335 329 } 336 330 if (!of_node_check_flag(node, OF_DYNAMIC)) 337 331 return; 332 + 333 + if (of_node_check_flag(node, OF_OVERLAY)) { 334 + 335 + if (!of_node_check_flag(node, OF_OVERLAY_FREE_CSET)) { 336 + /* premature refcount of zero, do not free memory */ 337 + pr_err("ERROR: memory leak before free overlay changeset, %pOF\n", 338 + node); 339 + return; 340 + } 341 + 342 + /* 343 + * If node->properties non-empty then properties were added 344 + * to this node either by different overlay that has not 345 + * yet been removed, or by a non-overlay mechanism. 346 + */ 347 + if (node->properties) 348 + pr_err("ERROR: %s(), unexpected properties in %pOF\n", 349 + __func__, node); 350 + } 338 351 339 352 property_list_free(node->properties); 340 353 property_list_free(node->deadprops); ··· 459 434 460 435 static void __of_changeset_entry_destroy(struct of_changeset_entry *ce) 461 436 { 437 + if (ce->action == OF_RECONFIG_ATTACH_NODE && 438 + of_node_check_flag(ce->np, OF_OVERLAY)) { 439 + if (kref_read(&ce->np->kobj.kref) > 1) { 440 + pr_err("ERROR: memory leak, expected refcount 1 instead of %d, of_node_get()/of_node_put() unbalanced - destroy cset entry: attach overlay node %pOF\n", 441 + kref_read(&ce->np->kobj.kref), ce->np); 442 + } else { 443 + of_node_set_flag(ce->np, OF_OVERLAY_FREE_CSET); 444 + } 445 + } 446 + 462 447 of_node_put(ce->np); 463 448 list_del(&ce->node); 464 449 kfree(ce);
+3 -1
drivers/of/kobj.c
··· 133 133 } 134 134 if (!name) 135 135 return -ENOMEM; 136 + 137 + of_node_get(np); 138 + 136 139 rc = kobject_add(&np->kobj, parent, "%s", name); 137 140 kfree(name); 138 141 if (rc) ··· 162 159 kobject_del(&np->kobj); 163 160 } 164 161 165 - /* finally remove the kobj_init ref */ 166 162 of_node_put(np); 167 163 }
+231 -61
drivers/of/overlay.c
··· 24 24 #include "of_private.h" 25 25 26 26 /** 27 + * struct target - info about current target node as recursing through overlay 28 + * @np: node where current level of overlay will be applied 29 + * @in_livetree: @np is a node in the live devicetree 30 + * 31 + * Used in the algorithm to create the portion of a changeset that describes 32 + * an overlay fragment, which is a devicetree subtree. Initially @np is a node 33 + * in the live devicetree where the overlay subtree is targeted to be grafted 34 + * into. When recursing to the next level of the overlay subtree, the target 35 + * also recurses to the next level of the live devicetree, as long as overlay 36 + * subtree node also exists in the live devicetree. When a node in the overlay 37 + * subtree does not exist at the same level in the live devicetree, target->np 38 + * points to a newly allocated node, and all subsequent targets in the subtree 39 + * will be newly allocated nodes. 40 + */ 41 + struct target { 42 + struct device_node *np; 43 + bool in_livetree; 44 + }; 45 + 46 + /** 27 47 * struct fragment - info about fragment nodes in overlay expanded device tree 28 48 * @target: target of the overlay operation 29 49 * @overlay: pointer to the __overlay__ node 30 50 */ 31 51 struct fragment { 32 - struct device_node *target; 33 52 struct device_node *overlay; 53 + struct device_node *target; 34 54 }; 35 55 36 56 /** ··· 92 72 } 93 73 94 74 static int build_changeset_next_level(struct overlay_changeset *ovcs, 95 - struct device_node *target_node, 96 - const struct device_node *overlay_node); 75 + struct target *target, const struct device_node *overlay_node); 97 76 98 77 /* 99 78 * of_resolve_phandles() finds the largest phandle in the live tree. ··· 276 257 /** 277 258 * add_changeset_property() - add @overlay_prop to overlay changeset 278 259 * @ovcs: overlay changeset 279 - * @target_node: where to place @overlay_prop in live tree 260 + * @target: where @overlay_prop will be placed 280 261 * @overlay_prop: property to add or update, from overlay tree 281 262 * @is_symbols_prop: 1 if @overlay_prop is from node "/__symbols__" 282 263 * 283 - * If @overlay_prop does not already exist in @target_node, add changeset entry 284 - * to add @overlay_prop in @target_node, else add changeset entry to update 264 + * If @overlay_prop does not already exist in live devicetree, add changeset 265 + * entry to add @overlay_prop in @target, else add changeset entry to update 285 266 * value of @overlay_prop. 286 267 * 287 - * Some special properties are not updated (no error returned). 268 + * @target may be either in the live devicetree or in a new subtree that 269 + * is contained in the changeset. 270 + * 271 + * Some special properties are not added or updated (no error returned): 272 + * "name", "phandle", "linux,phandle". 273 + * 274 + * Properties "#address-cells" and "#size-cells" are not updated if they 275 + * are already in the live tree, but if present in the live tree, the values 276 + * in the overlay must match the values in the live tree. 288 277 * 289 278 * Update of property in symbols node is not allowed. 290 279 * ··· 300 273 * invalid @overlay. 301 274 */ 302 275 static int add_changeset_property(struct overlay_changeset *ovcs, 303 - struct device_node *target_node, 304 - struct property *overlay_prop, 276 + struct target *target, struct property *overlay_prop, 305 277 bool is_symbols_prop) 306 278 { 307 279 struct property *new_prop = NULL, *prop; 308 280 int ret = 0; 281 + bool check_for_non_overlay_node = false; 309 282 310 - prop = of_find_property(target_node, overlay_prop->name, NULL); 283 + if (target->in_livetree) 284 + if (!of_prop_cmp(overlay_prop->name, "name") || 285 + !of_prop_cmp(overlay_prop->name, "phandle") || 286 + !of_prop_cmp(overlay_prop->name, "linux,phandle")) 287 + return 0; 311 288 312 - if (!of_prop_cmp(overlay_prop->name, "name") || 313 - !of_prop_cmp(overlay_prop->name, "phandle") || 314 - !of_prop_cmp(overlay_prop->name, "linux,phandle")) 315 - return 0; 289 + if (target->in_livetree) 290 + prop = of_find_property(target->np, overlay_prop->name, NULL); 291 + else 292 + prop = NULL; 316 293 317 294 if (is_symbols_prop) { 318 295 if (prop) ··· 329 298 if (!new_prop) 330 299 return -ENOMEM; 331 300 332 - if (!prop) 333 - ret = of_changeset_add_property(&ovcs->cset, target_node, 301 + if (!prop) { 302 + check_for_non_overlay_node = true; 303 + if (!target->in_livetree) { 304 + new_prop->next = target->np->deadprops; 305 + target->np->deadprops = new_prop; 306 + } 307 + ret = of_changeset_add_property(&ovcs->cset, target->np, 334 308 new_prop); 335 - else 336 - ret = of_changeset_update_property(&ovcs->cset, target_node, 309 + } else if (!of_prop_cmp(prop->name, "#address-cells")) { 310 + if (!of_prop_val_eq(prop, new_prop)) { 311 + pr_err("ERROR: changing value of #address-cells is not allowed in %pOF\n", 312 + target->np); 313 + ret = -EINVAL; 314 + } 315 + } else if (!of_prop_cmp(prop->name, "#size-cells")) { 316 + if (!of_prop_val_eq(prop, new_prop)) { 317 + pr_err("ERROR: changing value of #size-cells is not allowed in %pOF\n", 318 + target->np); 319 + ret = -EINVAL; 320 + } 321 + } else { 322 + check_for_non_overlay_node = true; 323 + ret = of_changeset_update_property(&ovcs->cset, target->np, 337 324 new_prop); 325 + } 326 + 327 + if (check_for_non_overlay_node && 328 + !of_node_check_flag(target->np, OF_OVERLAY)) 329 + pr_err("WARNING: memory leak will occur if overlay removed, property: %pOF/%s\n", 330 + target->np, new_prop->name); 338 331 339 332 if (ret) { 340 333 kfree(new_prop->name); ··· 370 315 371 316 /** 372 317 * add_changeset_node() - add @node (and children) to overlay changeset 373 - * @ovcs: overlay changeset 374 - * @target_node: where to place @node in live tree 375 - * @node: node from within overlay device tree fragment 318 + * @ovcs: overlay changeset 319 + * @target: where @node will be placed in live tree or changeset 320 + * @node: node from within overlay device tree fragment 376 321 * 377 - * If @node does not already exist in @target_node, add changeset entry 378 - * to add @node in @target_node. 322 + * If @node does not already exist in @target, add changeset entry 323 + * to add @node in @target. 379 324 * 380 - * If @node already exists in @target_node, and the existing node has 325 + * If @node already exists in @target, and the existing node has 381 326 * a phandle, the overlay node is not allowed to have a phandle. 382 327 * 383 328 * If @node has child nodes, add the children recursively via ··· 397 342 * a live devicetree created from Open Firmware. 398 343 * 399 344 * NOTE_2: Multiple mods of created nodes not supported. 400 - * If more than one fragment contains a node that does not already exist 401 - * in the live tree, then for each fragment of_changeset_attach_node() 402 - * will add a changeset entry to add the node. When the changeset is 403 - * applied, __of_attach_node() will attach the node twice (once for 404 - * each fragment). At this point the device tree will be corrupted. 405 - * 406 - * TODO: add integrity check to ensure that multiple fragments do not 407 - * create the same node. 408 345 * 409 346 * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if 410 347 * invalid @overlay. 411 348 */ 412 349 static int add_changeset_node(struct overlay_changeset *ovcs, 413 - struct device_node *target_node, struct device_node *node) 350 + struct target *target, struct device_node *node) 414 351 { 415 352 const char *node_kbasename; 353 + const __be32 *phandle; 416 354 struct device_node *tchild; 417 - int ret = 0; 355 + struct target target_child; 356 + int ret = 0, size; 418 357 419 358 node_kbasename = kbasename(node->full_name); 420 359 421 - for_each_child_of_node(target_node, tchild) 360 + for_each_child_of_node(target->np, tchild) 422 361 if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name))) 423 362 break; 424 363 425 364 if (!tchild) { 426 - tchild = __of_node_dup(node, node_kbasename); 365 + tchild = __of_node_dup(NULL, node_kbasename); 427 366 if (!tchild) 428 367 return -ENOMEM; 429 368 430 - tchild->parent = target_node; 369 + tchild->parent = target->np; 370 + tchild->name = __of_get_property(node, "name", NULL); 371 + tchild->type = __of_get_property(node, "device_type", NULL); 372 + 373 + if (!tchild->name) 374 + tchild->name = "<NULL>"; 375 + if (!tchild->type) 376 + tchild->type = "<NULL>"; 377 + 378 + /* ignore obsolete "linux,phandle" */ 379 + phandle = __of_get_property(node, "phandle", &size); 380 + if (phandle && (size == 4)) 381 + tchild->phandle = be32_to_cpup(phandle); 382 + 383 + of_node_set_flag(tchild, OF_OVERLAY); 431 384 432 385 ret = of_changeset_attach_node(&ovcs->cset, tchild); 433 386 if (ret) 434 387 return ret; 435 388 436 - return build_changeset_next_level(ovcs, tchild, node); 389 + target_child.np = tchild; 390 + target_child.in_livetree = false; 391 + 392 + ret = build_changeset_next_level(ovcs, &target_child, node); 393 + of_node_put(tchild); 394 + return ret; 437 395 } 438 396 439 - if (node->phandle && tchild->phandle) 397 + if (node->phandle && tchild->phandle) { 440 398 ret = -EINVAL; 441 - else 442 - ret = build_changeset_next_level(ovcs, tchild, node); 399 + } else { 400 + target_child.np = tchild; 401 + target_child.in_livetree = target->in_livetree; 402 + ret = build_changeset_next_level(ovcs, &target_child, node); 403 + } 443 404 of_node_put(tchild); 444 405 445 406 return ret; ··· 464 393 /** 465 394 * build_changeset_next_level() - add level of overlay changeset 466 395 * @ovcs: overlay changeset 467 - * @target_node: where to place @overlay_node in live tree 396 + * @target: where to place @overlay_node in live tree 468 397 * @overlay_node: node from within an overlay device tree fragment 469 398 * 470 399 * Add the properties (if any) and nodes (if any) from @overlay_node to the ··· 477 406 * invalid @overlay_node. 478 407 */ 479 408 static int build_changeset_next_level(struct overlay_changeset *ovcs, 480 - struct device_node *target_node, 481 - const struct device_node *overlay_node) 409 + struct target *target, const struct device_node *overlay_node) 482 410 { 483 411 struct device_node *child; 484 412 struct property *prop; 485 413 int ret; 486 414 487 415 for_each_property_of_node(overlay_node, prop) { 488 - ret = add_changeset_property(ovcs, target_node, prop, 0); 416 + ret = add_changeset_property(ovcs, target, prop, 0); 489 417 if (ret) { 490 418 pr_debug("Failed to apply prop @%pOF/%s, err=%d\n", 491 - target_node, prop->name, ret); 419 + target->np, prop->name, ret); 492 420 return ret; 493 421 } 494 422 } 495 423 496 424 for_each_child_of_node(overlay_node, child) { 497 - ret = add_changeset_node(ovcs, target_node, child); 425 + ret = add_changeset_node(ovcs, target, child); 498 426 if (ret) { 499 427 pr_debug("Failed to apply node @%pOF/%pOFn, err=%d\n", 500 - target_node, child, ret); 428 + target->np, child, ret); 501 429 of_node_put(child); 502 430 return ret; 503 431 } ··· 509 439 * Add the properties from __overlay__ node to the @ovcs->cset changeset. 510 440 */ 511 441 static int build_changeset_symbols_node(struct overlay_changeset *ovcs, 512 - struct device_node *target_node, 442 + struct target *target, 513 443 const struct device_node *overlay_symbols_node) 514 444 { 515 445 struct property *prop; 516 446 int ret; 517 447 518 448 for_each_property_of_node(overlay_symbols_node, prop) { 519 - ret = add_changeset_property(ovcs, target_node, prop, 1); 449 + ret = add_changeset_property(ovcs, target, prop, 1); 520 450 if (ret) { 521 - pr_debug("Failed to apply prop @%pOF/%s, err=%d\n", 522 - target_node, prop->name, ret); 451 + pr_debug("Failed to apply symbols prop @%pOF/%s, err=%d\n", 452 + target->np, prop->name, ret); 523 453 return ret; 524 454 } 525 455 } 526 456 527 457 return 0; 458 + } 459 + 460 + static int find_dup_cset_node_entry(struct overlay_changeset *ovcs, 461 + struct of_changeset_entry *ce_1) 462 + { 463 + struct of_changeset_entry *ce_2; 464 + char *fn_1, *fn_2; 465 + int node_path_match; 466 + 467 + if (ce_1->action != OF_RECONFIG_ATTACH_NODE && 468 + ce_1->action != OF_RECONFIG_DETACH_NODE) 469 + return 0; 470 + 471 + ce_2 = ce_1; 472 + list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) { 473 + if ((ce_2->action != OF_RECONFIG_ATTACH_NODE && 474 + ce_2->action != OF_RECONFIG_DETACH_NODE) || 475 + of_node_cmp(ce_1->np->full_name, ce_2->np->full_name)) 476 + continue; 477 + 478 + fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np); 479 + fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np); 480 + node_path_match = !strcmp(fn_1, fn_2); 481 + kfree(fn_1); 482 + kfree(fn_2); 483 + if (node_path_match) { 484 + pr_err("ERROR: multiple fragments add and/or delete node %pOF\n", 485 + ce_1->np); 486 + return -EINVAL; 487 + } 488 + } 489 + 490 + return 0; 491 + } 492 + 493 + static int find_dup_cset_prop(struct overlay_changeset *ovcs, 494 + struct of_changeset_entry *ce_1) 495 + { 496 + struct of_changeset_entry *ce_2; 497 + char *fn_1, *fn_2; 498 + int node_path_match; 499 + 500 + if (ce_1->action != OF_RECONFIG_ADD_PROPERTY && 501 + ce_1->action != OF_RECONFIG_REMOVE_PROPERTY && 502 + ce_1->action != OF_RECONFIG_UPDATE_PROPERTY) 503 + return 0; 504 + 505 + ce_2 = ce_1; 506 + list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) { 507 + if ((ce_2->action != OF_RECONFIG_ADD_PROPERTY && 508 + ce_2->action != OF_RECONFIG_REMOVE_PROPERTY && 509 + ce_2->action != OF_RECONFIG_UPDATE_PROPERTY) || 510 + of_node_cmp(ce_1->np->full_name, ce_2->np->full_name)) 511 + continue; 512 + 513 + fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np); 514 + fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np); 515 + node_path_match = !strcmp(fn_1, fn_2); 516 + kfree(fn_1); 517 + kfree(fn_2); 518 + if (node_path_match && 519 + !of_prop_cmp(ce_1->prop->name, ce_2->prop->name)) { 520 + pr_err("ERROR: multiple fragments add, update, and/or delete property %pOF/%s\n", 521 + ce_1->np, ce_1->prop->name); 522 + return -EINVAL; 523 + } 524 + } 525 + 526 + return 0; 527 + } 528 + 529 + /** 530 + * changeset_dup_entry_check() - check for duplicate entries 531 + * @ovcs: Overlay changeset 532 + * 533 + * Check changeset @ovcs->cset for multiple {add or delete} node entries for 534 + * the same node or duplicate {add, delete, or update} properties entries 535 + * for the same property. 536 + * 537 + * Returns 0 on success, or -EINVAL if duplicate changeset entry found. 538 + */ 539 + static int changeset_dup_entry_check(struct overlay_changeset *ovcs) 540 + { 541 + struct of_changeset_entry *ce_1; 542 + int dup_entry = 0; 543 + 544 + list_for_each_entry(ce_1, &ovcs->cset.entries, node) { 545 + dup_entry |= find_dup_cset_node_entry(ovcs, ce_1); 546 + dup_entry |= find_dup_cset_prop(ovcs, ce_1); 547 + } 548 + 549 + return dup_entry ? -EINVAL : 0; 528 550 } 529 551 530 552 /** ··· 634 472 static int build_changeset(struct overlay_changeset *ovcs) 635 473 { 636 474 struct fragment *fragment; 475 + struct target target; 637 476 int fragments_count, i, ret; 638 477 639 478 /* ··· 649 486 for (i = 0; i < fragments_count; i++) { 650 487 fragment = &ovcs->fragments[i]; 651 488 652 - ret = build_changeset_next_level(ovcs, fragment->target, 489 + target.np = fragment->target; 490 + target.in_livetree = true; 491 + ret = build_changeset_next_level(ovcs, &target, 653 492 fragment->overlay); 654 493 if (ret) { 655 - pr_debug("apply failed '%pOF'\n", fragment->target); 494 + pr_debug("fragment apply failed '%pOF'\n", 495 + fragment->target); 656 496 return ret; 657 497 } 658 498 } 659 499 660 500 if (ovcs->symbols_fragment) { 661 501 fragment = &ovcs->fragments[ovcs->count - 1]; 662 - ret = build_changeset_symbols_node(ovcs, fragment->target, 502 + 503 + target.np = fragment->target; 504 + target.in_livetree = true; 505 + ret = build_changeset_symbols_node(ovcs, &target, 663 506 fragment->overlay); 664 507 if (ret) { 665 - pr_debug("apply failed '%pOF'\n", fragment->target); 508 + pr_debug("symbols fragment apply failed '%pOF'\n", 509 + fragment->target); 666 510 return ret; 667 511 } 668 512 } 669 513 670 - return 0; 514 + return changeset_dup_entry_check(ovcs); 671 515 } 672 516 673 517 /* ··· 684 514 * 1) "target" property containing the phandle of the target 685 515 * 2) "target-path" property containing the path of the target 686 516 */ 687 - static struct device_node *find_target_node(struct device_node *info_node) 517 + static struct device_node *find_target(struct device_node *info_node) 688 518 { 689 519 struct device_node *node; 690 520 const char *path; ··· 790 620 791 621 fragment = &fragments[cnt]; 792 622 fragment->overlay = overlay_node; 793 - fragment->target = find_target_node(node); 623 + fragment->target = find_target(node); 794 624 if (!fragment->target) { 795 625 of_node_put(fragment->overlay); 796 626 ret = -EINVAL; ··· 978 808 979 809 ret = __of_changeset_apply_notify(&ovcs->cset); 980 810 if (ret) 981 - pr_err("overlay changeset entry notify error %d\n", ret); 811 + pr_err("overlay apply changeset entry notify error %d\n", ret); 982 812 /* notify failure is not fatal, continue */ 983 813 984 814 list_add_tail(&ovcs->ovcs_list, &ovcs_list); ··· 1237 1067 1238 1068 ret = __of_changeset_revert_notify(&ovcs->cset); 1239 1069 if (ret) 1240 - pr_err("overlay changeset entry notify error %d\n", ret); 1070 + pr_err("overlay remove changeset entry notify error %d\n", ret); 1241 1071 /* notify failure is not fatal, continue */ 1242 1072 1243 1073 *ovcs_id = 0;
+2
drivers/of/unittest-data/Makefile
··· 17 17 overlay_12.dtb.o \ 18 18 overlay_13.dtb.o \ 19 19 overlay_15.dtb.o \ 20 + overlay_bad_add_dup_node.dtb.o \ 21 + overlay_bad_add_dup_prop.dtb.o \ 20 22 overlay_bad_phandle.dtb.o \ 21 23 overlay_bad_symbol.dtb.o \ 22 24 overlay_base.dtb.o
+28
drivers/of/unittest-data/overlay_bad_add_dup_node.dts
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /dts-v1/; 3 + /plugin/; 4 + 5 + /* 6 + * &electric_1/motor-1 and &spin_ctrl_1 are the same node: 7 + * /testcase-data-2/substation@100/motor-1 8 + * 9 + * Thus the new node "controller" in each fragment will 10 + * result in an attempt to add the same node twice. 11 + * This will result in an error and the overlay apply 12 + * will fail. 13 + */ 14 + 15 + &electric_1 { 16 + 17 + motor-1 { 18 + controller { 19 + power_bus = < 0x1 0x2 >; 20 + }; 21 + }; 22 + }; 23 + 24 + &spin_ctrl_1 { 25 + controller { 26 + power_bus_emergency = < 0x101 0x102 >; 27 + }; 28 + };
+24
drivers/of/unittest-data/overlay_bad_add_dup_prop.dts
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /dts-v1/; 3 + /plugin/; 4 + 5 + /* 6 + * &electric_1/motor-1 and &spin_ctrl_1 are the same node: 7 + * /testcase-data-2/substation@100/motor-1 8 + * 9 + * Thus the property "rpm_avail" in each fragment will 10 + * result in an attempt to update the same property twice. 11 + * This will result in an error and the overlay apply 12 + * will fail. 13 + */ 14 + 15 + &electric_1 { 16 + 17 + motor-1 { 18 + rpm_avail = < 100 >; 19 + }; 20 + }; 21 + 22 + &spin_ctrl_1 { 23 + rpm_avail = < 100 200 >; 24 + };
+1
drivers/of/unittest-data/overlay_base.dts
··· 30 30 spin_ctrl_1: motor-1 { 31 31 compatible = "ot,ferris-wheel-motor"; 32 32 spin = "clockwise"; 33 + rpm_avail = < 50 >; 33 34 }; 34 35 35 36 spin_ctrl_2: motor-8 {
+78 -18
drivers/of/unittest.c
··· 379 379 for (i = 0; i < 8; i++) { 380 380 bool passed = true; 381 381 382 + memset(&args, 0, sizeof(args)); 382 383 rc = of_parse_phandle_with_args(np, "phandle-list", 383 384 "#phandle-cells", i, &args); 384 385 ··· 433 432 } 434 433 435 434 /* Check for missing list property */ 435 + memset(&args, 0, sizeof(args)); 436 436 rc = of_parse_phandle_with_args(np, "phandle-list-missing", 437 437 "#phandle-cells", 0, &args); 438 438 unittest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); ··· 442 440 unittest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); 443 441 444 442 /* Check for missing cells property */ 443 + memset(&args, 0, sizeof(args)); 445 444 rc = of_parse_phandle_with_args(np, "phandle-list", 446 445 "#phandle-cells-missing", 0, &args); 447 446 unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); ··· 451 448 unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); 452 449 453 450 /* Check for bad phandle in list */ 451 + memset(&args, 0, sizeof(args)); 454 452 rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle", 455 453 "#phandle-cells", 0, &args); 456 454 unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); ··· 460 456 unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); 461 457 462 458 /* Check for incorrectly formed argument list */ 459 + memset(&args, 0, sizeof(args)); 463 460 rc = of_parse_phandle_with_args(np, "phandle-list-bad-args", 464 461 "#phandle-cells", 1, &args); 465 462 unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); ··· 511 506 for (i = 0; i < 8; i++) { 512 507 bool passed = true; 513 508 509 + memset(&args, 0, sizeof(args)); 514 510 rc = of_parse_phandle_with_args_map(np, "phandle-list", 515 511 "phandle", i, &args); 516 512 ··· 569 563 } 570 564 571 565 /* Check for missing list property */ 566 + memset(&args, 0, sizeof(args)); 572 567 rc = of_parse_phandle_with_args_map(np, "phandle-list-missing", 573 568 "phandle", 0, &args); 574 569 unittest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); 575 570 576 571 /* Check for missing cells,map,mask property */ 572 + memset(&args, 0, sizeof(args)); 577 573 rc = of_parse_phandle_with_args_map(np, "phandle-list", 578 574 "phandle-missing", 0, &args); 579 575 unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); 580 576 581 577 /* Check for bad phandle in list */ 578 + memset(&args, 0, sizeof(args)); 582 579 rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-phandle", 583 580 "phandle", 0, &args); 584 581 unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); 585 582 586 583 /* Check for incorrectly formed argument list */ 584 + memset(&args, 0, sizeof(args)); 587 585 rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-args", 588 586 "phandle", 1, &args); 589 587 unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); ··· 797 787 for (i = 0; i < 4; i++) { 798 788 bool passed = true; 799 789 800 - args.args_count = 0; 790 + memset(&args, 0, sizeof(args)); 801 791 rc = of_irq_parse_one(np, i, &args); 802 792 803 793 passed &= !rc; ··· 818 808 for (i = 0; i < 4; i++) { 819 809 bool passed = true; 820 810 821 - args.args_count = 0; 811 + memset(&args, 0, sizeof(args)); 822 812 rc = of_irq_parse_one(np, i, &args); 823 813 824 814 /* Test the values from tests-phandle.dtsi */ ··· 874 864 for (i = 0; i < 7; i++) { 875 865 bool passed = true; 876 866 867 + memset(&args, 0, sizeof(args)); 877 868 rc = of_irq_parse_one(np, i, &args); 878 869 879 870 /* Test the values from tests-phandle.dtsi */ ··· 1082 1071 * of np into dup node (present in live tree) and 1083 1072 * updates parent of children of np to dup. 1084 1073 * 1085 - * @np: node already present in live tree 1074 + * @np: node whose properties are being added to the live tree 1086 1075 * @dup: node present in live tree to be updated 1087 1076 */ 1088 1077 static void update_node_properties(struct device_node *np, 1089 1078 struct device_node *dup) 1090 1079 { 1091 1080 struct property *prop; 1081 + struct property *save_next; 1092 1082 struct device_node *child; 1093 - 1094 - for_each_property_of_node(np, prop) 1095 - of_add_property(dup, prop); 1083 + int ret; 1096 1084 1097 1085 for_each_child_of_node(np, child) 1098 1086 child->parent = dup; 1087 + 1088 + /* 1089 + * "unittest internal error: unable to add testdata property" 1090 + * 1091 + * If this message reports a property in node '/__symbols__' then 1092 + * the respective unittest overlay contains a label that has the 1093 + * same name as a label in the live devicetree. The label will 1094 + * be in the live devicetree only if the devicetree source was 1095 + * compiled with the '-@' option. If you encounter this error, 1096 + * please consider renaming __all__ of the labels in the unittest 1097 + * overlay dts files with an odd prefix that is unlikely to be 1098 + * used in a real devicetree. 1099 + */ 1100 + 1101 + /* 1102 + * open code for_each_property_of_node() because of_add_property() 1103 + * sets prop->next to NULL 1104 + */ 1105 + for (prop = np->properties; prop != NULL; prop = save_next) { 1106 + save_next = prop->next; 1107 + ret = of_add_property(dup, prop); 1108 + if (ret) 1109 + pr_err("unittest internal error: unable to add testdata property %pOF/%s", 1110 + np, prop->name); 1111 + } 1099 1112 } 1100 1113 1101 1114 /** ··· 1128 1093 * 1129 1094 * @np: Node to attach to live tree 1130 1095 */ 1131 - static int attach_node_and_children(struct device_node *np) 1096 + static void attach_node_and_children(struct device_node *np) 1132 1097 { 1133 1098 struct device_node *next, *dup, *child; 1134 1099 unsigned long flags; 1135 1100 const char *full_name; 1136 1101 1137 1102 full_name = kasprintf(GFP_KERNEL, "%pOF", np); 1103 + 1104 + if (!strcmp(full_name, "/__local_fixups__") || 1105 + !strcmp(full_name, "/__fixups__")) 1106 + return; 1107 + 1138 1108 dup = of_find_node_by_path(full_name); 1139 1109 kfree(full_name); 1140 1110 if (dup) { 1141 1111 update_node_properties(np, dup); 1142 - return 0; 1112 + return; 1143 1113 } 1144 1114 1145 1115 child = np->child; ··· 1165 1125 attach_node_and_children(child); 1166 1126 child = next; 1167 1127 } 1168 - 1169 - return 0; 1170 1128 } 1171 1129 1172 1130 /** ··· 1471 1433 } while (defers > 0); 1472 1434 } 1473 1435 1474 - static int __init of_unittest_apply_overlay(int overlay_nr, int unittest_nr, 1475 - int *overlay_id) 1436 + static int __init of_unittest_apply_overlay(int overlay_nr, int *overlay_id) 1476 1437 { 1477 1438 const char *overlay_name; 1478 1439 ··· 1504 1467 } 1505 1468 1506 1469 ovcs_id = 0; 1507 - ret = of_unittest_apply_overlay(overlay_nr, unittest_nr, &ovcs_id); 1470 + ret = of_unittest_apply_overlay(overlay_nr, &ovcs_id); 1508 1471 if (ret != 0) { 1509 1472 /* of_unittest_apply_overlay already called unittest() */ 1510 1473 return ret; ··· 1540 1503 1541 1504 /* apply the overlay */ 1542 1505 ovcs_id = 0; 1543 - ret = of_unittest_apply_overlay(overlay_nr, unittest_nr, &ovcs_id); 1506 + ret = of_unittest_apply_overlay(overlay_nr, &ovcs_id); 1544 1507 if (ret != 0) { 1545 1508 /* of_unittest_apply_overlay already called unittest() */ 1546 1509 return ret; ··· 2198 2161 OVERLAY_INFO_EXTERN(overlay_12); 2199 2162 OVERLAY_INFO_EXTERN(overlay_13); 2200 2163 OVERLAY_INFO_EXTERN(overlay_15); 2164 + OVERLAY_INFO_EXTERN(overlay_bad_add_dup_node); 2165 + OVERLAY_INFO_EXTERN(overlay_bad_add_dup_prop); 2201 2166 OVERLAY_INFO_EXTERN(overlay_bad_phandle); 2202 2167 OVERLAY_INFO_EXTERN(overlay_bad_symbol); 2203 2168 2204 - /* order of entries is hard-coded into users of overlays[] */ 2169 + /* entries found by name */ 2205 2170 static struct overlay_info overlays[] = { 2206 2171 OVERLAY_INFO(overlay_base, -9999), 2207 2172 OVERLAY_INFO(overlay, 0), ··· 2222 2183 OVERLAY_INFO(overlay_12, 0), 2223 2184 OVERLAY_INFO(overlay_13, 0), 2224 2185 OVERLAY_INFO(overlay_15, 0), 2186 + OVERLAY_INFO(overlay_bad_add_dup_node, -EINVAL), 2187 + OVERLAY_INFO(overlay_bad_add_dup_prop, -EINVAL), 2225 2188 OVERLAY_INFO(overlay_bad_phandle, -EINVAL), 2226 2189 OVERLAY_INFO(overlay_bad_symbol, -EINVAL), 2227 - {} 2190 + /* end marker */ 2191 + {.dtb_begin = NULL, .dtb_end = NULL, .expected_result = 0, .name = NULL} 2228 2192 }; 2229 2193 2230 2194 static struct device_node *overlay_base_root; ··· 2257 2215 u32 data_size; 2258 2216 void *new_fdt; 2259 2217 u32 size; 2218 + int found = 0; 2219 + const char *overlay_name = "overlay_base"; 2220 + 2221 + for (info = overlays; info && info->name; info++) { 2222 + if (!strcmp(overlay_name, info->name)) { 2223 + found = 1; 2224 + break; 2225 + } 2226 + } 2227 + if (!found) { 2228 + pr_err("no overlay data for %s\n", overlay_name); 2229 + return; 2230 + } 2260 2231 2261 2232 info = &overlays[0]; 2262 2233 ··· 2317 2262 { 2318 2263 struct overlay_info *info; 2319 2264 int found = 0; 2320 - int k; 2321 2265 int ret; 2322 2266 u32 size; 2323 2267 2324 - for (k = 0, info = overlays; info && info->name; info++, k++) { 2268 + for (info = overlays; info && info->name; info++) { 2325 2269 if (!strcmp(overlay_name, info->name)) { 2326 2270 found = 1; 2327 2271 break; ··· 2483 2429 2484 2430 unittest(overlay_data_apply("overlay", NULL), 2485 2431 "Adding overlay 'overlay' failed\n"); 2432 + 2433 + unittest(overlay_data_apply("overlay_bad_add_dup_node", NULL), 2434 + "Adding overlay 'overlay_bad_add_dup_node' failed\n"); 2435 + 2436 + unittest(overlay_data_apply("overlay_bad_add_dup_prop", NULL), 2437 + "Adding overlay 'overlay_bad_add_dup_prop' failed\n"); 2486 2438 2487 2439 unittest(overlay_data_apply("overlay_bad_phandle", NULL), 2488 2440 "Adding overlay 'overlay_bad_phandle' failed\n");
+16 -5
include/linux/of.h
··· 138 138 extern struct device_node *of_stdout; 139 139 extern raw_spinlock_t devtree_lock; 140 140 141 - /* flag descriptions (need to be visible even when !CONFIG_OF) */ 142 - #define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ 143 - #define OF_DETACHED 2 /* node has been detached from the device tree */ 144 - #define OF_POPULATED 3 /* device already created for the node */ 145 - #define OF_POPULATED_BUS 4 /* of_platform_populate recursed to children of this node */ 141 + /* 142 + * struct device_node flag descriptions 143 + * (need to be visible even when !CONFIG_OF) 144 + */ 145 + #define OF_DYNAMIC 1 /* (and properties) allocated via kmalloc */ 146 + #define OF_DETACHED 2 /* detached from the device tree */ 147 + #define OF_POPULATED 3 /* device already created */ 148 + #define OF_POPULATED_BUS 4 /* platform bus created for children */ 149 + #define OF_OVERLAY 5 /* allocated for an overlay */ 150 + #define OF_OVERLAY_FREE_CSET 6 /* in overlay cset being freed */ 146 151 147 152 #define OF_BAD_ADDR ((u64)-1) 148 153 ··· 989 984 #define of_prop_cmp(s1, s2) strcmp((s1), (s2)) 990 985 #define of_node_cmp(s1, s2) strcasecmp((s1), (s2)) 991 986 #endif 987 + 988 + static inline int of_prop_val_eq(struct property *p1, struct property *p2) 989 + { 990 + return p1->length == p2->length && 991 + !memcmp(p1->value, p2->value, (size_t)p1->length); 992 + } 992 993 993 994 #if defined(CONFIG_OF) && defined(CONFIG_NUMA) 994 995 extern int of_node_to_nid(struct device_node *np);