Message ID | 20211112002706.453289-5-marijn.suijten@somainline.org (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | backlight: qcom-wled: fix and solidify handling of enabled-strings | expand |
On Fri, Nov 12, 2021 at 01:26:57AM +0100, Marijn Suijten wrote: > When not specifying num-strings in the DT the default is used, but +1 is > added to it which turns WLED3 into 4 and WLED4/5 into 5 strings instead > of 3 and 4 respectively, causing out-of-bounds reads and register > read/writes. This +1 exists for a deficiency in the DT parsing code, > and is simply omitted entirely - solving this oob issue - by parsing the > property separately much like qcom,enabled-strings. > > This also allows more stringent checks on the maximum value when > qcom,enabled-strings is provided in the DT. Note that num-strings is > parsed after enabled-strings to give it final sign-off over the length, > which DT currently utilizes to get around an incorrect fixed read of > four elements from that array (has been addressed in a prior patch). > > Fixes: 93c64f1ea1e8 ("leds: add Qualcomm PM8941 WLED driver") > Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org> > Reviewed-By: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org> > --- > drivers/video/backlight/qcom-wled.c | 51 +++++++++++------------------ > 1 file changed, 19 insertions(+), 32 deletions(-) > > diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c > index 977cd75827d7..c5232478a343 100644 > --- a/drivers/video/backlight/qcom-wled.c > +++ b/drivers/video/backlight/qcom-wled.c > @@ -1552,6 +1520,25 @@ static int wled_configure(struct wled *wled) > } > } > > + rc = of_property_read_u32(dev->of_node, "qcom,num-strings", &val); > + if (!rc) { > + if (val < 1 || val > wled->max_string_count) { > + dev_err(dev, "qcom,num-strings must be between 1 and %d\n", > + wled->max_string_count); > + return -EINVAL; > + } > + > + if (string_len > 0) { > + dev_warn(dev, "qcom,num-strings and qcom,enabled-strings are ambiguous\n"); This warning occurs even when there is no ambiguity. This could be: if (string_len > 0 && val != string_len) The warning should also be below the error message on the next if statement. Combined these changes allows us to give a much more helpful and assertive warning message: qcom,num-strings mis-matches and will partially override qcom,enabled-strings (remove qcom,num-strings?) > + if (val > string_len) { > + dev_err(dev, "qcom,num-strings exceeds qcom,enabled-strings\n"); > + return -EINVAL; > + } > + } Daniel.
On 2021-11-12 12:08:39, Daniel Thompson wrote: > On Fri, Nov 12, 2021 at 01:26:57AM +0100, Marijn Suijten wrote: > > When not specifying num-strings in the DT the default is used, but +1 is > > added to it which turns WLED3 into 4 and WLED4/5 into 5 strings instead > > of 3 and 4 respectively, causing out-of-bounds reads and register > > read/writes. This +1 exists for a deficiency in the DT parsing code, > > and is simply omitted entirely - solving this oob issue - by parsing the > > property separately much like qcom,enabled-strings. > > > > This also allows more stringent checks on the maximum value when > > qcom,enabled-strings is provided in the DT. Note that num-strings is > > parsed after enabled-strings to give it final sign-off over the length, > > which DT currently utilizes to get around an incorrect fixed read of > > four elements from that array (has been addressed in a prior patch). > > > > Fixes: 93c64f1ea1e8 ("leds: add Qualcomm PM8941 WLED driver") > > Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org> > > Reviewed-By: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org> > > --- > > drivers/video/backlight/qcom-wled.c | 51 +++++++++++------------------ > > 1 file changed, 19 insertions(+), 32 deletions(-) > > > > diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c > > index 977cd75827d7..c5232478a343 100644 > > --- a/drivers/video/backlight/qcom-wled.c > > +++ b/drivers/video/backlight/qcom-wled.c > > @@ -1552,6 +1520,25 @@ static int wled_configure(struct wled *wled) > > } > > } > > > > + rc = of_property_read_u32(dev->of_node, "qcom,num-strings", &val); > > + if (!rc) { > > + if (val < 1 || val > wled->max_string_count) { > > + dev_err(dev, "qcom,num-strings must be between 1 and %d\n", > > + wled->max_string_count); > > + return -EINVAL; > > + } > > + > > + if (string_len > 0) { > > + dev_warn(dev, "qcom,num-strings and qcom,enabled-strings are ambiguous\n"); > > The warning should also be below the error message on the next if statement. Agreed. > This warning occurs even when there is no ambiguity. > > This could be: > > if (string_len > 0 && val != string_len) > > Combined these changes allows us to give a much more helpful and assertive > warning message: > > qcom,num-strings mis-matches and will partially override > qcom,enabled-strings (remove qcom,num-strings?) I want to let the user know it's set regardless of whether they're equivalent; no need to set both. How about: Only one of qcom,num-strings or qcom,enabled-strings should be set That should be more descriptive? Otherwise, let me know if you really want to allow users to (unnecessarily) set both - or if it can / should be caught in DT validation instead. - Marijn > > + if (val > string_len) { > > + dev_err(dev, "qcom,num-strings exceeds qcom,enabled-strings\n"); > > + return -EINVAL; > > + } > > + } > > > Daniel.
On Fri, Nov 12, 2021 at 01:35:01PM +0100, Marijn Suijten wrote: > On 2021-11-12 12:08:39, Daniel Thompson wrote: > > On Fri, Nov 12, 2021 at 01:26:57AM +0100, Marijn Suijten wrote: > > > + if (string_len > 0) { > > > + dev_warn(dev, "qcom,num-strings and qcom,enabled-strings are ambiguous\n"); > > > > The warning should also be below the error message on the next if statement. > > Agreed. > > > This warning occurs even when there is no ambiguity. > > > > This could be: > > > > if (string_len > 0 && val != string_len) > > > > Combined these changes allows us to give a much more helpful and assertive > > warning message: > > > > qcom,num-strings mis-matches and will partially override > > qcom,enabled-strings (remove qcom,num-strings?) > > I want to let the user know it's set regardless of whether they're > equivalent; no need to set both. > > How about: > > Only one of qcom,num-strings or qcom,enabled-strings should be set > > That should be more descriptive? Otherwise, let me know if you really > want to allow users to (unnecessarily) set both - or if it can / should > be caught in DT validation instead. Yes. I can live with that text. Let's use that. Maybe I wouldn't if there gazilions of existing DTs with both properties but IIRC the number is likely to be small or zero (although we couldn't be 100% sure which). Daniel.
On 2021-11-12 13:35:03, Marijn Suijten wrote: > On 2021-11-12 12:08:39, Daniel Thompson wrote: > > On Fri, Nov 12, 2021 at 01:26:57AM +0100, Marijn Suijten wrote: > > > When not specifying num-strings in the DT the default is used, but +1 is > > > added to it which turns WLED3 into 4 and WLED4/5 into 5 strings instead > > > of 3 and 4 respectively, causing out-of-bounds reads and register > > > read/writes. This +1 exists for a deficiency in the DT parsing code, > > > and is simply omitted entirely - solving this oob issue - by parsing the > > > property separately much like qcom,enabled-strings. > > > > > > This also allows more stringent checks on the maximum value when > > > qcom,enabled-strings is provided in the DT. Note that num-strings is > > > parsed after enabled-strings to give it final sign-off over the length, > > > which DT currently utilizes to get around an incorrect fixed read of > > > four elements from that array (has been addressed in a prior patch). > > > > > > Fixes: 93c64f1ea1e8 ("leds: add Qualcomm PM8941 WLED driver") > > > Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org> > > > Reviewed-By: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org> > > > --- > > > drivers/video/backlight/qcom-wled.c | 51 +++++++++++------------------ > > > 1 file changed, 19 insertions(+), 32 deletions(-) > > > > > > diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c > > > index 977cd75827d7..c5232478a343 100644 > > > --- a/drivers/video/backlight/qcom-wled.c > > > +++ b/drivers/video/backlight/qcom-wled.c > > > @@ -1552,6 +1520,25 @@ static int wled_configure(struct wled *wled) > > > } > > > } > > > > > > + rc = of_property_read_u32(dev->of_node, "qcom,num-strings", &val); > > > + if (!rc) { > > > + if (val < 1 || val > wled->max_string_count) { > > > + dev_err(dev, "qcom,num-strings must be between 1 and %d\n", > > > + wled->max_string_count); > > > + return -EINVAL; > > > + } > > > + > > > + if (string_len > 0) { > > > + dev_warn(dev, "qcom,num-strings and qcom,enabled-strings are ambiguous\n"); > > > > The warning should also be below the error message on the next if statement. > > Agreed. Thinking about this again while reworking the patches, I initially put this above the error to make DT writers aware. There's no point telling them that their values are out of sync (num-strings > len(enabled-strings)), when they "shouldn't even" (don't need to) set both in the first place. They might needlessly fix the discrepancy, see the driver finally probe (working backlight) and carry on without noticing this warning that now appears. Sorry for bringing this back up, but I'm curious about your opinion. - Marijn
On Fri, Nov 12, 2021 at 10:43:37PM +0100, Marijn Suijten wrote: > On 2021-11-12 13:35:03, Marijn Suijten wrote: > > On 2021-11-12 12:08:39, Daniel Thompson wrote: > > > On Fri, Nov 12, 2021 at 01:26:57AM +0100, Marijn Suijten wrote: > > > > When not specifying num-strings in the DT the default is used, but +1 is > > > > added to it which turns WLED3 into 4 and WLED4/5 into 5 strings instead > > > > of 3 and 4 respectively, causing out-of-bounds reads and register > > > > read/writes. This +1 exists for a deficiency in the DT parsing code, > > > > and is simply omitted entirely - solving this oob issue - by parsing the > > > > property separately much like qcom,enabled-strings. > > > > > > > > This also allows more stringent checks on the maximum value when > > > > qcom,enabled-strings is provided in the DT. Note that num-strings is > > > > parsed after enabled-strings to give it final sign-off over the length, > > > > which DT currently utilizes to get around an incorrect fixed read of > > > > four elements from that array (has been addressed in a prior patch). > > > > > > > > Fixes: 93c64f1ea1e8 ("leds: add Qualcomm PM8941 WLED driver") > > > > Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org> > > > > Reviewed-By: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org> > > > > --- > > > > drivers/video/backlight/qcom-wled.c | 51 +++++++++++------------------ > > > > 1 file changed, 19 insertions(+), 32 deletions(-) > > > > > > > > diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c > > > > index 977cd75827d7..c5232478a343 100644 > > > > --- a/drivers/video/backlight/qcom-wled.c > > > > +++ b/drivers/video/backlight/qcom-wled.c > > > > @@ -1552,6 +1520,25 @@ static int wled_configure(struct wled *wled) > > > > } > > > > } > > > > > > > > + rc = of_property_read_u32(dev->of_node, "qcom,num-strings", &val); > > > > + if (!rc) { > > > > + if (val < 1 || val > wled->max_string_count) { > > > > + dev_err(dev, "qcom,num-strings must be between 1 and %d\n", > > > > + wled->max_string_count); > > > > + return -EINVAL; > > > > + } > > > > + > > > > + if (string_len > 0) { > > > > + dev_warn(dev, "qcom,num-strings and qcom,enabled-strings are ambiguous\n"); > > > > > > The warning should also be below the error message on the next if statement. > > > > Agreed. > > Thinking about this again while reworking the patches, I initially put > this above the error to make DT writers aware. There's no point telling > them that their values are out of sync (num-strings > > len(enabled-strings)), when they "shouldn't even" (don't need to) set > both in the first place. They might needlessly fix the discrepancy, see > the driver finally probe (working backlight) and carry on without > noticing this warning that now appears. > > Sorry for bringing this back up, but I'm curious about your opinion. With a more helpful warning about how to fix then I think it is OK to have both the warning and the error. Daniel.
On 2021-11-15 11:23:27, Daniel Thompson wrote: > On Fri, Nov 12, 2021 at 10:43:37PM +0100, Marijn Suijten wrote: > > On 2021-11-12 13:35:03, Marijn Suijten wrote: > > > On 2021-11-12 12:08:39, Daniel Thompson wrote: > > > > On Fri, Nov 12, 2021 at 01:26:57AM +0100, Marijn Suijten wrote: > > > > > When not specifying num-strings in the DT the default is used, but +1 is > > > > > added to it which turns WLED3 into 4 and WLED4/5 into 5 strings instead > > > > > of 3 and 4 respectively, causing out-of-bounds reads and register > > > > > read/writes. This +1 exists for a deficiency in the DT parsing code, > > > > > and is simply omitted entirely - solving this oob issue - by parsing the > > > > > property separately much like qcom,enabled-strings. > > > > > > > > > > This also allows more stringent checks on the maximum value when > > > > > qcom,enabled-strings is provided in the DT. Note that num-strings is > > > > > parsed after enabled-strings to give it final sign-off over the length, > > > > > which DT currently utilizes to get around an incorrect fixed read of > > > > > four elements from that array (has been addressed in a prior patch). > > > > > > > > > > Fixes: 93c64f1ea1e8 ("leds: add Qualcomm PM8941 WLED driver") > > > > > Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org> > > > > > Reviewed-By: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org> > > > > > --- > > > > > drivers/video/backlight/qcom-wled.c | 51 +++++++++++------------------ > > > > > 1 file changed, 19 insertions(+), 32 deletions(-) > > > > > > > > > > diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c > > > > > index 977cd75827d7..c5232478a343 100644 > > > > > --- a/drivers/video/backlight/qcom-wled.c > > > > > +++ b/drivers/video/backlight/qcom-wled.c > > > > > @@ -1552,6 +1520,25 @@ static int wled_configure(struct wled *wled) > > > > > } > > > > > } > > > > > > > > > > + rc = of_property_read_u32(dev->of_node, "qcom,num-strings", &val); > > > > > + if (!rc) { > > > > > + if (val < 1 || val > wled->max_string_count) { > > > > > + dev_err(dev, "qcom,num-strings must be between 1 and %d\n", > > > > > + wled->max_string_count); > > > > > + return -EINVAL; > > > > > + } > > > > > + > > > > > + if (string_len > 0) { > > > > > + dev_warn(dev, "qcom,num-strings and qcom,enabled-strings are ambiguous\n"); > > > > > > > > The warning should also be below the error message on the next if statement. > > > > > > Agreed. > > > > Thinking about this again while reworking the patches, I initially put > > this above the error to make DT writers aware. There's no point telling > > them that their values are out of sync (num-strings > > > len(enabled-strings)), when they "shouldn't even" (don't need to) set > > both in the first place. They might needlessly fix the discrepancy, see > > the driver finally probe (working backlight) and carry on without > > noticing this warning that now appears. > > > > Sorry for bringing this back up, but I'm curious about your opinion. > > With a more helpful warning about how to fix then I think it is OK to > have both the warning and the error. Thanks - I presume the message we settled upon last time is helpful enough: Only one of qcom,num-strings or qcom,enabled-strings should be set I'll respin this, together with this warning reordered into the next commit, and using __le16 for the cpu_to_le16 output. - Marijn
diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c index 977cd75827d7..c5232478a343 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -1253,21 +1253,6 @@ static const struct wled_var_cfg wled5_ovp_cfg = { .size = 16, }; -static u32 wled3_num_strings_values_fn(u32 idx) -{ - return idx + 1; -} - -static const struct wled_var_cfg wled3_num_strings_cfg = { - .fn = wled3_num_strings_values_fn, - .size = 3, -}; - -static const struct wled_var_cfg wled4_num_strings_cfg = { - .fn = wled3_num_strings_values_fn, - .size = 4, -}; - static u32 wled3_switch_freq_values_fn(u32 idx) { return 19200 / (2 * (1 + idx)); @@ -1341,11 +1326,6 @@ static int wled_configure(struct wled *wled) .val_ptr = &cfg->switch_freq, .cfg = &wled3_switch_freq_cfg, }, - { - .name = "qcom,num-strings", - .val_ptr = &cfg->num_strings, - .cfg = &wled3_num_strings_cfg, - }, }; const struct wled_u32_opts wled4_opts[] = { @@ -1369,11 +1349,6 @@ static int wled_configure(struct wled *wled) .val_ptr = &cfg->switch_freq, .cfg = &wled3_switch_freq_cfg, }, - { - .name = "qcom,num-strings", - .val_ptr = &cfg->num_strings, - .cfg = &wled4_num_strings_cfg, - }, }; const struct wled_u32_opts wled5_opts[] = { @@ -1397,11 +1372,6 @@ static int wled_configure(struct wled *wled) .val_ptr = &cfg->switch_freq, .cfg = &wled3_switch_freq_cfg, }, - { - .name = "qcom,num-strings", - .val_ptr = &cfg->num_strings, - .cfg = &wled4_num_strings_cfg, - }, { .name = "qcom,modulator-sel", .val_ptr = &cfg->mod_sel, @@ -1520,8 +1490,6 @@ static int wled_configure(struct wled *wled) *bool_opts[i].val_ptr = true; } - cfg->num_strings = cfg->num_strings + 1; - string_len = of_property_count_elems_of_size(dev->of_node, "qcom,enabled-strings", sizeof(u32)); @@ -1552,6 +1520,25 @@ static int wled_configure(struct wled *wled) } } + rc = of_property_read_u32(dev->of_node, "qcom,num-strings", &val); + if (!rc) { + if (val < 1 || val > wled->max_string_count) { + dev_err(dev, "qcom,num-strings must be between 1 and %d\n", + wled->max_string_count); + return -EINVAL; + } + + if (string_len > 0) { + dev_warn(dev, "qcom,num-strings and qcom,enabled-strings are ambiguous\n"); + if (val > string_len) { + dev_err(dev, "qcom,num-strings exceeds qcom,enabled-strings\n"); + return -EINVAL; + } + } + + cfg->num_strings = val; + } + return 0; }