diff mbox series

[RFC,v1] clk: Fix potential NULL dereference in clk_fetch_parent_index()

Message ID 20190815223155.21384-1-martin.blumenstingl@googlemail.com (mailing list archive)
State Accepted, archived
Headers show
Series [RFC,v1] clk: Fix potential NULL dereference in clk_fetch_parent_index() | expand

Commit Message

Martin Blumenstingl Aug. 15, 2019, 10:31 p.m. UTC
Don't compare the parent clock name with a NULL name in the
clk_parent_map. This prevents a kernel crash when passing NULL
core->parents[i].name to strcmp().

An example which triggered this is a mux clock with four parents when
each of them is referenced in the clock driver using
clk_parent_data.fw_name and then calling clk_set_parent(clk, 3rd_parent)
on this mux.
In this case the first parent is also the HW default so
core->parents[i].hw is populated when the clock is registered. Calling
clk_set_parent(clk, 3rd_parent) will then go through all parents and
skip the first parent because it's hw pointer doesn't match. For the
second parent no hw pointer is cached yet and clk_core_get(core, 1)
returns a non-matching pointer (which is correct because we are comparing
the second with the third parent). Comparing the result of
clk_core_get(core, 2) with the requested parent gives a match. However
we don't reach this point because right after the clk_core_get(core, 1)
mismatch the old code tried to !strcmp(parent->name, NULL) (where the
second argument is actually core->parents[i].name, but that was never
populated by the clock driver).

Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
I have seen the original crash when I was testing an MMC driver which
is not upstream yet on v5.3-rc4. I'm not sure whether this fix is
"correct" (it fixes the crash for me) or where to point the Fixes tag
to, it may be one of:
- fc0c209c147f ("clk: Allow parents to be specified without string names")
- 1a079560b145 ("clk: Cache core in clk_fetch_parent_index() without names")

This is meant to be applied on top of v5.3-rc4.


 drivers/clk/clk.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

Comments

Stephen Boyd Aug. 15, 2019, 11:29 p.m. UTC | #1
Quoting Martin Blumenstingl (2019-08-15 15:31:55)
> Don't compare the parent clock name with a NULL name in the
> clk_parent_map. This prevents a kernel crash when passing NULL
> core->parents[i].name to strcmp().
> 
> An example which triggered this is a mux clock with four parents when
> each of them is referenced in the clock driver using
> clk_parent_data.fw_name and then calling clk_set_parent(clk, 3rd_parent)
> on this mux.
> In this case the first parent is also the HW default so
> core->parents[i].hw is populated when the clock is registered. Calling
> clk_set_parent(clk, 3rd_parent) will then go through all parents and
> skip the first parent because it's hw pointer doesn't match. For the
> second parent no hw pointer is cached yet and clk_core_get(core, 1)
> returns a non-matching pointer (which is correct because we are comparing
> the second with the third parent). Comparing the result of
> clk_core_get(core, 2) with the requested parent gives a match. However
> we don't reach this point because right after the clk_core_get(core, 1)
> mismatch the old code tried to !strcmp(parent->name, NULL) (where the
> second argument is actually core->parents[i].name, but that was never
> populated by the clock driver).
> 
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> ---
> I have seen the original crash when I was testing an MMC driver which
> is not upstream yet on v5.3-rc4. I'm not sure whether this fix is
> "correct" (it fixes the crash for me) or where to point the Fixes tag
> to, it may be one of:
> - fc0c209c147f ("clk: Allow parents to be specified without string names")
> - 1a079560b145 ("clk: Cache core in clk_fetch_parent_index() without names")
> 
> This is meant to be applied on top of v5.3-rc4.
> 

Ah ok. I thought that strcmp() would ignore NULL arguments, but
apparently not. I can apply this to clk-fixes.
Martin Blumenstingl Aug. 16, 2019, 6:48 a.m. UTC | #2
Hi Stephen,

On Fri, Aug 16, 2019 at 1:29 AM Stephen Boyd <sboyd@kernel.org> wrote:
>
> Quoting Martin Blumenstingl (2019-08-15 15:31:55)
> > Don't compare the parent clock name with a NULL name in the
> > clk_parent_map. This prevents a kernel crash when passing NULL
> > core->parents[i].name to strcmp().
> >
> > An example which triggered this is a mux clock with four parents when
> > each of them is referenced in the clock driver using
> > clk_parent_data.fw_name and then calling clk_set_parent(clk, 3rd_parent)
> > on this mux.
> > In this case the first parent is also the HW default so
> > core->parents[i].hw is populated when the clock is registered. Calling
> > clk_set_parent(clk, 3rd_parent) will then go through all parents and
> > skip the first parent because it's hw pointer doesn't match. For the
> > second parent no hw pointer is cached yet and clk_core_get(core, 1)
> > returns a non-matching pointer (which is correct because we are comparing
> > the second with the third parent). Comparing the result of
> > clk_core_get(core, 2) with the requested parent gives a match. However
> > we don't reach this point because right after the clk_core_get(core, 1)
> > mismatch the old code tried to !strcmp(parent->name, NULL) (where the
> > second argument is actually core->parents[i].name, but that was never
> > populated by the clock driver).
> >
> > Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> > ---
> > I have seen the original crash when I was testing an MMC driver which
> > is not upstream yet on v5.3-rc4. I'm not sure whether this fix is
> > "correct" (it fixes the crash for me) or where to point the Fixes tag
> > to, it may be one of:
> > - fc0c209c147f ("clk: Allow parents to be specified without string names")
> > - 1a079560b145 ("clk: Cache core in clk_fetch_parent_index() without names")
> >
> > This is meant to be applied on top of v5.3-rc4.
> >
>
> Ah ok. I thought that strcmp() would ignore NULL arguments, but
> apparently not. I can apply this to clk-fixes.
at least ARM [0] and the generic [1] implementations don't

