| From 57a6ad482af256b2a13de14194fb8f67c1a65f10 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= <mirq-linux@rere.qmqm.pl> |
| Date: Fri, 13 Nov 2020 01:20:27 +0100 |
| Subject: regulator: fix memory leak with repeated set_machine_constraints() |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Michał Mirosław <mirq-linux@rere.qmqm.pl> |
| |
| commit 57a6ad482af256b2a13de14194fb8f67c1a65f10 upstream. |
| |
| Fixed commit introduced a possible second call to |
| set_machine_constraints() and that allocates memory for |
| rdev->constraints. Move the allocation to the caller so |
| it's easier to manage and done once. |
| |
| Fixes: aea6cb99703e ("regulator: resolve supply after creating regulator") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl> |
| Tested-by: Ahmad Fatoum <a.fatoum@pengutronix.de> # stpmic1 |
| Link: https://lore.kernel.org/r/78c3d4016cebc08d441aad18cb924b4e4d9cf9df.1605226675.git.mirq-linux@rere.qmqm.pl |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/regulator/core.c | 29 +++++++++++++---------------- |
| 1 file changed, 13 insertions(+), 16 deletions(-) |
| |
| --- a/drivers/regulator/core.c |
| +++ b/drivers/regulator/core.c |
| @@ -1091,7 +1091,6 @@ static int _regulator_do_enable(struct r |
| /** |
| * set_machine_constraints - sets regulator constraints |
| * @rdev: regulator source |
| - * @constraints: constraints to apply |
| * |
| * Allows platform initialisation code to define and constrain |
| * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: |
| @@ -1099,21 +1098,11 @@ static int _regulator_do_enable(struct r |
| * regulator operations to proceed i.e. set_voltage, set_current_limit, |
| * set_mode. |
| */ |
| -static int set_machine_constraints(struct regulator_dev *rdev, |
| - const struct regulation_constraints *constraints) |
| +static int set_machine_constraints(struct regulator_dev *rdev) |
| { |
| int ret = 0; |
| const struct regulator_ops *ops = rdev->desc->ops; |
| |
| - if (constraints) |
| - rdev->constraints = kmemdup(constraints, sizeof(*constraints), |
| - GFP_KERNEL); |
| - else |
| - rdev->constraints = kzalloc(sizeof(*constraints), |
| - GFP_KERNEL); |
| - if (!rdev->constraints) |
| - return -ENOMEM; |
| - |
| ret = machine_constraints_voltage(rdev, rdev->constraints); |
| if (ret != 0) |
| return ret; |
| @@ -4257,7 +4246,6 @@ struct regulator_dev * |
| regulator_register(const struct regulator_desc *regulator_desc, |
| const struct regulator_config *cfg) |
| { |
| - const struct regulation_constraints *constraints = NULL; |
| const struct regulator_init_data *init_data; |
| struct regulator_config *config = NULL; |
| static atomic_t regulator_no = ATOMIC_INIT(-1); |
| @@ -4358,14 +4346,23 @@ regulator_register(const struct regulato |
| |
| /* set regulator constraints */ |
| if (init_data) |
| - constraints = &init_data->constraints; |
| + rdev->constraints = kmemdup(&init_data->constraints, |
| + sizeof(*rdev->constraints), |
| + GFP_KERNEL); |
| + else |
| + rdev->constraints = kzalloc(sizeof(*rdev->constraints), |
| + GFP_KERNEL); |
| + if (!rdev->constraints) { |
| + ret = -ENOMEM; |
| + goto wash; |
| + } |
| |
| if (init_data && init_data->supply_regulator) |
| rdev->supply_name = init_data->supply_regulator; |
| else if (regulator_desc->supply_name) |
| rdev->supply_name = regulator_desc->supply_name; |
| |
| - ret = set_machine_constraints(rdev, constraints); |
| + ret = set_machine_constraints(rdev); |
| if (ret == -EPROBE_DEFER) { |
| /* Regulator might be in bypass mode and so needs its supply |
| * to set the constraints */ |
| @@ -4374,7 +4371,7 @@ regulator_register(const struct regulato |
| * that is just being created */ |
| ret = regulator_resolve_supply(rdev); |
| if (!ret) |
| - ret = set_machine_constraints(rdev, constraints); |
| + ret = set_machine_constraints(rdev); |
| else |
| rdev_dbg(rdev, "unable to resolve supply early: %pe\n", |
| ERR_PTR(ret)); |