On 15/12/16 20:40, Shuah Khan wrote:
Using devm resources that have external dependencies such as a dev
for a file handler could result in devm resources getting released
durin unbind while an application has the file open holding pointer
to the devm resource. This results in use-after-free errors when the
application exits.

That's solving the wrong problem.

The real problem is that when registering a video_device it should do
this:

devnode->cdev.kobj.parent = &devnode->dev.kobj;

(taken from cec-core.c)

This will prevent isp->dev from being released as long as there is a
filehandle still open.

After that change I believe that this will work correctly, but this
has to be tested first!

Regards,

        Hans


Signed-off-by: Shuah Khan <shua...@osg.samsung.com>
---
 drivers/media/platform/omap3isp/isp.c         | 71 +++++++++++++++++++--------
 drivers/media/platform/omap3isp/ispccp2.c     | 10 +++-
 drivers/media/platform/omap3isp/isph3a_aewb.c | 21 +++++---
 drivers/media/platform/omap3isp/isph3a_af.c   | 21 +++++---
 drivers/media/platform/omap3isp/isphist.c     |  5 +-
 5 files changed, 92 insertions(+), 36 deletions(-)

diff --git a/drivers/media/platform/omap3isp/isp.c 
b/drivers/media/platform/omap3isp/isp.c
index 0321d84..a11c509 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -1374,7 +1374,7 @@ static int isp_get_clocks(struct isp_device *isp)
        unsigned int i;

        for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) {
-               clk = devm_clk_get(isp->dev, isp_clocks[i]);
+               clk = clk_get(isp->dev, isp_clocks[i]);
                if (IS_ERR(clk)) {
                        dev_err(isp->dev, "clk_get %s failed\n", isp_clocks[i]);
                        return PTR_ERR(clk);
@@ -1386,6 +1386,14 @@ static int isp_get_clocks(struct isp_device *isp)
        return 0;
 }

+static void isp_put_clocks(struct isp_device *isp)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i)
+               clk_put(isp->clock[i]);
+}
+
 /*
  * omap3isp_get - Acquire the ISP resource.
  *
@@ -2015,6 +2023,11 @@ static int isp_remove(struct platform_device *pdev)

        media_entity_enum_cleanup(&isp->crashed);

+       regulator_put(isp->isp_csiphy2.vdd);
+       regulator_put(isp->isp_csiphy1.vdd);
+
+       isp_put_clocks(isp);
+       kfree(isp);
        return 0;
 }

@@ -2107,8 +2120,8 @@ static int isp_of_parse_nodes(struct device *dev,
 {
        struct device_node *node = NULL;

-       notifier->subdevs = devm_kcalloc(
-               dev, ISP_MAX_SUBDEVS, sizeof(*notifier->subdevs), GFP_KERNEL);
+       notifier->subdevs = kcalloc(
+               ISP_MAX_SUBDEVS, sizeof(*notifier->subdevs), GFP_KERNEL);
        if (!notifier->subdevs)
                return -ENOMEM;

@@ -2116,11 +2129,9 @@ static int isp_of_parse_nodes(struct device *dev,
               (node = of_graph_get_next_endpoint(dev->of_node, node))) {
                struct isp_async_subdev *isd;

-               isd = devm_kzalloc(dev, sizeof(*isd), GFP_KERNEL);
-               if (!isd) {
-                       of_node_put(node);
+               isd = kzalloc(sizeof(*isd), GFP_KERNEL);
+               if (!isd)
                        return -ENOMEM;
-               }

                notifier->subdevs[notifier->num_subdevs] = &isd->asd;

@@ -2204,7 +2215,7 @@ static int isp_probe(struct platform_device *pdev)
        int ret;
        int i, m;

-       isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL);
+       isp = kzalloc(sizeof(*isp), GFP_KERNEL);
        if (!isp) {
                dev_err(&pdev->dev, "could not allocate memory\n");
                return -ENOMEM;
@@ -2213,21 +2224,23 @@ static int isp_probe(struct platform_device *pdev)
        ret = of_property_read_u32(pdev->dev.of_node, "ti,phy-type",
                                   &isp->phy_type);
        if (ret)
-               return ret;
+               goto error_release_isp;

        isp->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
                                                      "syscon");
-       if (IS_ERR(isp->syscon))
-               return PTR_ERR(isp->syscon);
+       if (IS_ERR(isp->syscon)) {
+               ret = PTR_ERR(isp->syscon);
+               goto error_release_isp;
+       }

        ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 1,
                                         &isp->syscon_offset);
        if (ret)
-               return ret;
+               goto error_release_isp;

        ret = isp_of_parse_nodes(&pdev->dev, &isp->notifier);
        if (ret < 0)
-               return ret;
+               goto error_release_isp;

        isp->autoidle = autoidle;

@@ -2244,8 +2257,18 @@ static int isp_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, isp);

        /* Regulators */