I did not bisect this so do you have any suggestion for a Fixes tag? I
mentioned two candidates above, but I'm not sure which one to use
just let me know, then I'll resend with the fixes tag so you can take
it through clk-fixes


Martin


[0] https://elixir.bootlin.com/linux/v5.2/source/arch/arm/boot/compressed/string.c#L91
[1] https://elixir.bootlin.com/linux/v5.2/source/lib/string.c#L356
Stephen Boyd Aug. 16, 2019, 5:30 p.m. UTC | #3
Quoting Martin Blumenstingl (2019-08-15 15:31:55)
> Don't compare the parent clock name with a NULL name in the
> clk_parent_map. This prevents a kernel crash when passing NULL
> core->parents[i].name to strcmp().
> 
> An example which triggered this is a mux clock with four parents when
> each of them is referenced in the clock driver using
> clk_parent_data.fw_name and then calling clk_set_parent(clk, 3rd_parent)
> on this mux.
> In this case the first parent is also the HW default so
> core->parents[i].hw is populated when the clock is registered. Calling
> clk_set_parent(clk, 3rd_parent) will then go through all parents and
> skip the first parent because it's hw pointer doesn't match. For the
> second parent no hw pointer is cached yet and clk_core_get(core, 1)
> returns a non-matching pointer (which is correct because we are comparing
> the second with the third parent). Comparing the result of
> clk_core_get(core, 2) with the requested parent gives a match. However
> we don't reach this point because right after the clk_core_get(core, 1)
> mismatch the old code tried to !strcmp(parent->name, NULL) (where the
> second argument is actually core->parents[i].name, but that was never
> populated by the clock driver).
> 
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> ---

Applied to clk-fixes
Stephen Boyd Aug. 16, 2019, 5:31 p.m. UTC | #4
Quoting Martin Blumenstingl (2019-08-15 23:48:08)
> > > I have seen the original crash when I was testing an MMC driver which
> > > is not upstream yet on v5.3-rc4. I'm not sure whether this fix is
> > > "correct" (it fixes the crash for me) or where to point the Fixes tag
> > > to, it may be one of:
> > > - fc0c209c147f ("clk: Allow parents to be specified without string names")
> > > - 1a079560b145 ("clk: Cache core in clk_fetch_parent_index() without names")
> > >
> > > This is meant to be applied on top of v5.3-rc4.
> > >
> >
> > Ah ok. I thought that strcmp() would ignore NULL arguments, but
> > apparently not. I can apply this to clk-fixes.
> at least ARM [0] and the generic [1] implementations don't
> 
> I did not bisect this so do you have any suggestion for a Fixes tag? I
> mentioned two candidates above, but I'm not sure which one to use
> just let me know, then I'll resend with the fixes tag so you can take
> it through clk-fixes
> 
> 

I added the fixes tag for the first one, where it was broken, i.e.
fc0c209c147f. Thanks.
Neil Armstrong Aug. 19, 2019, 8:43 a.m. UTC | #5
Hi,

On 16/08/2019 19:31, Stephen Boyd wrote:
> Quoting Martin Blumenstingl (2019-08-15 23:48:08)
>>>> I have seen the original crash when I was testing an MMC driver which
>>>> is not upstream yet on v5.3-rc4. I'm not sure whether this fix is
>>>> "correct" (it fixes the crash for me) or where to point the Fixes tag
>>>> to, it may be one of:
>>>> - fc0c209c147f ("clk: Allow parents to be specified without string names")
>>>> - 1a079560b145 ("clk: Cache core in clk_fetch_parent_index() without names")
>>>>
>>>> This is meant to be applied on top of v5.3-rc4.
>>>>
>>>
>>> Ah ok. I thought that strcmp() would ignore NULL arguments, but
>>> apparently not. I can apply this to clk-fixes.
>> at least ARM [0] and the generic [1] implementations don't
>>
>> I did not bisect this so do you have any suggestion for a Fixes tag? I
>> mentioned two candidates above, but I'm not sure which one to use
>> just let me know, then I'll resend with the fixes tag so you can take
>> it through clk-fixes
>>
>>
> 
> I added the fixes tag for the first one, where it was broken, i.e.
> fc0c209c147f. Thanks.
> 

