2022-02-22 14:08:30

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [RFT PATCH 0/3] Fix kfree() of const memory on setting driver_override

Hi,

Drivers still seem to use driver_override incorrectly. Perhaps my old
patch makes sense now?
https://lore.kernel.org/all/[email protected]/

Not tested - please review and test (e.g. by writing to dirver_override
sysfs entry with KASAN enabled).

Dependencies
============
Patches are independent.

Best regards,
Krzysztof

Krzysztof Kozlowski (3):
clk: imx: scu: fix kfree() of const memory on setting driver_override
slimbus: qcom-ngd: fix kfree() of const memory on setting
driver_override
rpmsg: fix kfree() of const memory on setting driver_override

drivers/clk/imx/clk-scu.c | 6 +++++-
drivers/rpmsg/rpmsg_internal.h | 12 ++++++++++--
drivers/rpmsg/rpmsg_ns.c | 13 +++++++++++--
drivers/slimbus/qcom-ngd-ctrl.c | 9 ++++++++-
4 files changed, 34 insertions(+), 6 deletions(-)

--
2.32.0


2022-02-22 15:08:19

by Rasmus Villemoes

[permalink] [raw]
Subject: Re: [RFT PATCH 0/3] Fix kfree() of const memory on setting driver_override

On 22/02/2022 14.27, Krzysztof Kozlowski wrote:
> Hi,
>
> Drivers still seem to use driver_override incorrectly. Perhaps my old
> patch makes sense now?
> https://lore.kernel.org/all/[email protected]/
>
> Not tested - please review and test (e.g. by writing to dirver_override
> sysfs entry with KASAN enabled).

Perhaps it would make sense to update the core code to release using
kfree_const(), allowing drivers to set the initial value with
kstrdup_const(). Drivers that currently use kstrdup() or kasprintf()
will continue to work [but if they kstrdup() a string literal they could
be changed to use kstrdup_const].

Rasmus

2022-02-22 15:13:27

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [RFT PATCH 3/3] rpmsg: fix kfree() of const memory on setting driver_override

The driver_override field from rpmsg_device should not be initialized
from const memory because the core later kfree() it, for example when
driver_override is set via sysfs.

