linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Fix for drm_mode_config_cleanup issue
       [not found] <0687f68004b28ed3a364b06a9eb64e2e@agner.ch>
@ 2019-04-02 13:49 ` Michael Grzeschik
  2019-04-02 13:49   ` [PATCH 1/3] ipuv3-crtc: add remove action for devres data Michael Grzeschik
                     ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Michael Grzeschik @ 2019-04-02 13:49 UTC (permalink / raw)
  To: p.zabel, airlied, gregkh; +Cc: linux-kernel, linux, dri-devel, rafael, kernel

Fix the issue: "drm/imx: Crash in drm_mode_config_cleanup".

Which was documented here:

https://www.spinics.net/lists/dri-devel/msg189388.html

And tried to address with this:

https://patchwork.kernel.org/patch/10633297/
https://patchwork.kernel.org/patch/10633299/

This series fixes the possible case of use after free by adding action
functions to the devres cleanup path. So it will ensure the generic
cleanup code will not use the already freed memory.


Michael Grzeschik (3):
  ipuv3-crtc: add remove action for devres data
  ipuv3-ldb: add init list head on bind
  ipuv3-ldb: add remove action for devres data

 drivers/gpu/drm/imx/imx-ldb.c    | 35 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/imx/ipuv3-crtc.c | 12 +++++++++++
 2 files changed, 47 insertions(+)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] ipuv3-crtc: add remove action for devres data
  2019-04-02 13:49 ` [PATCH 0/3] Fix for drm_mode_config_cleanup issue Michael Grzeschik
@ 2019-04-02 13:49   ` Michael Grzeschik
  2019-04-02 15:49     ` Philipp Zabel
  2019-04-02 13:49   ` [PATCH 2/3] ipuv3-ldb: add init list head on bind Michael Grzeschik
  2019-04-02 13:49   ` [PATCH 3/3] ipuv3-ldb: add remove action for devres data Michael Grzeschik
  2 siblings, 1 reply; 6+ messages in thread
From: Michael Grzeschik @ 2019-04-02 13:49 UTC (permalink / raw)
  To: p.zabel, airlied, gregkh; +Cc: linux-kernel, linux, dri-devel, rafael, kernel

The destroy function in drm_mode_config_cleanup will remove the objects
in ipu-drm-core by calling its destroy functions if the bind function
fails. The drm_crtc is also part of the devres allocated ipu_crtc
object. The ipu_crtc object will already be cleaned up if the bind for
the crtc fails. This leads drm_crtc_cleanup try to clean already freed
memory.

We fix this issue by adding the devres action ipu_crtc_remove_head which
will remove its head from the objects in ipu-drm-core which then never
calls its destroy function anymore.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 drivers/gpu/drm/imx/ipuv3-crtc.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
index ec3602ebbc1cd..fa1ee33a43d77 100644
--- a/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -429,6 +429,14 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
 	return ret;
 }
 
+static void ipu_crtc_remove_head(void *data)
+{
+	struct ipu_crtc *ipu_crtc = data;
+	struct drm_crtc *crtc = &ipu_crtc->base;
+
+	list_del(&crtc->head);
+}
+
 static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
 {
 	struct ipu_client_platformdata *pdata = dev->platform_data;
@@ -440,6 +448,10 @@ static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
 	if (!ipu_crtc)
 		return -ENOMEM;
 
+	ret = devm_add_action(dev, ipu_crtc_remove_head, ipu_crtc);
+	if (ret)
+		return ret;
+
 	ipu_crtc->dev = dev;
 
 	ret = ipu_crtc_init(ipu_crtc, pdata, drm);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] ipuv3-ldb: add init list head on bind
  2019-04-02 13:49 ` [PATCH 0/3] Fix for drm_mode_config_cleanup issue Michael Grzeschik
  2019-04-02 13:49   ` [PATCH 1/3] ipuv3-crtc: add remove action for devres data Michael Grzeschik
@ 2019-04-02 13:49   ` Michael Grzeschik
  2019-04-02 13:49   ` [PATCH 3/3] ipuv3-ldb: add remove action for devres data Michael Grzeschik
  2 siblings, 0 replies; 6+ messages in thread
From: Michael Grzeschik @ 2019-04-02 13:49 UTC (permalink / raw)
  To: p.zabel, airlied, gregkh; +Cc: linux-kernel, linux, dri-devel, rafael, kernel

The list head is not initialised after imx_ldb_bind
allocates the imx_ldb object. Ensure it will be valid
before anyone uses it.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 drivers/gpu/drm/imx/imx-ldb.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 3837333022804..a11f8758da70e 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -581,6 +581,20 @@ static int imx_ldb_panel_ddc(struct device *dev,
 	return 0;
 }
 
+static void ipu_ldb_init_encoder_head(struct imx_ldb *imx_ldb)
+{
+	struct imx_ldb_channel *imx_ldb_ch;
+	struct drm_encoder *encoder;
+
+	imx_ldb_ch = &imx_ldb->channel[0];
+	encoder = &imx_ldb_ch->encoder;
+	INIT_LIST_HEAD(&encoder->head);
+
+	imx_ldb_ch = &imx_ldb->channel[1];
+	encoder = &imx_ldb_ch->encoder;
+	INIT_LIST_HEAD(&encoder->head);
+}
+
 static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 {
 	struct drm_device *drm = data;
@@ -597,6 +611,8 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 	if (!imx_ldb)
 		return -ENOMEM;
 
+	ipu_ldb_init_encoder_head(imx_ldb);
+
 	imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
 	if (IS_ERR(imx_ldb->regmap)) {
 		dev_err(dev, "failed to get parent regmap\n");
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] ipuv3-ldb: add remove action for devres data
  2019-04-02 13:49 ` [PATCH 0/3] Fix for drm_mode_config_cleanup issue Michael Grzeschik
  2019-04-02 13:49   ` [PATCH 1/3] ipuv3-crtc: add remove action for devres data Michael Grzeschik
  2019-04-02 13:49   ` [PATCH 2/3] ipuv3-ldb: add init list head on bind Michael Grzeschik
