CVE-2026-46288
Description
In the Linux kernel, the following vulnerability has been resolved:
of: unittest: fix use-after-free in of_unittest_changeset()
The variable 'parent' is assigned the value of 'nchangeset' earlier in the function, meaning both point to the same struct device_node. The call to of_node_put(nchangeset) can decrement the reference count to zero and free the node if there are no other holders. After that, the code still uses 'parent' to check for the presence of a property and to read a string property, leading to a use-after-free.
Fix this by moving the of_node_put() call after the last access to 'parent', avoiding the UAF.
Affected products
1Patches
86fdad20b7975of: unittest: fix use-after-free in of_unittest_changeset()
1 file changed · +1 −3
drivers/of/unittest.c+1 −3 modifieddiff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 2940295843e6f..eae7ebdf5130d 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -896,8 +896,6 @@ static void __init of_unittest_changeset(void) unittest(!of_changeset_apply(&chgset), "apply failed\n"); - of_node_put(nchangeset); - /* Make sure node names are constructed correctly */ unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")), "'%pOF' not added\n", n21); @@ -919,6 +917,7 @@ static void __init of_unittest_changeset(void) if (!ret) unittest(strcmp(propstr, "hello") == 0, "original value not in updated property after revert"); + of_node_put(nchangeset); of_changeset_destroy(&chgset); of_node_put(n1); -- cgit 1.3-korg
37318d1a27c9of: unittest: fix use-after-free in of_unittest_changeset()
1 file changed · +1 −3
drivers/of/unittest.c+1 −3 modifieddiff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index ba223736237e8..bd58b9524791e 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -887,8 +887,6 @@ static void __init of_unittest_changeset(void) unittest(!of_changeset_apply(&chgset), "apply failed\n"); - of_node_put(nchangeset); - /* Make sure node names are constructed correctly */ unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")), "'%pOF' not added\n", n21); @@ -910,6 +908,7 @@ static void __init of_unittest_changeset(void) if (!ret) unittest(strcmp(propstr, "hello") == 0, "original value not in updated property after revert"); + of_node_put(nchangeset); of_changeset_destroy(&chgset); of_node_put(n1); -- cgit 1.3-korg
7f0f0926f301of: unittest: fix use-after-free in of_unittest_changeset()
1 file changed · +1 −3
drivers/of/unittest.c+1 −3 modifieddiff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 9c184e93f50c6..f19abb42db40d 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -896,8 +896,6 @@ static void __init of_unittest_changeset(void) unittest(!of_changeset_apply(&chgset), "apply failed\n"); - of_node_put(nchangeset); - /* Make sure node names are constructed correctly */ unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")), "'%pOF' not added\n", n21); @@ -919,6 +917,7 @@ static void __init of_unittest_changeset(void) if (!ret) unittest(strcmp(propstr, "hello") == 0, "original value not in updated property after revert"); + of_node_put(nchangeset); of_changeset_destroy(&chgset); of_node_put(n1); -- cgit 1.3-korg
faecdd423c27of: unittest: fix use-after-free in of_unittest_changeset()
1 file changed · +1 −3
drivers/of/unittest.c+1 −3 modifieddiff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 2940295843e6f..eae7ebdf5130d 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -896,8 +896,6 @@ static void __init of_unittest_changeset(void) unittest(!of_changeset_apply(&chgset), "apply failed\n"); - of_node_put(nchangeset); - /* Make sure node names are constructed correctly */ unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")), "'%pOF' not added\n", n21); @@ -919,6 +917,7 @@ static void __init of_unittest_changeset(void) if (!ret) unittest(strcmp(propstr, "hello") == 0, "original value not in updated property after revert"); + of_node_put(nchangeset); of_changeset_destroy(&chgset); of_node_put(n1); -- cgit 1.3-korg
faecdd423c27of: unittest: fix use-after-free in of_unittest_changeset()
1 file changed · +1 −3
drivers/of/unittest.c+1 −3 modifieddiff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 2940295843e6f..eae7ebdf5130d 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -896,8 +896,6 @@ static void __init of_unittest_changeset(void) unittest(!of_changeset_apply(&chgset), "apply failed\n"); - of_node_put(nchangeset); - /* Make sure node names are constructed correctly */ unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")), "'%pOF' not added\n", n21); @@ -919,6 +917,7 @@ static void __init of_unittest_changeset(void) if (!ret) unittest(strcmp(propstr, "hello") == 0, "original value not in updated property after revert"); + of_node_put(nchangeset); of_changeset_destroy(&chgset); of_node_put(n1); -- cgit 1.3-korg
37318d1a27c9of: unittest: fix use-after-free in of_unittest_changeset()
1 file changed · +1 −3
drivers/of/unittest.c+1 −3 modifieddiff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index ba223736237e8..bd58b9524791e 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -887,8 +887,6 @@ static void __init of_unittest_changeset(void) unittest(!of_changeset_apply(&chgset), "apply failed\n"); - of_node_put(nchangeset); - /* Make sure node names are constructed correctly */ unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")), "'%pOF' not added\n", n21); @@ -910,6 +908,7 @@ static void __init of_unittest_changeset(void) if (!ret) unittest(strcmp(propstr, "hello") == 0, "original value not in updated property after revert"); + of_node_put(nchangeset); of_changeset_destroy(&chgset); of_node_put(n1); -- cgit 1.3-korg
6fdad20b7975of: unittest: fix use-after-free in of_unittest_changeset()
1 file changed · +1 −3
drivers/of/unittest.c+1 −3 modifieddiff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 2940295843e6f..eae7ebdf5130d 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -896,8 +896,6 @@ static void __init of_unittest_changeset(void) unittest(!of_changeset_apply(&chgset), "apply failed\n"); - of_node_put(nchangeset); - /* Make sure node names are constructed correctly */ unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")), "'%pOF' not added\n", n21); @@ -919,6 +917,7 @@ static void __init of_unittest_changeset(void) if (!ret) unittest(strcmp(propstr, "hello") == 0, "original value not in updated property after revert"); + of_node_put(nchangeset); of_changeset_destroy(&chgset); of_node_put(n1); -- cgit 1.3-korg
7f0f0926f301of: unittest: fix use-after-free in of_unittest_changeset()
1 file changed · +1 −3
drivers/of/unittest.c+1 −3 modifieddiff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 9c184e93f50c6..f19abb42db40d 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -896,8 +896,6 @@ static void __init of_unittest_changeset(void) unittest(!of_changeset_apply(&chgset), "apply failed\n"); - of_node_put(nchangeset); - /* Make sure node names are constructed correctly */ unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")), "'%pOF' not added\n", n21); @@ -919,6 +917,7 @@ static void __init of_unittest_changeset(void) if (!ret) unittest(strcmp(propstr, "hello") == 0, "original value not in updated property after revert"); + of_node_put(nchangeset); of_changeset_destroy(&chgset); of_node_put(n1); -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"The code uses a device node after it has been freed, leading to a use-after-free vulnerability."
Attack vector
An attacker can trigger this vulnerability by manipulating the device tree during runtime. The vulnerability occurs within the `of_unittest_changeset()` function. Specifically, the `of_node_put(nchangeset)` call can free the `nchangeset` node prematurely. Subsequently, the code attempts to access the `parent` variable, which points to the same freed node, to check for property presence and read a string property. This leads to a use-after-free condition.
Affected code
The vulnerability exists in the `of_unittest_changeset()` function within the file `drivers/of/unittest.c`. The issue stems from the order of operations involving the `nchangeset` and `parent` variables and the `of_node_put()` function.
What the fix does
The patch moves the `of_node_put(nchangeset)` call to a later point in the `of_unittest_changeset()` function. This ensures that the `parent` variable, which is an alias for `nchangeset`, is no longer used after the node has been potentially freed. By deferring the `of_node_put()` call until after all accesses to `parent` are completed, the use-after-free condition is avoided [patch_id=5239954].
Generated on Jun 8, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4News mentions
0No linked articles in our index yet.