Fixes: 950a7388f02b ("rpmsg: Turn name service into a stand alone driver")
Fixes: c0cdc19f84a4 ("rpmsg: Driver for user space endpoint interface")
Cc: <[email protected]>
Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/rpmsg/rpmsg_internal.h | 12 ++++++++++--
drivers/rpmsg/rpmsg_ns.c | 13 +++++++++++--
2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index b1245d3ed7c6..c21e73ffbf05 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -92,10 +92,18 @@ int rpmsg_release_channel(struct rpmsg_device *rpdev,
*/
static inline int rpmsg_chrdev_register_device(struct rpmsg_device *rpdev)
{
+ int ret;
+
strcpy(rpdev->id.name, "rpmsg_chrdev");
- rpdev->driver_override = "rpmsg_chrdev";
+ rpdev->driver_override = kstrdup("rpmsg_chrdev", GFP_KERNEL);
+ if (!rpdev->driver_override)
+ return -ENOMEM;
+
+ ret = rpmsg_register_device(rpdev);
+ if (ret)
+ kfree(rpdev->driver_override);

- return rpmsg_register_device(rpdev);
+ return ret;
}

#endif
diff --git a/drivers/rpmsg/rpmsg_ns.c b/drivers/rpmsg/rpmsg_ns.c
index 762ff1ae279f..7d0605307d23 100644
--- a/drivers/rpmsg/rpmsg_ns.c
+++ b/drivers/rpmsg/rpmsg_ns.c
@@ -20,12 +20,21 @@
*/
int rpmsg_ns_register_device(struct rpmsg_device *rpdev)
{
+ int ret;
+
strcpy(rpdev->id.name, "rpmsg_ns");
- rpdev->driver_override = "rpmsg_ns";
+ rpdev->driver_override = kstrdup("rpmsg_ns", GFP_KERNEL);
+ if (!rpdev->driver_override)
+ return -ENOMEM;
+
rpdev->src = RPMSG_NS_ADDR;
rpdev->dst = RPMSG_NS_ADDR;

- return rpmsg_register_device(rpdev);
+ ret = rpmsg_register_device(rpdev);
+ if (ret)
+ kfree(rpdev->driver_override);
+
+ return ret;
}
EXPORT_SYMBOL(rpmsg_ns_register_device);

--
2.32.0

2022-02-22 16:00:09

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [RFT PATCH 0/3] Fix kfree() of const memory on setting driver_override

On 22/02/2022 14:51, Rasmus Villemoes wrote:
> On 22/02/2022 14.27, Krzysztof Kozlowski wrote:
>> Hi,
>>
>> Drivers still seem to use driver_override incorrectly. Perhaps my old
>> patch makes sense now?
>> https://lore.kernel.org/all/[email protected]/
>>
>> Not tested - please review and test (e.g. by writing to dirver_override
>> sysfs entry with KASAN enabled).
>
> Perhaps it would make sense to update the core code to release using
> kfree_const(), allowing drivers to set the initial value with
> kstrdup_const(). Drivers that currently use kstrdup() or kasprintf()
> will continue to work [but if they kstrdup() a string literal they could
> be changed to use kstrdup_const].

The core here means several buses, so the change would not be that
small. However I don't see the reason why "driver_override" is special
and should be freed with kfree_const() while most of other places don't
use it.

The driver_override field definition is here obvious: "char *", so any
assignments of "const char *" are logically wrong (although GCC does not
warn of this literal string const discarding). Adding kfree_const() is
hiding the problem - someone did not read the definition of assigned field.

Best regards,
Krzysztof

2022-02-22 16:34:10

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [RFT PATCH 2/3] slimbus: qcom-ngd: fix kfree() of const memory on setting driver_override

The driver_override field from platform driver should not be initialized
from const memory because the core later kfree() it, for example when
driver_override is set via sysfs.

Fixes: 917809e2280b ("slimbus: ngd: Add qcom SLIMBus NGD driver")
Cc: <[email protected]>
Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/slimbus/qcom-ngd-ctrl.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
index 7040293c2ee8..5987d8f8a8fd 100644
--- a/drivers/slimbus/qcom-ngd-ctrl.c
+++ b/drivers/slimbus/qcom-ngd-ctrl.c
@@ -1455,7 +1455,14 @@ static int of_qcom_slim_ngd_register(struct device *parent,
}
ngd->id = id;
ngd->pdev->dev.parent = parent;
- ngd->pdev->driver_override = QCOM_SLIM_NGD_DRV_NAME;
+ ngd->pdev->driver_override = kstrdup(QCOM_SLIM_NGD_DRV_NAME,
+ GFP_KERNEL);
+ if (!ngd->pdev->driver_override) {
+ platform_device_put(ngd->pdev);
+ kfree(ngd);
+ of_node_put(node);
+ return -ENOMEM;
+ }
ngd->pdev->dev.of_node = node;
ctrl->ngd = ngd;

--
2.32.0

2022-02-23 16:58:17

by Robin Murphy

[permalink] [raw]
Subject: Re: [RFT PATCH 0/3] Fix kfree() of const memory on setting driver_override

On 2022-02-22 14:06, Krzysztof Kozlowski wrote:
> On 22/02/2022 14:51, Rasmus Villemoes wrote:
>> On 22/02/2022 14.27, Krzysztof Kozlowski wrote:
>>> Hi,
>>>
>>> Drivers still seem to use driver_override incorrectly. Perhaps my old
>>> patch makes sense now?
>>> https://lore.kernel.org/all/[email protected]/
>>>
>>> Not tested - please review and test (e.g. by writing to dirver_override
>>> sysfs entry with KASAN enabled).
>>
>> Perhaps it would make sense to update the core code to release using
>> kfree_const(), allowing drivers to set the initial value with
>> kstrdup_const(). Drivers that currently use kstrdup() or kasprintf()
>> will continue to work [but if they kstrdup() a string literal they could
>> be changed to use kstrdup_const].
>
> The core here means several buses, so the change would not be that
> small. However I don't see the reason why "driver_override" is special
> and should be freed with kfree_const() while most of other places don't
> use it.
>
> The driver_override field definition is here obvious: "char *", so any
> assignments of "const char *" are logically wrong (although GCC does not
> warn of this literal string const discarding). Adding kfree_const() is
> hiding the problem - someone did not read the definition of assigned field.

That's not the issue, though, is it? If I take the struct
platform_device definition at face value, this should be perfectly valid:

static char foo[] = "foo";
pdev->driver_override = &foo;

And in fact that's effectively how the direct assignment form works
anyway - string literals are static arrays of type char (or wchar_t),
*not* const char, however trying to modify them is undefined behaviour.

There's a big difference between "non-const" and "kfree()able", and
AFAICS there's no obvious clue that the latter is actually a requirement.

Cheers,
Robin.

2022-02-23 20:52:32

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [RFT PATCH 0/3] Fix kfree() of const memory on setting driver_override

On 23/02/2022 16:08, Robin Murphy wrote:
> On 2022-02-23 14:22, Krzysztof Kozlowski wrote:
>> On 23/02/2022 15:04, Robin Murphy wrote:
>>> On 2022-02-22 14:06, Krzysztof Kozlowski wrote:
>>>> On 22/02/2022 14:51, Rasmus Villemoes wrote:
>>>>> On 22/02/2022 14.27, Krzysztof Kozlowski wrote:
>>>>>> Hi,
>>>>>>
>>>>>> Drivers still seem to use driver_override incorrectly. Perhaps my old
>>>>>> patch makes sense now?
>>>>>> https://lore.kernel.org/all/[email protected]/
>>>>>>
>>>>>> Not tested - please review and test (e.g. by writing to dirver_override
>>>>>> sysfs entry with KASAN enabled).
>>>>>
>>>>> Perhaps it would make sense to update the core code to release using
>>>>> kfree_const(), allowing drivers to set the initial value with
>>>>> kstrdup_const(). Drivers that currently use kstrdup() or kasprintf()
>>>>> will continue to work [but if they kstrdup() a string literal they could
>>>>> be changed to use kstrdup_const].
>>>>
>>>> The core here means several buses, so the change would not be that
>>>> small. However I don't see the reason why "driver_override" is special
>>>> and should be freed with kfree_const() while most of other places don't
>>>> use it.
>>>>
>>>> The driver_override field definition is here obvious: "char *", so any
>>>> assignments of "const char *" are logically wrong (although GCC does not
>>>> warn of this literal string const discarding). Adding kfree_const() is
>>>> hiding the problem - someone did not read the definition of assigned field.
>>>
>>> That's not the issue, though, is it? If I take the struct
>>> platform_device definition at face value, this should be perfectly valid:
>>>
>>> static char foo[] = "foo";
>>> pdev->driver_override = &foo;
>>
>>
>> Yes, that's not the issue. It's rather about the interface. By
>> convention we do not modify string literals but "char *driver_override"
>> indicates that this is modifiable memory. I would argue that it even
>> means that ownership is passed. Therefore passing string literal to
>> "char *driver_override" is wrong from logical point of view.
>>
>> Plus, as you mentioned later, can lead to undefined behavior.
>
> But does anything actually need to modify a driver_override string? I
> wouldn't have thought so. I see at least two buses that *do* define
> theirs as const char *, but still assume to kfree() them.

I think the drivers/clk/imx/clk-scu.c (fixed here) does not actually
need it. It uses the feature to create multiple platform devices for
each clock, with unique names matching the clock (e.g. pwm0_clk,
pwm1_clk) and then bind all them via common clock driver.

It looks therefore like something for convenience of debugging or going
through sysfs devices.

Removal of driver_override from such drivers is a bit too much here,
because I would not be able to test it.

>
>>> And in fact that's effectively how the direct assignment form works
>>> anyway - string literals are static arrays of type char (or wchar_t),
>>> *not* const char, however trying to modify them is undefined behaviour.
>>>
>>> There's a big difference between "non-const" and "kfree()able", and
>>> AFAICS there's no obvious clue that the latter is actually a requirement.
>>
>> Then maybe kfreeable should be made a requirement? Or at least clearly
>> documented?
>
> Indeed, there's clearly some room for improvement still. And I'm not
> suggesting that these changes aren't already sensible as they are, just
> that the given justification seems a little unfair :)

