2023-02-27 02:29:33

by void0red

[permalink] [raw]
Subject: [PATCH] hwmon: add a check of devm_add_action

devm_add_action may fails, do the cleanup when if fails.

Signed-off-by: Kang Chen <[email protected]>
---
drivers/hwmon/g762.c | 6 +++++-
drivers/hwmon/nzxt-smart2.c | 4 +++-
2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c
index 64a0599b2..d06d8bf20 100644
--- a/drivers/hwmon/g762.c
+++ b/drivers/hwmon/g762.c
@@ -620,7 +620,11 @@ static int g762_of_clock_enable(struct i2c_client *client)
data = i2c_get_clientdata(client);
data->clk = clk;

- devm_add_action(&client->dev, g762_of_clock_disable, data);
+ ret = devm_add_action(&client->dev, g762_of_clock_disable, data);
+ if (ret) {
+ dev_err(&client->dev, "failed to add disable clock action\n");
+ goto clk_unprep;
+ }
return 0;

clk_unprep:
diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
index 2b93ba896..725974cb3 100644
--- a/drivers/hwmon/nzxt-smart2.c
+++ b/drivers/hwmon/nzxt-smart2.c
@@ -737,8 +737,10 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
init_waitqueue_head(&drvdata->wq);

mutex_init(&drvdata->mutex);
- devm_add_action(&hdev->dev, (void (*)(void *))mutex_destroy,
+ ret = devm_add_action(&hdev->dev, (void (*)(void *))mutex_destroy,
&drvdata->mutex);
+ if (ret)
+ return ret;

ret = hid_parse(hdev);
if (ret)
--
2.34.1



2023-02-27 02:38:32

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH] hwmon: add a check of devm_add_action

On 2/26/23 18:17, Kang Chen wrote:
> devm_add_action may fails, do the cleanup when if fails.
>
> Signed-off-by: Kang Chen <[email protected]>
> ---
> drivers/hwmon/g762.c | 6 +++++-
> drivers/hwmon/nzxt-smart2.c | 4 +++-

Two patches, please.

Guenter