For the record, this also fixes the Amlogic Meson GXBB/GXL when AO-CEC driver
is enabled :

[    7.790319] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
[    7.790324] Mem abort info:
[    7.790326]   ESR = 0x96000007
[    7.790330]   Exception class = DABT (current EL), IL = 32 bits
[    7.790331]   SET = 0, FnV = 0
[    7.790333]   EA = 0, S1PTW = 0
[    7.790334] Data abort info:
[    7.790336]   ISV = 0, ISS = 0x00000007
[    7.790337]   CM = 0, WnR = 0
[    7.790341] user pgtable: 4k pages, 48-bit VAs, pgdp=00000000364b7000
[    7.790343] [0000000000000000] pgd=00000000364f5003, pud=00000000364f6003, pmd=00000000364f7003, pte=0000000000000000
[    7.790350] Internal error: Oops: 96000007 [#1] SMP
[    7.790461] Modules linked in: ao_cec(+)
[    7.793569] CPU: 1 PID: 398 Comm: systemd-udevd Not tainted 5.3.0-rc5 #1
[    7.800199] Hardware name: Libre Computer Board AML-S905X-CC (DT)
[    7.806233] pstate: 40000005 (nZcv daif -PAN -UAO)
[    7.810985] pc : __pi_strcmp+0x1c/0x154
[    7.814775] lr : clk_fetch_parent_index.part.43+0xe4/0x120
[    7.820203] sp : ffff0000113d3770
[    7.823481] x29: ffff0000113d3770 x28: ffff00001136f000
[    7.828741] x27: 0000000000000100 x26: ffff000010130648
[    7.834012] x25: ffff000008943100 x24: 0000000000008000
[    7.839273] x23: ffff80007c15cc00 x22: ffff80007c15cd00
[    7.844525] x21: ffff80007c15ca00 x20: 0000000000000000
[    7.849791] x19: 0000000000000000 x18: 0000000000000001
[    7.855048] x17: 0000000000000000 x16: 0000000000000000
[    7.860316] x15: ffffffffffffffff x14: ffffffffffffffff
[    7.865578] x13: 0000000000000028 x12: 0101010101010101
[    7.870831] x11: 0000000000000004 x10: 0101010101010101
[    7.876092] x9 : ffffffffffffffff x8 : 7f7f7f7f7f7f7f7f
[    7.881354] x7 : 0000000000000000 x6 : 0d0d0206ebadf2e1
[    7.886615] x5 : 61722d6b06020d0d x4 : 8080808000000000
[    7.891876] x3 : 36c6f636b2d72610 x2 : 00006b32335f6f61
[    7.897137] x1 : 0000000000000000 x0 : ffff000010b147f0
[    7.902405] Call trace:
[    7.904825]  __pi_strcmp+0x1c/0x154
[    7.908269]  clk_calc_new_rates+0x208/0x260
[    7.912419]  clk_calc_new_rates+0x10c/0x260
[    7.916556]  clk_core_set_rate_nolock+0xe8/0x1e8
[    7.921129]  clk_set_rate+0x34/0xa0
[    7.924583]  meson_ao_cec_probe+0x19c/0x278 [ao_cec]
[    7.929498]  platform_drv_probe+0x50/0xa0
[    7.933461]  really_probe+0xec/0x3d0
[    7.936989]  driver_probe_device+0xdc/0x130
[    7.941128]  device_driver_attach+0x6c/0x78
[    7.945267]  __driver_attach+0x9c/0x168
[    7.949065]  bus_for_each_dev+0x70/0xc0
[    7.952860]  driver_attach+0x20/0x28
[    7.956394]  bus_add_driver+0x190/0x220
[    7.960190]  driver_register+0x60/0x110
[    7.963987]  __platform_driver_register+0x44/0x50
[    7.968646]  meson_ao_cec_driver_init+0x1c/0x1000 [ao_cec]
[    7.974079]  do_one_initcall+0x74/0x1b0
[    7.977873]  do_init_module+0x50/0x208
[    7.981581]  load_module+0x1dc4/0x2350
[    7.985288]  __se_sys_finit_module+0x9c/0xf8
[    7.989515]  __arm64_sys_finit_module+0x18/0x20
[    7.994001]  el0_svc_common.constprop.0+0x7c/0xe8
[    7.998658]  el0_svc_compat_handler+0x18/0x20
[    8.002970]  el0_svc_compat+0x8/0x10
[    8.006510] Code: 540002e1 f2400807 54000141 f8408402 (f8408423)
[    8.012543] ---[ end trace e915b8961764bcd0 ]---

Neil
diff mbox series

Patch

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index c0990703ce54..567a044a368b 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1632,7 +1632,8 @@  static int clk_fetch_parent_index(struct clk_core *core,
 			break;
 
 		/* Fallback to comparing globally unique names */
-		if (!strcmp(parent->name, core->parents[i].name))
+		if (core->parents[i].name &&
+		    !strcmp(parent->name, core->parents[i].name))
 			break;
 	}