-       isp->isp_csiphy1.vdd = devm_regulator_get(&pdev->dev, "vdd-csiphy1");
-       isp->isp_csiphy2.vdd = devm_regulator_get(&pdev->dev, "vdd-csiphy2");
+       isp->isp_csiphy1.vdd = regulator_get(&pdev->dev, "vdd-csiphy1");
+       if (IS_ERR(isp->isp_csiphy1.vdd)) {
+               ret = PTR_ERR(isp->isp_csiphy1.vdd);
+               isp->isp_csiphy1.vdd = NULL;
+               goto error;
+       }
+       isp->isp_csiphy2.vdd = regulator_get(&pdev->dev, "vdd-csiphy2");
+       if (IS_ERR(isp->isp_csiphy2.vdd)) {
+               ret = PTR_ERR(isp->isp_csiphy2.vdd);
+               isp->isp_csiphy2.vdd = NULL;
+               goto error_put_vdd_csiphy1;
+       }

        /* Clocks
         *
@@ -2264,16 +2287,17 @@ static int isp_probe(struct platform_device *pdev)
                isp->mmio_base[map_idx] =
                        devm_ioremap_resource(isp->dev, mem);
                if (IS_ERR(isp->mmio_base[map_idx]))
-                       return PTR_ERR(isp->mmio_base[map_idx]);
+                       ret = PTR_ERR(isp->mmio_base[map_idx]);
+                       goto error_put_vdd_csiphy2;
        }

        ret = isp_get_clocks(isp);
        if (ret < 0)
-               goto error;
+               goto error_put_vdd_csiphy2;

        ret = clk_enable(isp->clock[ISP_CLK_CAM_ICK]);
        if (ret < 0)
-               goto error;
+               goto error_put_vdd_csiphy2;

        isp->revision = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
        dev_info(isp->dev, "Revision %d.%d found\n",
@@ -2283,7 +2307,7 @@ static int isp_probe(struct platform_device *pdev)

        if (__omap3isp_get(isp, false) == NULL) {
                ret = -ENODEV;
-               goto error;
+               goto error_put_vdd_csiphy2;
        }

        ret = isp_reset(isp);
@@ -2334,7 +2358,7 @@ static int isp_probe(struct platform_device *pdev)
        }
        isp->irq_num = ret;

-       if (devm_request_irq(isp->dev, isp->irq_num, isp_isr, IRQF_SHARED,
+       if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED,
                             "OMAP3 ISP", isp)) {
                dev_err(isp->dev, "Unable to request IRQ\n");
                ret = -EINVAL;
@@ -2375,8 +2399,15 @@ static int isp_probe(struct platform_device *pdev)
 error_isp:
        isp_xclk_cleanup(isp);
        __omap3isp_put(isp, false);
+error_put_vdd_csiphy2:
+       regulator_put(isp->isp_csiphy2.vdd);
+error_put_vdd_csiphy1:
+       regulator_put(isp->isp_csiphy1.vdd);
 error:
        mutex_destroy(&isp->isp_mutex);
+       isp_put_clocks(isp);
+error_release_isp:
+       kfree(isp);

        return ret;
 }
diff --git a/drivers/media/platform/omap3isp/ispccp2.c 
b/drivers/media/platform/omap3isp/ispccp2.c
index 4c1e7f0..adf4191 100644
--- a/drivers/media/platform/omap3isp/ispccp2.c
+++ b/drivers/media/platform/omap3isp/ispccp2.c
@@ -1135,7 +1135,7 @@ int omap3isp_ccp2_init(struct isp_device *isp)
         * TODO: Don't hardcode the usage of PHY1 (shared with CSI2c).
         */
        if (isp->revision == ISP_REVISION_2_0) {
-               ccp2->vdds_csib = devm_regulator_get(isp->dev, "vdds_csib");
+               ccp2->vdds_csib = regulator_get(isp->dev, "vdds_csib");
                if (IS_ERR(ccp2->vdds_csib)) {
                        dev_dbg(isp->dev,
                                "Could not get regulator vdds_csib\n");
@@ -1147,10 +1147,15 @@ int omap3isp_ccp2_init(struct isp_device *isp)

        ret = ccp2_init_entities(ccp2);
        if (ret < 0)
-               return ret;
+               goto error_put_vdds_csib;

        ccp2_reset(ccp2);
        return 0;
+
+error_put_vdds_csib:
+       regulator_put(ccp2->vdds_csib);
+
+       return ret;
 }

 /*
@@ -1162,4 +1167,5 @@ void omap3isp_ccp2_cleanup(struct isp_device *isp)
        struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;

        omap3isp_video_cleanup(&ccp2->video_in);
+       regulator_put(ccp2->vdds_csib);
 }
diff --git a/drivers/media/platform/omap3isp/isph3a_aewb.c 
b/drivers/media/platform/omap3isp/isph3a_aewb.c
index ccaf92f..042de3e 100644
--- a/drivers/media/platform/omap3isp/isph3a_aewb.c
+++ b/drivers/media/platform/omap3isp/isph3a_aewb.c
@@ -289,9 +289,10 @@ int omap3isp_h3a_aewb_init(struct isp_device *isp)
 {
        struct ispstat *aewb = &isp->isp_aewb;
        struct omap3isp_h3a_aewb_config *aewb_cfg;
-       struct omap3isp_h3a_aewb_config *aewb_recover_cfg;
+       struct omap3isp_h3a_aewb_config *aewb_recover_cfg = NULL;
+       int ret;

-       aewb_cfg = devm_kzalloc(isp->dev, sizeof(*aewb_cfg), GFP_KERNEL);
+       aewb_cfg = kzalloc(sizeof(*aewb_cfg), GFP_KERNEL);
        if (!aewb_cfg)
                return -ENOMEM;

@@ -301,12 +302,12 @@ int omap3isp_h3a_aewb_init(struct isp_device *isp)
        aewb->isp = isp;

        /* Set recover state configuration */
-       aewb_recover_cfg = devm_kzalloc(isp->dev, sizeof(*aewb_recover_cfg),
-                                       GFP_KERNEL);
+       aewb_recover_cfg = kzalloc(sizeof(*aewb_recover_cfg), GFP_KERNEL);
        if (!aewb_recover_cfg) {
                dev_err(aewb->isp->dev, "AEWB: cannot allocate memory for "
                                        "recover configuration.\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto err_release_aewb_cfg;
        }

        aewb_recover_cfg->saturation_limit = OMAP3ISP_AEWB_MAX_SATURATION_LIM;
@@ -323,13 +324,21 @@ int omap3isp_h3a_aewb_init(struct isp_device *isp)
        if (h3a_aewb_validate_params(aewb, aewb_recover_cfg)) {
                dev_err(aewb->isp->dev, "AEWB: recover configuration is "
                                        "invalid.\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_release_aewb_recover_cfg;
        }

        aewb_recover_cfg->buf_size = h3a_aewb_get_buf_size(aewb_recover_cfg);
        aewb->recover_priv = aewb_recover_cfg;

        return omap3isp_stat_init(aewb, "AEWB", &h3a_aewb_subdev_ops);
+
+err_release_aewb_recover_cfg:
+       kfree(aewb_recover_cfg);
+err_release_aewb_cfg:
+       kfree(aewb_cfg);
+
+       return ret;
 }

 /*
diff --git a/drivers/media/platform/omap3isp/isph3a_af.c 
b/drivers/media/platform/omap3isp/isph3a_af.c
index 92937f7..1919cb2 100644
--- a/drivers/media/platform/omap3isp/isph3a_af.c
+++ b/drivers/media/platform/omap3isp/isph3a_af.c
@@ -352,9 +352,10 @@ int omap3isp_h3a_af_init(struct isp_device *isp)
 {
        struct ispstat *af = &isp->isp_af;
        struct omap3isp_h3a_af_config *af_cfg;
-       struct omap3isp_h3a_af_config *af_recover_cfg;
+       struct omap3isp_h3a_af_config *af_recover_cfg = NULL;
+       int ret;

-       af_cfg = devm_kzalloc(isp->dev, sizeof(*af_cfg), GFP_KERNEL);
+       af_cfg = kzalloc(sizeof(*af_cfg), GFP_KERNEL);
        if (af_cfg == NULL)
                return -ENOMEM;

@@ -364,12 +365,12 @@ int omap3isp_h3a_af_init(struct isp_device *isp)
        af->isp = isp;

        /* Set recover state configuration */
-       af_recover_cfg = devm_kzalloc(isp->dev, sizeof(*af_recover_cfg),
-                                     GFP_KERNEL);
+       af_recover_cfg = kzalloc(sizeof(*af_recover_cfg), GFP_KERNEL);
        if (!af_recover_cfg) {
                dev_err(af->isp->dev, "AF: cannot allocate memory for recover "
                                      "configuration.\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto err_release_af_cfg;
        }

        af_recover_cfg->paxel.h_start = OMAP3ISP_AF_PAXEL_HZSTART_MIN;
@@ -381,13 +382,21 @@ int omap3isp_h3a_af_init(struct isp_device *isp)
        if (h3a_af_validate_params(af, af_recover_cfg)) {
                dev_err(af->isp->dev, "AF: recover configuration is "
                                      "invalid.\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_release_af_recover_cfg;
        }

        af_recover_cfg->buf_size = h3a_af_get_buf_size(af_recover_cfg);
        af->recover_priv = af_recover_cfg;

        return omap3isp_stat_init(af, "AF", &h3a_af_subdev_ops);
+
+err_release_af_recover_cfg:
+       kfree(af_recover_cfg);
+err_release_af_cfg:
+       kfree(af_cfg);
+
+       return ret;
 }

 void omap3isp_h3a_af_cleanup(struct isp_device *isp)
diff --git a/drivers/media/platform/omap3isp/isphist.c 
b/drivers/media/platform/omap3isp/isphist.c
index 7138b04..5d8f04b 100644
--- a/drivers/media/platform/omap3isp/isphist.c
+++ b/drivers/media/platform/omap3isp/isphist.c
@@ -477,9 +477,9 @@ int omap3isp_hist_init(struct isp_device *isp)
 {
        struct ispstat *hist = &isp->isp_hist;
        struct omap3isp_hist_config *hist_cfg;
-       int ret = -1;
+       int ret = 0;

-       hist_cfg = devm_kzalloc(isp->dev, sizeof(*hist_cfg), GFP_KERNEL);
+       hist_cfg = kzalloc(sizeof(*hist_cfg), GFP_KERNEL);
        if (hist_cfg == NULL)
                return -ENOMEM;

@@ -517,6 +517,7 @@ int omap3isp_hist_init(struct isp_device *isp)
        if (ret) {
                if (hist->dma_ch)
                        dma_release_channel(hist->dma_ch);
+               kfree(hist_cfg);
        }

        return ret;


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to