> 2 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c
> index 64a0599b2..d06d8bf20 100644
> --- a/drivers/hwmon/g762.c
> +++ b/drivers/hwmon/g762.c
> @@ -620,7 +620,11 @@ static int g762_of_clock_enable(struct i2c_client *client)
> data = i2c_get_clientdata(client);
> data->clk = clk;
>
> - devm_add_action(&client->dev, g762_of_clock_disable, data);
> + ret = devm_add_action(&client->dev, g762_of_clock_disable, data);
> + if (ret) {
> + dev_err(&client->dev, "failed to add disable clock action\n");
> + goto clk_unprep;
> + }
> return 0;
>
> clk_unprep:
> diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
> index 2b93ba896..725974cb3 100644
> --- a/drivers/hwmon/nzxt-smart2.c
> +++ b/drivers/hwmon/nzxt-smart2.c
> @@ -737,8 +737,10 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
> init_waitqueue_head(&drvdata->wq);
>
> mutex_init(&drvdata->mutex);
> - devm_add_action(&hdev->dev, (void (*)(void *))mutex_destroy,
> + ret = devm_add_action(&hdev->dev, (void (*)(void *))mutex_destroy,
> &drvdata->mutex);
> + if (ret)
> + return ret;
>
> ret = hid_parse(hdev);
> if (ret)


2023-02-27 03:09:22

by void0red

[permalink] [raw]
Subject: [PATCH v2 1/2] hwmon: g762: add a check of devm_add_action in g762_of_clock_enable

From: Kang Chen <[email protected]>

devm_add_action may fails, check it and do the cleanup.

Signed-off-by: Kang Chen <[email protected]>
---
v2 -> v1: split the patch

drivers/hwmon/g762.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c
index 64a0599b2..e2c3c34f0 100644
--- a/drivers/hwmon/g762.c
+++ b/drivers/hwmon/g762.c
@@ -620,7 +620,12 @@ static int g762_of_clock_enable(struct i2c_client *client)
data = i2c_get_clientdata(client);
data->clk = clk;

- devm_add_action(&client->dev, g762_of_clock_disable, data);
+ ret = devm_add_action(&client->dev, g762_of_clock_disable, data);
+ if (ret) {
+ dev_err(&client->dev, "failed to add disable clock action\n");
+ goto clk_unprep;
+ }
+
return 0;

clk_unprep:
--
2.34.1


2023-02-27 03:09:30

by void0red

[permalink] [raw]
Subject: [PATCH v2 2/2] hwmon: nzxt-smart2: add a check of devm_add_action in nzxt_smart2_hid_probe

From: Kang Chen <[email protected]>

devm_add_action may fails, check it and return early.

Signed-off-by: Kang Chen <[email protected]>
---
v2 -> v1: split the patch

drivers/hwmon/nzxt-smart2.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
index 2b93ba896..725974cb3 100644
--- a/drivers/hwmon/nzxt-smart2.c
+++ b/drivers/hwmon/nzxt-smart2.c
@@ -737,8 +737,10 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
init_waitqueue_head(&drvdata->wq);

mutex_init(&drvdata->mutex);
- devm_add_action(&hdev->dev, (void (*)(void *))mutex_destroy,
+ ret = devm_add_action(&hdev->dev, (void (*)(void *))mutex_destroy,
&drvdata->mutex);
+ if (ret)
+ return ret;

ret = hid_parse(hdev);
if (ret)
--
2.34.1


2023-02-27 04:21:54

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 2/2] hwmon: nzxt-smart2: add a check of devm_add_action in nzxt_smart2_hid_probe

On 2/26/23 19:09, void0red wrote:
> From: Kang Chen <[email protected]>
>
> devm_add_action may fails, check it and return early.
>
> Signed-off-by: Kang Chen <[email protected]>
> ---
> v2 -> v1: split the patch
>
> drivers/hwmon/nzxt-smart2.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
> index 2b93ba896..725974cb3 100644
> --- a/drivers/hwmon/nzxt-smart2.c
> +++ b/drivers/hwmon/nzxt-smart2.c
> @@ -737,8 +737,10 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
> init_waitqueue_head(&drvdata->wq);
>
> mutex_init(&drvdata->mutex);
> - devm_add_action(&hdev->dev, (void (*)(void *))mutex_destroy,
> + ret = devm_add_action(&hdev->dev, (void (*)(void *))mutex_destroy,
> &drvdata->mutex);

Please watch for multi-line alignment. Also, turns out the original
code is wrong: Type casting a function pointer argument like this,
while it typically works in practice, is undefined in C. The function
pointer passed to devm_add_action() needs to point to a local
function with void * argument, and that function needs to call
mutex_destroy() with the same argument. Also, based on the context,
this needs to call devm_add_action_or_reset() to ensure that
the destroy function is called on error.

Thanks,
Guenter

> + if (ret)
> + return ret;
>
> ret = hid_parse(hdev);
> if (ret)


2023-02-27 09:20:10

by void0red

[permalink] [raw]
Subject: [PATCH v3] hwmon: nzxt-smart2: handle failure of devm_add_action in nzxt_smart2_hid_probe

From: Kang Chen <[email protected]>

1. replace the devm_add_action with devm_add_action_or_reset to ensure
the mutex lock can be destroyed when it fails.
2. use local wrapper function mutex_fini instead of mutex_destroy to
avoid undefined behaviours.
3. add a check of devm_add_action_or_reset and return early when it fails.

Link: https://lore.kernel.org/all/[email protected]
Signed-off-by: Kang Chen <[email protected]>
---
v3 -> v2: use local function and devm_add_action_or_rest
v2 -> v1: split the patch

drivers/hwmon/nzxt-smart2.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
index 2b93ba896..340002581 100644
--- a/drivers/hwmon/nzxt-smart2.c
+++ b/drivers/hwmon/nzxt-smart2.c
@@ -721,6 +721,11 @@ static int __maybe_unused nzxt_smart2_hid_reset_resume(struct hid_device *hdev)
return init_device(drvdata, drvdata->update_interval);
}

+static void mutex_fini(void *lock)
+{
+ mutex_destroy(lock);
+}
+
static int nzxt_smart2_hid_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
@@ -737,8 +742,9 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
init_waitqueue_head(&drvdata->wq);

mutex_init(&drvdata->mutex);
- devm_add_action(&hdev->dev, (void (*)(void *))mutex_destroy,
- &drvdata->mutex);
+ ret = devm_add_action_or_reset(&hdev->dev, mutex_fini, &drvdata->mutex);
+ if (ret)
+ return ret;

ret = hid_parse(hdev);
if (ret)
--
2.34.1


2023-03-10 16:45:59

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] hwmon: g762: add a check of devm_add_action in g762_of_clock_enable