Yeah, maybe also my "const" in the title and commit is not accurate. I
think that literal strings are part of .rodata (and objdump confirm)
thus are considered const.

> Even kfree_const() can't help if someone has put their string in the
> middle of some larger block of kmalloc()ed memory, so perhaps
> encouraging a dedicated setter function rather than just exposing a raw
> string pointer is the ideal solution in the long term.


Best regards,
Krzysztof

2022-02-24 00:35:09

by Robin Murphy

[permalink] [raw]
Subject: Re: [RFT PATCH 0/3] Fix kfree() of const memory on setting driver_override

On 2022-02-23 14:22, Krzysztof Kozlowski wrote:
> On 23/02/2022 15:04, Robin Murphy wrote:
>> On 2022-02-22 14:06, Krzysztof Kozlowski wrote:
>>> On 22/02/2022 14:51, Rasmus Villemoes wrote:
>>>> On 22/02/2022 14.27, Krzysztof Kozlowski wrote:
>>>>> Hi,
>>>>>
>>>>> Drivers still seem to use driver_override incorrectly. Perhaps my old
>>>>> patch makes sense now?
>>>>> https://lore.kernel.org/all/[email protected]/
>>>>>
>>>>> Not tested - please review and test (e.g. by writing to dirver_override
>>>>> sysfs entry with KASAN enabled).
>>>>
>>>> Perhaps it would make sense to update the core code to release using
>>>> kfree_const(), allowing drivers to set the initial value with
>>>> kstrdup_const(). Drivers that currently use kstrdup() or kasprintf()
>>>> will continue to work [but if they kstrdup() a string literal they could
>>>> be changed to use kstrdup_const].
>>>
>>> The core here means several buses, so the change would not be that
>>> small. However I don't see the reason why "driver_override" is special
>>> and should be freed with kfree_const() while most of other places don't
>>> use it.
>>>
>>> The driver_override field definition is here obvious: "char *", so any
>>> assignments of "const char *" are logically wrong (although GCC does not
>>> warn of this literal string const discarding). Adding kfree_const() is
>>> hiding the problem - someone did not read the definition of assigned field.
>>
>> That's not the issue, though, is it? If I take the struct
>> platform_device definition at face value, this should be perfectly valid:
>>
>> static char foo[] = "foo";
>> pdev->driver_override = &foo;
>
>
> Yes, that's not the issue. It's rather about the interface. By
> convention we do not modify string literals but "char *driver_override"
> indicates that this is modifiable memory. I would argue that it even
> means that ownership is passed. Therefore passing string literal to
> "char *driver_override" is wrong from logical point of view.
>
> Plus, as you mentioned later, can lead to undefined behavior.

