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

Configure Feed

Select the types of activity you want to include in your feed.

of: Fix double free in of_parse_phandle_with_args_map

In of_parse_phandle_with_args_map() the inner loop that
iterates through the map entries calls of_node_put(new)
to free the reference acquired by the previous iteration
of the inner loop. This assumes that the value of "new" is
NULL on the first iteration of the inner loop.

Make sure that this is true in all iterations of the outer
loop by setting "new" to NULL after its value is assigned to "cur".

Extend the unittest to detect the double free and add an additional
test case that actually triggers this path.

Fixes: bd6f2fd5a1 ("of: Support parsing phandle argument lists through a nexus node")
Cc: Stephen Boyd <stephen.boyd@linaro.org>
Signed-off-by: "Christian A. Ehrhardt" <lk@c--e.de>
Link: https://lore.kernel.org/r/20231229105411.1603434-1-lk@c--e.de
Signed-off-by: Rob Herring <robh@kernel.org>

authored by

Christian A. Ehrhardt and committed by
Rob Herring
4dde8356 5e3ef454

+53 -32
+1
drivers/of/base.c
··· 1464 1464 out_args->np = new; 1465 1465 of_node_put(cur); 1466 1466 cur = new; 1467 + new = NULL; 1467 1468 } 1468 1469 put: 1469 1470 of_node_put(cur);
+9 -1
drivers/of/unittest-data/tests-phandle.dtsi
··· 40 40 phandle-map-pass-thru = <0x0 0xf0>; 41 41 }; 42 42 43 + provider5: provider5 { 44 + #phandle-cells = <2>; 45 + phandle-map = <2 7 &provider4 2 3>; 46 + phandle-map-mask = <0xff 0xf>; 47 + phandle-map-pass-thru = <0x0 0xf0>; 48 + }; 49 + 43 50 consumer-a { 44 51 phandle-list = <&provider1 1>, 45 52 <&provider2 2 0>, ··· 73 66 <&provider4 4 0x100>, 74 67 <&provider4 0 0x61>, 75 68 <&provider0>, 76 - <&provider4 19 0x20>; 69 + <&provider4 19 0x20>, 70 + <&provider5 2 7>; 77 71 phandle-list-bad-phandle = <12345678 0 0>; 78 72 phandle-list-bad-args = <&provider2 1 0>, 79 73 <&provider4 0>;
+43 -31
drivers/of/unittest.c
··· 456 456 457 457 unittest(passed, "index %i - data error on node %pOF rc=%i\n", 458 458 i, args.np, rc); 459 + 460 + if (rc == 0) 461 + of_node_put(args.np); 459 462 } 460 463 461 464 /* Check for missing list property */ ··· 548 545 549 546 static void __init of_unittest_parse_phandle_with_args_map(void) 550 547 { 551 - struct device_node *np, *p0, *p1, *p2, *p3; 548 + struct device_node *np, *p[6] = {}; 552 549 struct of_phandle_args args; 550 + unsigned int prefs[6]; 553 551 int i, rc; 554 552 555 553 np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-b"); ··· 559 555 return; 560 556 } 561 557 562 - p0 = of_find_node_by_path("/testcase-data/phandle-tests/provider0"); 563 - if (!p0) { 564 - pr_err("missing testcase data\n"); 565 - return; 566 - } 567 - 568 - p1 = of_find_node_by_path("/testcase-data/phandle-tests/provider1"); 569 - if (!p1) { 570 - pr_err("missing testcase data\n"); 571 - return; 572 - } 573 - 574 - p2 = of_find_node_by_path("/testcase-data/phandle-tests/provider2"); 575 - if (!p2) { 576 - pr_err("missing testcase data\n"); 577 - return; 578 - } 579 - 580 - p3 = of_find_node_by_path("/testcase-data/phandle-tests/provider3"); 581 - if (!p3) { 582 - pr_err("missing testcase data\n"); 583 - return; 558 + p[0] = of_find_node_by_path("/testcase-data/phandle-tests/provider0"); 559 + p[1] = of_find_node_by_path("/testcase-data/phandle-tests/provider1"); 560 + p[2] = of_find_node_by_path("/testcase-data/phandle-tests/provider2"); 561 + p[3] = of_find_node_by_path("/testcase-data/phandle-tests/provider3"); 562 + p[4] = of_find_node_by_path("/testcase-data/phandle-tests/provider4"); 563 + p[5] = of_find_node_by_path("/testcase-data/phandle-tests/provider5"); 564 + for (i = 0; i < ARRAY_SIZE(p); ++i) { 565 + if (!p[i]) { 566 + pr_err("missing testcase data\n"); 567 + return; 568 + } 569 + prefs[i] = kref_read(&p[i]->kobj.kref); 584 570 } 585 571 586 572 rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells"); 587 - unittest(rc == 7, "of_count_phandle_with_args() returned %i, expected 7\n", rc); 573 + unittest(rc == 8, "of_count_phandle_with_args() returned %i, expected 7\n", rc); 588 574 589 - for (i = 0; i < 8; i++) { 575 + for (i = 0; i < 9; i++) { 590 576 bool passed = true; 591 577 592 578 memset(&args, 0, sizeof(args)); ··· 587 593 switch (i) { 588 594 case 0: 589 595 passed &= !rc; 590 - passed &= (args.np == p1); 596 + passed &= (args.np == p[1]); 591 597 passed &= (args.args_count == 1); 592 598 passed &= (args.args[0] == 1); 593 599 break; 594 600 case 1: 595 601 passed &= !rc; 596 - passed &= (args.np == p3); 602 + passed &= (args.np == p[3]); 597 603 passed &= (args.args_count == 3); 598 604 passed &= (args.args[0] == 2); 599 605 passed &= (args.args[1] == 5); ··· 604 610 break; 605 611 case 3: 606 612 passed &= !rc; 607 - passed &= (args.np == p0); 613 + passed &= (args.np == p[0]); 608 614 passed &= (args.args_count == 0); 609 615 break; 610 616 case 4: 611 617 passed &= !rc; 612 - passed &= (args.np == p1); 618 + passed &= (args.np == p[1]); 613 619 passed &= (args.args_count == 1); 614 620 passed &= (args.args[0] == 3); 615 621 break; 616 622 case 5: 617 623 passed &= !rc; 618 - passed &= (args.np == p0); 624 + passed &= (args.np == p[0]); 619 625 passed &= (args.args_count == 0); 620 626 break; 621 627 case 6: 622 628 passed &= !rc; 623 - passed &= (args.np == p2); 629 + passed &= (args.np == p[2]); 624 630 passed &= (args.args_count == 2); 625 631 passed &= (args.args[0] == 15); 626 632 passed &= (args.args[1] == 0x20); 627 633 break; 628 634 case 7: 635 + passed &= !rc; 636 + passed &= (args.np == p[3]); 637 + passed &= (args.args_count == 3); 638 + passed &= (args.args[0] == 2); 639 + passed &= (args.args[1] == 5); 640 + passed &= (args.args[2] == 3); 641 + break; 642 + case 8: 629 643 passed &= (rc == -ENOENT); 630 644 break; 631 645 default: ··· 642 640 643 641 unittest(passed, "index %i - data error on node %s rc=%i\n", 644 642 i, args.np->full_name, rc); 643 + 644 + if (rc == 0) 645 + of_node_put(args.np); 645 646 } 646 647 647 648 /* Check for missing list property */ ··· 691 686 "OF: /testcase-data/phandle-tests/consumer-b: #phandle-cells = 2 found 1"); 692 687 693 688 unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); 689 + 690 + for (i = 0; i < ARRAY_SIZE(p); ++i) { 691 + unittest(prefs[i] == kref_read(&p[i]->kobj.kref), 692 + "provider%d: expected:%d got:%d\n", 693 + i, prefs[i], kref_read(&p[i]->kobj.kref)); 694 + of_node_put(p[i]); 695 + } 694 696 } 695 697 696 698 static void __init of_unittest_property_string(void)