On Mon, Feb 27, 2023 at 11:09:12AM +0800, void0red wrote:
> From: Kang Chen <[email protected]>
>
> devm_add_action may fails, check it and do the cleanup.
>
> Signed-off-by: Kang Chen <[email protected]>

Applied.

Thanks,
Guenter

> ---
> v2 -> v1: split the patch
>
> drivers/hwmon/g762.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c
> index 64a0599b2..e2c3c34f0 100644
> --- a/drivers/hwmon/g762.c
> +++ b/drivers/hwmon/g762.c
> @@ -620,7 +620,12 @@ static int g762_of_clock_enable(struct i2c_client *client)
> data = i2c_get_clientdata(client);
> data->clk = clk;
>
> - devm_add_action(&client->dev, g762_of_clock_disable, data);
> + ret = devm_add_action(&client->dev, g762_of_clock_disable, data);
> + if (ret) {
> + dev_err(&client->dev, "failed to add disable clock action\n");
> + goto clk_unprep;
> + }
> +
> return 0;
>
> clk_unprep:

2023-03-10 16:46:02

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v3] hwmon: nzxt-smart2: handle failure of devm_add_action in nzxt_smart2_hid_probe

On Mon, Feb 27, 2023 at 05:15:34PM +0800, void0red wrote:
> From: Kang Chen <[email protected]>
>
> 1. replace the devm_add_action with devm_add_action_or_reset to ensure
> the mutex lock can be destroyed when it fails.
> 2. use local wrapper function mutex_fini instead of mutex_destroy to
> avoid undefined behaviours.
> 3. add a check of devm_add_action_or_reset and return early when it fails.
>
> Link: https://lore.kernel.org/all/[email protected]
> Signed-off-by: Kang Chen <[email protected]>

Applied.

Thanks,
Guenter

> ---
> v3 -> v2: use local function and devm_add_action_or_rest
> v2 -> v1: split the patch
>
> drivers/hwmon/nzxt-smart2.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
> index 2b93ba896..340002581 100644
> --- a/drivers/hwmon/nzxt-smart2.c
> +++ b/drivers/hwmon/nzxt-smart2.c
> @@ -721,6 +721,11 @@ static int __maybe_unused nzxt_smart2_hid_reset_resume(struct hid_device *hdev)
> return init_device(drvdata, drvdata->update_interval);
> }
>
> +static void mutex_fini(void *lock)
> +{
> + mutex_destroy(lock);
> +}
> +
> static int nzxt_smart2_hid_probe(struct hid_device *hdev,
> const struct hid_device_id *id)
> {
> @@ -737,8 +742,9 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
> init_waitqueue_head(&drvdata->wq);
>
> mutex_init(&drvdata->mutex);
> - devm_add_action(&hdev->dev, (void (*)(void *))mutex_destroy,
> - &drvdata->mutex);
> + ret = devm_add_action_or_reset(&hdev->dev, mutex_fini, &drvdata->mutex);
> + if (ret)
> + return ret;
>
> ret = hid_parse(hdev);
> if (ret)