| From 8991a30b9b81a38f1ac8aca7cf60daa55c326b7e Mon Sep 17 00:00:00 2001 |
| From: Wen Yang <wen.yang99@zte.com.cn> |
| Date: Mon, 8 Jul 2019 14:19:05 +0800 |
| Subject: [PATCH] phy: ti: am654-serdes: fix an use-after-free in |
| serdes_am654_clk_register() |
| |
| commit 3e644828421e31167bedd8dc4d291cdcc822ab20 upstream. |
| |
| The regmap_node variable is still being used in the syscon_node_to_regmap() |
| call after the of_node_put() call, which may result in use-after-free. |
| |
| Fixes: 71e2f5c5c224 ("phy: ti: Add a new SERDES driver for TI's AM654x SoC") |
| Signed-off-by: Wen Yang <wen.yang99@zte.com.cn> |
| Cc: Kishon Vijay Abraham I <kishon@ti.com> |
| Cc: Roger Quadros <rogerq@ti.com> |
| Reviewed-by: Roger Quadros <rogerq@ti.com> |
| Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/phy/ti/phy-am654-serdes.c b/drivers/phy/ti/phy-am654-serdes.c |
| index d3769200cb9b..3b9eb639a740 100644 |
| --- a/drivers/phy/ti/phy-am654-serdes.c |
| +++ b/drivers/phy/ti/phy-am654-serdes.c |
| @@ -405,6 +405,7 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy, |
| const __be32 *addr; |
| unsigned int reg; |
| struct clk *clk; |
| + int ret = 0; |
| |
| mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); |
| if (!mux) |
| @@ -413,34 +414,40 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy, |
| init = &mux->clk_data; |
| |
| regmap_node = of_parse_phandle(node, "ti,serdes-clk", 0); |
| - of_node_put(regmap_node); |
| if (!regmap_node) { |
| dev_err(dev, "Fail to get serdes-clk node\n"); |
| - return -ENODEV; |
| + ret = -ENODEV; |
| + goto out_put_node; |
| } |
| |
| regmap = syscon_node_to_regmap(regmap_node->parent); |
| if (IS_ERR(regmap)) { |
| dev_err(dev, "Fail to get Syscon regmap\n"); |
| - return PTR_ERR(regmap); |
| + ret = PTR_ERR(regmap); |
| + goto out_put_node; |
| } |
| |
| num_parents = of_clk_get_parent_count(node); |
| if (num_parents < 2) { |
| dev_err(dev, "SERDES clock must have parents\n"); |
| - return -EINVAL; |
| + ret = -EINVAL; |
| + goto out_put_node; |
| } |
| |
| parent_names = devm_kzalloc(dev, (sizeof(char *) * num_parents), |
| GFP_KERNEL); |
| - if (!parent_names) |
| - return -ENOMEM; |
| + if (!parent_names) { |
| + ret = -ENOMEM; |
| + goto out_put_node; |
| + } |
| |
| of_clk_parent_fill(node, parent_names, num_parents); |
| |
| addr = of_get_address(regmap_node, 0, NULL, NULL); |
| - if (!addr) |
| - return -EINVAL; |
| + if (!addr) { |
| + ret = -EINVAL; |
| + goto out_put_node; |
| + } |
| |
| reg = be32_to_cpu(*addr); |
| |
| @@ -456,12 +463,16 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy, |
| mux->hw.init = init; |
| |
| clk = devm_clk_register(dev, &mux->hw); |
| - if (IS_ERR(clk)) |
| - return PTR_ERR(clk); |
| + if (IS_ERR(clk)) { |
| + ret = PTR_ERR(clk); |
| + goto out_put_node; |
| + } |
| |
| am654_phy->clks[clock_num] = clk; |
| |
| - return 0; |
| +out_put_node: |
| + of_node_put(regmap_node); |
| + return ret; |
| } |
| |
| static const struct of_device_id serdes_am654_id_table[] = { |
| -- |
| 2.27.0 |
| |