@ 2019-04-02 13:49   ` Michael Grzeschik
  2 siblings, 0 replies; 6+ messages in thread
From: Michael Grzeschik @ 2019-04-02 13:49 UTC (permalink / raw)
  To: p.zabel, airlied, gregkh; +Cc: linux-kernel, linux, dri-devel, rafael, kernel

The destroy function in drm_mode_config_cleanup will remove the objects
in ipu-drm-core by calling its destroy functions if the bind function
fails. The drm_encoder is also part of the devres allocated ipu_ldb
object. The ipu_ldb object will already be cleaned up if the bind for
the crtc fails. This leads drm_encoder_cleanup try to clean already freed
memory.

We fix this issue by adding the devres action ipu_ldb_remove_head which
will remove its head from the objects in ipu-drm-core which then never
calls its destroy function anymore.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 drivers/gpu/drm/imx/imx-ldb.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index a11f8758da70e..0a224036cc68d 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -581,6 +581,21 @@ static int imx_ldb_panel_ddc(struct device *dev,
 	return 0;
 }
 
+static void ipu_ldb_remove_head(void *data)
+{
+	struct imx_ldb *imx_ldb = data;
+	struct imx_ldb_channel *imx_ldb_ch;
+	struct drm_encoder *encoder;
+
+	imx_ldb_ch = &imx_ldb->channel[0];
+	encoder = &imx_ldb_ch->encoder;
+	list_del_init(&encoder->head);
+
+	imx_ldb_ch = &imx_ldb->channel[1];
+	encoder = &imx_ldb_ch->encoder;
+	list_del_init(&encoder->head);
+}
+
 static void ipu_ldb_init_encoder_head(struct imx_ldb *imx_ldb)
 {
 	struct imx_ldb_channel *imx_ldb_ch;
@@ -613,6 +628,10 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 
 	ipu_ldb_init_encoder_head(imx_ldb);
 
+	ret = devm_add_action(dev, ipu_ldb_remove_head, imx_ldb);
+	if (ret)
+		return ret;
+
 	imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
 	if (IS_ERR(imx_ldb->regmap)) {
 		dev_err(dev, "failed to get parent regmap\n");
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] ipuv3-crtc: add remove action for devres data
  2019-04-02 13:49   ` [PATCH 1/3] ipuv3-crtc: add remove action for devres data Michael Grzeschik
@ 2019-04-02 15:49     ` Philipp Zabel
  2019-04-03  7:22       ` Daniel Vetter
  0 siblings, 1 reply; 6+ messages in thread
From: Philipp Zabel @ 2019-04-02 15:49 UTC (permalink / raw)
  To: Michael Grzeschik, airlied, gregkh
  Cc: linux-kernel, linux, dri-devel, rafael, kernel

Hi Michael,

