| From c84389eb7cb049eb98832c4c3f4075f768ba462b Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 8 Oct 2018 13:14:35 +0200 |
| Subject: reset: Fix potential use-after-free in __of_reset_control_get() |
| |
| From: Geert Uytterhoeven <geert+renesas@glider.be> |
| |
| [ Upstream commit b790c8ea5593d6dc3580adfad8e117eeb56af874 ] |
| |
| Calling of_node_put() decreases the reference count of a device tree |
| object, and may free some data. |
| |
| However, the of_phandle_args structure embedding it is passed to |
| reset_controller_dev.of_xlate() after that, so it may still be accessed. |
| |
| Move the call to of_node_put() down to fix this. |
| |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| [p.zabel@pengutronix.de: moved of_node_put after mutex_unlock] |
| Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/reset/core.c | 15 ++++++++------- |
| 1 file changed, 8 insertions(+), 7 deletions(-) |
| |
| diff --git a/drivers/reset/core.c b/drivers/reset/core.c |
| index da4292e9de978..72b96b5c75a8f 100644 |
| --- a/drivers/reset/core.c |
| +++ b/drivers/reset/core.c |
| @@ -466,28 +466,29 @@ struct reset_control *__of_reset_control_get(struct device_node *node, |
| break; |
| } |
| } |
| - of_node_put(args.np); |
| |
| if (!rcdev) { |
| - mutex_unlock(&reset_list_mutex); |
| - return ERR_PTR(-EPROBE_DEFER); |
| + rstc = ERR_PTR(-EPROBE_DEFER); |
| + goto out; |
| } |
| |
| if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) { |
| - mutex_unlock(&reset_list_mutex); |
| - return ERR_PTR(-EINVAL); |
| + rstc = ERR_PTR(-EINVAL); |
| + goto out; |
| } |
| |
| rstc_id = rcdev->of_xlate(rcdev, &args); |
| if (rstc_id < 0) { |
| - mutex_unlock(&reset_list_mutex); |
| - return ERR_PTR(rstc_id); |
| + rstc = ERR_PTR(rstc_id); |
| + goto out; |
| } |
| |
| /* reset_list_mutex also protects the rcdev's reset_control list */ |
| rstc = __reset_control_get_internal(rcdev, rstc_id, shared); |
| |
| +out: |
| mutex_unlock(&reset_list_mutex); |
| + of_node_put(args.np); |
| |
| return rstc; |
| } |
| -- |
| 2.20.1 |
| |