diff mbox series

iio: magn: bmc150: add a lower bounds in bmc150_magn_write_raw()

Message ID 94939714-a232-4107-8741-8867038b03ae@kili.mountain (mailing list archive)
State Changes Requested
Headers show
Series iio: magn: bmc150: add a lower bounds in bmc150_magn_write_raw() | expand

Commit Message

Dan Carpenter March 8, 2023, 9:12 a.m. UTC
The "val" variable comes from the user via iio_write_channel_info().
This code puts an upper bound on "val" but it doesn't check for
negatives so Smatch complains.  I don't think either the bounds
checking is really required, but it's just good to be conservative.

Fixes: 5990dc970367 ("iio: magn: bmc150_magn: add oversampling ratio")
Signed-off-by: Dan Carpenter <error27@gmail.com>
---
 drivers/iio/magnetometer/bmc150_magn.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Jonathan Cameron March 12, 2023, 2:45 p.m. UTC | #1
On Wed, 8 Mar 2023 12:12:37 +0300
Dan Carpenter <error27@gmail.com> wrote:

> The "val" variable comes from the user via iio_write_channel_info().
> This code puts an upper bound on "val" but it doesn't check for
> negatives so Smatch complains.  I don't think either the bounds
> checking is really required, but it's just good to be conservative.
> 
> Fixes: 5990dc970367 ("iio: magn: bmc150_magn: add oversampling ratio")
> Signed-off-by: Dan Carpenter <error27@gmail.com>

Hi Dan,

I think this is more complex than it initially appears.

bmc150_magn_set_odr() matches against a table of possible value
(precise matching) and as such you'd assume neither check is necessary.

However, for a given configuration not all values in that table can
actually be set due to max_odr actually changing depending on other settings.

My immediate thought was "why not push this check into bmc150_magn_set_odr()"
where this will be more obvious.  Turns out that max_odr isn't available until
later in bmc150_magn_init() than the initial call of bmc150_magn_set_odr()
 
Whilst I 'think' you could move that around so that max_odr was set, that's not quite
obvious enough for me to want to do it without testing the result.

So question becomes is it wroth adding the val < 0 check here.
My gut feeling is that actually makes it more confusing because we are checking
something that doesn't restrict the later results alongside something that does.

Am I missing something, or was smatch just being overly careful?

Jonathan