On Tue, 2019-04-02 at 15:49 +0200, Michael Grzeschik wrote:
> The destroy function in drm_mode_config_cleanup will remove the objects
> in ipu-drm-core by calling its destroy functions if the bind function
> fails. The drm_crtc is also part of the devres allocated ipu_crtc
> object. The ipu_crtc object will already be cleaned up if the bind for
> the crtc fails. This leads drm_crtc_cleanup try to clean already freed
> memory.
> 
> We fix this issue by adding the devres action ipu_crtc_remove_head which
> will remove its head from the objects in ipu-drm-core which then never
> calls its destroy function anymore.
> 
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> ---
>  drivers/gpu/drm/imx/ipuv3-crtc.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
> index ec3602ebbc1cd..fa1ee33a43d77 100644
> --- a/drivers/gpu/drm/imx/ipuv3-crtc.c
> +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
> @@ -429,6 +429,14 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
>  	return ret;
>  }
>  
> +static void ipu_crtc_remove_head(void *data)
> +{
> +	struct ipu_crtc *ipu_crtc = data;
> +	struct drm_crtc *crtc = &ipu_crtc->base;
> +
> +	list_del(&crtc->head);

I don't think reaching into drm_crtc internals like this is going to be
robust. Currently, this is either missing the rest of drm_crtc_cleanup,
or it will crash if drm_crtc_init_with_planes hasn't been called yet.

I think you could call devm_add_action with a function that calls
drm_crtc_cleanup after drm_crtc_init_with_planes in ipu_crtc_init.

Alternatively, the ipu_crtc allocation could be changed to kzalloc. It
would then have to freed manually in the drm_crtc_funcs->destroy
callback.

regards
Philipp

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] ipuv3-crtc: add remove action for devres data
  2019-04-02 15:49     ` Philipp Zabel
@ 2019-04-03  7:22       ` Daniel Vetter
  0 siblings, 0 replies; 6+ messages in thread
From: Daniel Vetter @ 2019-04-03  7:22 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: Michael Grzeschik, airlied, gregkh, kernel, rafael, linux-kernel,
	dri-devel, linux

On Tue, Apr 02, 2019 at 05:49:23PM +0200, Philipp Zabel wrote:
> Hi Michael,
> 
> On Tue, 2019-04-02 at 15:49 +0200, Michael Grzeschik wrote:
> > The destroy function in drm_mode_config_cleanup will remove the objects
> > in ipu-drm-core by calling its destroy functions if the bind function
> > fails. The drm_crtc is also part of the devres allocated ipu_crtc
> > object. The ipu_crtc object will already be cleaned up if the bind for
> > the crtc fails. This leads drm_crtc_cleanup try to clean already freed
> > memory.
> > 
> > We fix this issue by adding the devres action ipu_crtc_remove_head which
> > will remove its head from the objects in ipu-drm-core which then never
> > calls its destroy function anymore.
> > 
> > Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> > ---
> >  drivers/gpu/drm/imx/ipuv3-crtc.c | 12 ++++++++++++
> >  1 file changed, 12 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
> > index ec3602ebbc1cd..fa1ee33a43d77 100644
> > --- a/drivers/gpu/drm/imx/ipuv3-crtc.c
> > +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
> > @@ -429,6 +429,14 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
> >  	return ret;
> >  }
> >  
> > +static void ipu_crtc_remove_head(void *data)
> > +{
> > +	struct ipu_crtc *ipu_crtc = data;
> > +	struct drm_crtc *crtc = &ipu_crtc->base;
> > +
> > +	list_del(&crtc->head);
> 
> I don't think reaching into drm_crtc internals like this is going to be
> robust. Currently, this is either missing the rest of drm_crtc_cleanup,
> or it will crash if drm_crtc_init_with_planes hasn't been called yet.
> 
> I think you could call devm_add_action with a function that calls
> drm_crtc_cleanup after drm_crtc_init_with_planes in ipu_crtc_init.
> 
> Alternatively, the ipu_crtc allocation could be changed to kzalloc. It
> would then have to freed manually in the drm_crtc_funcs->destroy
> callback.

Dirty secret of devm: You can't use it for any drm_ structure, because the
lifetimes of those do not match the lifetimes of the underlying device.
We'd need to tie the lifetimes of drm objects to drm_device. Noralf has
some patches to move that forward. We'd need something like
drm_dev_kzalloc which releases memory when drm_device is freed.

Agreed that digging even deeper into the devm deadend is not a good idea.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-04-03  7:22 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <0687f68004b28ed3a364b06a9eb64e2e@agner.ch>
2019-04-02 13:49 ` [PATCH 0/3] Fix for drm_mode_config_cleanup issue Michael Grzeschik
2019-04-02 13:49   ` [PATCH 1/3] ipuv3-crtc: add remove action for devres data Michael Grzeschik
2019-04-02 15:49     ` Philipp Zabel
2019-04-03  7:22       ` Daniel Vetter
2019-04-02 13:49   ` [PATCH 2/3] ipuv3-ldb: add init list head on bind Michael Grzeschik
2019-04-02 13:49   ` [PATCH 3/3] ipuv3-ldb: add remove action for devres data Michael Grzeschik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).