But does anything actually need to modify a driver_override string? I
wouldn't have thought so. I see at least two buses that *do* define
theirs as const char *, but still assume to kfree() them.

>> And in fact that's effectively how the direct assignment form works
>> anyway - string literals are static arrays of type char (or wchar_t),
>> *not* const char, however trying to modify them is undefined behaviour.
>>
>> There's a big difference between "non-const" and "kfree()able", and
>> AFAICS there's no obvious clue that the latter is actually a requirement.
>
> Then maybe kfreeable should be made a requirement? Or at least clearly
> documented?

Indeed, there's clearly some room for improvement still. And I'm not
suggesting that these changes aren't already sensible as they are, just
that the given justification seems a little unfair :)

Even kfree_const() can't help if someone has put their string in the
middle of some larger block of kmalloc()ed memory, so perhaps
encouraging a dedicated setter function rather than just exposing a raw
string pointer is the ideal solution in the long term.

Cheers,
Robin.

2022-02-24 00:53:49

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [RFT PATCH 0/3] Fix kfree() of const memory on setting driver_override

On 23/02/2022 15:04, Robin Murphy wrote:
> On 2022-02-22 14:06, Krzysztof Kozlowski wrote:
>> On 22/02/2022 14:51, Rasmus Villemoes wrote:
>>> On 22/02/2022 14.27, Krzysztof Kozlowski wrote:
>>>> Hi,
>>>>
>>>> Drivers still seem to use driver_override incorrectly. Perhaps my old
>>>> patch makes sense now?
>>>> https://lore.kernel.org/all/[email protected]/
>>>>
>>>> Not tested - please review and test (e.g. by writing to dirver_override
>>>> sysfs entry with KASAN enabled).
>>>
>>> Perhaps it would make sense to update the core code to release using
>>> kfree_const(), allowing drivers to set the initial value with
>>> kstrdup_const(). Drivers that currently use kstrdup() or kasprintf()
>>> will continue to work [but if they kstrdup() a string literal they could
>>> be changed to use kstrdup_const].
>>
>> The core here means several buses, so the change would not be that
>> small. However I don't see the reason why "driver_override" is special
>> and should be freed with kfree_const() while most of other places don't
>> use it.
>>
>> The driver_override field definition is here obvious: "char *", so any
>> assignments of "const char *" are logically wrong (although GCC does not
>> warn of this literal string const discarding). Adding kfree_const() is
>> hiding the problem - someone did not read the definition of assigned field.
>
> That's not the issue, though, is it? If I take the struct
> platform_device definition at face value, this should be perfectly valid:
>
> static char foo[] = "foo";
> pdev->driver_override = &foo;


Yes, that's not the issue. It's rather about the interface. By
convention we do not modify string literals but "char *driver_override"
indicates that this is modifiable memory. I would argue that it even
means that ownership is passed. Therefore passing string literal to
"char *driver_override" is wrong from logical point of view.

Plus, as you mentioned later, can lead to undefined behavior.

>
> And in fact that's effectively how the direct assignment form works
> anyway - string literals are static arrays of type char (or wchar_t),
> *not* const char, however trying to modify them is undefined behaviour.
>
> There's a big difference between "non-const" and "kfree()able", and
> AFAICS there's no obvious clue that the latter is actually a requirement.

Then maybe kfreeable should be made a requirement? Or at least clearly
documented?


Best regards,
Krzysztof