> ---
>  drivers/iio/magnetometer/bmc150_magn.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c
> index 06d5a1ef1fbd..c625416b8bcf 100644
> --- a/drivers/iio/magnetometer/bmc150_magn.c
> +++ b/drivers/iio/magnetometer/bmc150_magn.c
> @@ -537,7 +537,7 @@ static int bmc150_magn_write_raw(struct iio_dev *indio_dev,
>  
>  	switch (mask) {
>  	case IIO_CHAN_INFO_SAMP_FREQ:
> -		if (val > data->max_odr)
> +		if (val < 0 || val > data->max_odr)
>  			return -EINVAL;
>  		mutex_lock(&data->mutex);
>  		ret = bmc150_magn_set_odr(data, val);
Dan Carpenter March 13, 2023, 12:04 p.m. UTC | #2
On Sun, Mar 12, 2023 at 02:45:51PM +0000, Jonathan Cameron wrote:
> On Wed, 8 Mar 2023 12:12:37 +0300
> Dan Carpenter <error27@gmail.com> wrote:
> 
> > The "val" variable comes from the user via iio_write_channel_info().
> > This code puts an upper bound on "val" but it doesn't check for
> > negatives so Smatch complains.  I don't think either the bounds
> > checking is really required, but it's just good to be conservative.
> > 
> > Fixes: 5990dc970367 ("iio: magn: bmc150_magn: add oversampling ratio")
> > Signed-off-by: Dan Carpenter <error27@gmail.com>
> 
> Hi Dan,
> 
> I think this is more complex than it initially appears.
> 
> bmc150_magn_set_odr() matches against a table of possible value
> (precise matching) and as such you'd assume neither check is necessary.
> 
> However, for a given configuration not all values in that table can
> actually be set due to max_odr actually changing depending on other settings.
> 
> My immediate thought was "why not push this check into bmc150_magn_set_odr()"
> where this will be more obvious.  Turns out that max_odr isn't available until
> later in bmc150_magn_init() than the initial call of bmc150_magn_set_odr()
>  
> Whilst I 'think' you could move that around so that max_odr was set, that's not quite
> obvious enough for me to want to do it without testing the result.
> 
> So question becomes is it wroth adding the val < 0 check here.
> My gut feeling is that actually makes it more confusing because we are checking
> something that doesn't restrict the later results alongside something that does.
> 
> Am I missing something, or was smatch just being overly careful?

Okay, fair enough.  The upper bounds is required and the lower bounds is
not.

However, passing negatives is still not best practice and I feel like it
wasn't intentional here.  Let me resend the commit, but with a different
commit message that doesn't say the upper bound is not required.

The Smatch warning feels intuitively correct.  If you're going to have
an upper bounds check then you need to have a lower bounds check to
prevent negative values.  In practice it works pretty well.  The only
major issue with this check is that sometimes Smatch thinks a variable
can be negative when it cannot.

This patch is an example where passing a negative is harmless and I had
a similar warning last week where it was passing a negative param was
harmless as well.  The parameter was used as loop limit:

	for (i = 0; i < param; i++) {

It's a no-op since param is negative, but all all it needs is for
someone declare the iterator as "unsigned int i;" and then it becomes
a memory corruption issue.

So occasionally passing negatives is harmless but mostly it's bad.

regards,
dan carpenter
Jonathan Cameron March 18, 2023, 5:31 p.m. UTC | #3
On Mon, 13 Mar 2023 15:04:28 +0300
Dan Carpenter <error27@gmail.com> wrote:

> On Sun, Mar 12, 2023 at 02:45:51PM +0000, Jonathan Cameron wrote:
> > On Wed, 8 Mar 2023 12:12:37 +0300
> > Dan Carpenter <error27@gmail.com> wrote:
> >   
> > > The "val" variable comes from the user via iio_write_channel_info().
> > > This code puts an upper bound on "val" but it doesn't check for
> > > negatives so Smatch complains.  I don't think either the bounds
> > > checking is really required, but it's just good to be conservative.
> > > 
> > > Fixes: 5990dc970367 ("iio: magn: bmc150_magn: add oversampling ratio")
> > > Signed-off-by: Dan Carpenter <error27@gmail.com>  
> > 
> > Hi Dan,
> > 
> > I think this is more complex than it initially appears.
> > 
> > bmc150_magn_set_odr() matches against a table of possible value
> > (precise matching) and as such you'd assume neither check is necessary.
> > 
> > However, for a given configuration not all values in that table can
> > actually be set due to max_odr actually changing depending on other settings.
> > 
> > My immediate thought was "why not push this check into bmc150_magn_set_odr()"
> > where this will be more obvious.  Turns out that max_odr isn't available until
> > later in bmc150_magn_init() than the initial call of bmc150_magn_set_odr()
> >  
> > Whilst I 'think' you could move that around so that max_odr was set, that's not quite
> > obvious enough for me to want to do it without testing the result.
> > 
> > So question becomes is it wroth adding the val < 0 check here.
> > My gut feeling is that actually makes it more confusing because we are checking
> > something that doesn't restrict the later results alongside something that does.
> > 
> > Am I missing something, or was smatch just being overly careful?  
> 
> Okay, fair enough.  The upper bounds is required and the lower bounds is
> not.
> 
> However, passing negatives is still not best practice and I feel like it
> wasn't intentional here.  Let me resend the commit, but with a different
> commit message that doesn't say the upper bound is not required.

That works for me.

> 
> The Smatch warning feels intuitively correct.  If you're going to have
> an upper bounds check then you need to have a lower bounds check to
> prevent negative values.  In practice it works pretty well.  The only
> major issue with this check is that sometimes Smatch thinks a variable
> can be negative when it cannot.
> 
> This patch is an example where passing a negative is harmless and I had
> a similar warning last week where it was passing a negative param was
> harmless as well.  The parameter was used as loop limit:
> 
> 	for (i = 0; i < param; i++) {
> 
> It's a no-op since param is negative, but all all it needs is for
> someone declare the iterator as "unsigned int i;" and then it becomes
> a memory corruption issue.
> 
> So occasionally passing negatives is harmless but mostly it's bad.

Agreed.

> 
> regards,
> dan carpenter
> 
> 
>
diff mbox series

Patch

diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c
index 06d5a1ef1fbd..c625416b8bcf 100644
--- a/drivers/iio/magnetometer/bmc150_magn.c
+++ b/drivers/iio/magnetometer/bmc150_magn.c
@@ -537,7 +537,7 @@  static int bmc150_magn_write_raw(struct iio_dev *indio_dev,
 
 	switch (mask) {
 	case IIO_CHAN_INFO_SAMP_FREQ:
-		if (val > data->max_odr)
+		if (val < 0 || val > data->max_odr)
 			return -EINVAL;
 		mutex_lock(&data->mutex);
 		ret = bmc150_magn_set_odr(data, val);