Message ID | 20220414061410.7678-1-xiam0nd.tong@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [RESEND] omapdrm: fix missing check on list iterator | expand |
Hi, On 14/04/2022 09:14, Xiaomeng Tong wrote: > The bug is here: > bus_flags = connector->display_info.bus_flags; > > The list iterator 'connector-' will point to a bogus position containing > HEAD if the list is empty or no element is found. This case must > be checked before any use of the iterator, otherwise it will lead > to a invalid memory access. > > To fix this bug, add an check. Use a new value 'iter' as the list > iterator, while use the old value 'connector' as a dedicated variable > to point to the found element. > > Cc: stable@vger.kernel.org > Fixes: ("drm/omap: Add support for drm_panel") > Signed-off-by: Xiaomeng Tong <xiam0nd.tong@gmail.com> > --- > drivers/gpu/drm/omapdrm/omap_encoder.c | 14 +++++++++----- > 1 file changed, 9 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c > index 4dd05bc732da..d648ab4223b1 100644 > --- a/drivers/gpu/drm/omapdrm/omap_encoder.c > +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c > @@ -76,14 +76,16 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, > struct omap_encoder *omap_encoder = to_omap_encoder(encoder); > struct omap_dss_device *output = omap_encoder->output; > struct drm_device *dev = encoder->dev; > - struct drm_connector *connector; > + struct drm_connector *connector = NULL, *iter; > struct drm_bridge *bridge; > struct videomode vm = { 0 }; > u32 bus_flags; > > - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { > - if (connector->encoder == encoder) > + list_for_each_entry(iter, &dev->mode_config.connector_list, head) { > + if (iter->encoder == encoder) { > + connector = iter; > break; > + } > } When does this bug happen? How do you get omap_encoder_mode_set() called for an encoder with a connector that is not valid? > > drm_display_mode_to_videomode(adjusted_mode, &vm); > @@ -106,8 +108,10 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, > omap_encoder_update_videomode_flags(&vm, bus_flags); > } > > - bus_flags = connector->display_info.bus_flags; > - omap_encoder_update_videomode_flags(&vm, bus_flags); > + if (connector) { > + bus_flags = connector->display_info.bus_flags; > + omap_encoder_update_videomode_flags(&vm, bus_flags); > + } > > /* Set timings for all devices in the display pipeline. */ > dss_mgr_set_timings(output, &vm); How does this fix the issue? You just skip the lines that set up the videomode, but then pass that videomode to dss_mgr_set_timings()... Tomi
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c index 4dd05bc732da..d648ab4223b1 100644 --- a/drivers/gpu/drm/omapdrm/omap_encoder.c +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c @@ -76,14 +76,16 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, struct omap_encoder *omap_encoder = to_omap_encoder(encoder); struct omap_dss_device *output = omap_encoder->output; struct drm_device *dev = encoder->dev; - struct drm_connector *connector; + struct drm_connector *connector = NULL, *iter; struct drm_bridge *bridge; struct videomode vm = { 0 }; u32 bus_flags; - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) + list_for_each_entry(iter, &dev->mode_config.connector_list, head) { + if (iter->encoder == encoder) { + connector = iter; break; + } } drm_display_mode_to_videomode(adjusted_mode, &vm); @@ -106,8 +108,10 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, omap_encoder_update_videomode_flags(&vm, bus_flags); } - bus_flags = connector->display_info.bus_flags; - omap_encoder_update_videomode_flags(&vm, bus_flags); + if (connector) { + bus_flags = connector->display_info.bus_flags; + omap_encoder_update_videomode_flags(&vm, bus_flags); + } /* Set timings for all devices in the display pipeline. */ dss_mgr_set_timings(output, &vm);
The bug is here: bus_flags = connector->display_info.bus_flags; The list iterator 'connector-' will point to a bogus position containing HEAD if the list is empty or no element is found. This case must be checked before any use of the iterator, otherwise it will lead to a invalid memory access. To fix this bug, add an check. Use a new value 'iter' as the list iterator, while use the old value 'connector' as a dedicated variable to point to the found element. Cc: stable@vger.kernel.org Fixes: ("drm/omap: Add support for drm_panel") Signed-off-by: Xiaomeng Tong <xiam0nd.tong@gmail.com> --- drivers/gpu/drm/omapdrm/omap_encoder.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)