linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] scsi: sg: Avoid overflow when USER_HZ > HZ
@ 2016-08-19 16:43 Paul Burton
  2016-08-19 16:43 ` [PATCH 2/2] scsi: sg: Use mult_frac, drop MULDIV macro Paul Burton
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Paul Burton @ 2016-08-19 16:43 UTC (permalink / raw)
  To: linux-scsi, James E . J . Bottomley, Martin K . Petersen,
	Doug Gilbert
  Cc: Paul Burton

Calculating the maximum timeout that a user can set via the
SG_SET_TIMEOUT ioctl involves multiplying INT_MAX by USER_HZ/HZ. If
USER_HZ is larger than HZ then this results in an overflow when
performed as a 32 bit integer calculation, resulting in compiler
warnings such as the following:

  drivers/scsi/sg.c: In function 'sg_ioctl':
  drivers/scsi/sg.c:91:67: warning: integer overflow in expression [-Woverflow]
   #define MULDIV(X,MUL,DIV) ((((X % DIV) * MUL) / DIV) + ((X / DIV) * MUL))
                                                                     ^
  drivers/scsi/sg.c:887:14: note: in expansion of macro 'MULDIV'
     if (val >= MULDIV (INT_MAX, USER_HZ, HZ))
                ^
  drivers/scsi/sg.c:91:67: warning: integer overflow in expression [-Woverflow]
   #define MULDIV(X,MUL,DIV) ((((X % DIV) * MUL) / DIV) + ((X / DIV) * MUL))
                                                                     ^
  drivers/scsi/sg.c:888:13: note: in expansion of macro 'MULDIV'
         val = MULDIV (INT_MAX, USER_HZ, HZ);
               ^

Avoid this overflow by performing the (constant) arithmetic on 64 bit
integers, which ensures that overflow from multiplying the 32 bit values
cannot occur. When converting the result back to a 32 bit integer use
min_t to ensure that we don't simply truncate a value beyond INT_MAX to
a 32 bit integer, but instead use INT_MAX where the result was larger
than it. As the values are all compile time constant the 64 bit
arithmetic should have no runtime cost.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 drivers/scsi/sg.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index ae7d9bd..bb5ec2d 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -884,8 +884,9 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 			return result;
 		if (val < 0)
 			return -EIO;
-		if (val >= MULDIV (INT_MAX, USER_HZ, HZ))
-		    val = MULDIV (INT_MAX, USER_HZ, HZ);
+		if (val >= MULDIV((s64)INT_MAX, USER_HZ, HZ))
+			val = min_t(s64, MULDIV((s64)INT_MAX, USER_HZ, HZ),
+				    INT_MAX);
 		sfp->timeout_user = val;
 		sfp->timeout = MULDIV (val, HZ, USER_HZ);
 
-- 
2.9.3


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

* [PATCH 2/2] scsi: sg: Use mult_frac, drop MULDIV macro
  2016-08-19 16:43 [PATCH 1/2] scsi: sg: Avoid overflow when USER_HZ > HZ Paul Burton
@ 2016-08-19 16:43 ` Paul Burton
  2016-08-26 21:21   ` Douglas Gilbert
  2016-08-31  2:19   ` Martin K. Petersen
  2016-08-26  3:27 ` [PATCH 1/2] scsi: sg: Avoid overflow when USER_HZ > HZ Martin K. Petersen
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 7+ messages in thread
From: Paul Burton @ 2016-08-19 16:43 UTC (permalink / raw)
  To: linux-scsi, James E . J . Bottomley, Martin K . Petersen,
	Doug Gilbert
  Cc: Paul Burton

The MULDIV macro is essentially a duplicate of the more standard
mult_frac macro. Replace use of MULDIV with mult_frac & drop the
duplication.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
 drivers/scsi/sg.c | 19 ++++---------------
 1 file changed, 4 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index bb5ec2d..070332e 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -79,18 +79,7 @@ static void sg_proc_cleanup(void);
  */
 #define SG_MAX_CDB_SIZE 252
 
-/*
- * Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d)
- * Then when using 32 bit integers x * m may overflow during the calculation.
- * Replacing muldiv(x) by muldiv(x)=((x % d) * m) / d + int(x / d) * m
- * calculates the same, but prevents the overflow when both m and d
- * are "small" numbers (like HZ and USER_HZ).
- * Of course an overflow is inavoidable if the result of muldiv doesn't fit
- * in 32 bits.
- */
-#define MULDIV(X,MUL,DIV) ((((X % DIV) * MUL) / DIV) + ((X / DIV) * MUL))
-
-#define SG_DEFAULT_TIMEOUT MULDIV(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
+#define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
 
 int sg_big_buff = SG_DEF_RESERVED_SIZE;
 /* N.B. This variable is readable and writeable via
@@ -884,11 +873,11 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 			return result;
 		if (val < 0)
 			return -EIO;
-		if (val >= MULDIV((s64)INT_MAX, USER_HZ, HZ))
-			val = min_t(s64, MULDIV((s64)INT_MAX, USER_HZ, HZ),
+		if (val >= mult_frac((s64)INT_MAX, USER_HZ, HZ))
+			val = min_t(s64, mult_frac((s64)INT_MAX, USER_HZ, HZ),
 				    INT_MAX);
 		sfp->timeout_user = val;
-		sfp->timeout = MULDIV (val, HZ, USER_HZ);
+		sfp->timeout = mult_frac(val, HZ, USER_HZ);
 
 		return 0;
 	case SG_GET_TIMEOUT:	/* N.B. User receives timeout as return value */
-- 
2.9.3


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

* Re: [PATCH 1/2] scsi: sg: Avoid overflow when USER_HZ > HZ
  2016-08-19 16:43 [PATCH 1/2] scsi: sg: Avoid overflow when USER_HZ > HZ Paul Burton
  2016-08-19 16:43 ` [PATCH 2/2] scsi: sg: Use mult_frac, drop MULDIV macro Paul Burton
@ 2016-08-26  3:27 ` Martin K. Petersen
  2016-08-26 21:21 ` Douglas Gilbert
  2016-08-31  2:19 ` Martin K. Petersen
  3 siblings, 0 replies; 7+ messages in thread
From: Martin K. Petersen @ 2016-08-26  3:27 UTC (permalink / raw)
  To: Paul Burton
  Cc: linux-scsi, James E . J . Bottomley, Martin K . Petersen,
	Doug Gilbert

>>>>> "Paul" == Paul Burton <paul.burton@imgtec.com> writes:

Paul> Calculating the maximum timeout that a user can set via the
Paul> SG_SET_TIMEOUT ioctl involves multiplying INT_MAX by
Paul> USER_HZ/HZ. If USER_HZ is larger than HZ then this results in an
Paul> overflow when performed as a 32 bit integer calculation, resulting
Paul> in compiler warnings such as the following:

Doug: Please review.

Thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* Re: [PATCH 1/2] scsi: sg: Avoid overflow when USER_HZ > HZ
  2016-08-19 16:43 [PATCH 1/2] scsi: sg: Avoid overflow when USER_HZ > HZ Paul Burton
  2016-08-19 16:43 ` [PATCH 2/2] scsi: sg: Use mult_frac, drop MULDIV macro Paul Burton
  2016-08-26  3:27 ` [PATCH 1/2] scsi: sg: Avoid overflow when USER_HZ > HZ Martin K. Petersen
@ 2016-08-26 21:21 ` Douglas Gilbert
  2016-08-31  2:19 ` Martin K. Petersen
  3 siblings, 0 replies; 7+ messages in thread
From: Douglas Gilbert @ 2016-08-26 21:21 UTC (permalink / raw)
  To: Paul Burton, linux-scsi, James E . J . Bottomley,
	Martin K . Petersen

On 2016-08-19 06:43 PM, Paul Burton wrote:
> Calculating the maximum timeout that a user can set via the
> SG_SET_TIMEOUT ioctl involves multiplying INT_MAX by USER_HZ/HZ. If
> USER_HZ is larger than HZ then this results in an overflow when
> performed as a 32 bit integer calculation, resulting in compiler
> warnings such as the following:
>
>   drivers/scsi/sg.c: In function 'sg_ioctl':
>   drivers/scsi/sg.c:91:67: warning: integer overflow in expression [-Woverflow]
>    #define MULDIV(X,MUL,DIV) ((((X % DIV) * MUL) / DIV) + ((X / DIV) * MUL))
>                                                                      ^
>   drivers/scsi/sg.c:887:14: note: in expansion of macro 'MULDIV'
>      if (val >= MULDIV (INT_MAX, USER_HZ, HZ))
>                 ^
>   drivers/scsi/sg.c:91:67: warning: integer overflow in expression [-Woverflow]
>    #define MULDIV(X,MUL,DIV) ((((X % DIV) * MUL) / DIV) + ((X / DIV) * MUL))
>                                                                      ^
>   drivers/scsi/sg.c:888:13: note: in expansion of macro 'MULDIV'
>          val = MULDIV (INT_MAX, USER_HZ, HZ);
>                ^
>
> Avoid this overflow by performing the (constant) arithmetic on 64 bit
> integers, which ensures that overflow from multiplying the 32 bit values
> cannot occur. When converting the result back to a 32 bit integer use
> min_t to ensure that we don't simply truncate a value beyond INT_MAX to
> a 32 bit integer, but instead use INT_MAX where the result was larger
> than it. As the values are all compile time constant the 64 bit
> arithmetic should have no runtime cost.
>
> Signed-off-by: Paul Burton <paul.burton@imgtec.com>

That macro has been changed several times, hopefully this is the final
time.

Acked by: Douglas Gilbert <dgilbert@interlog.com>

> ---
>  drivers/scsi/sg.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
> index ae7d9bd..bb5ec2d 100644
> --- a/drivers/scsi/sg.c
> +++ b/drivers/scsi/sg.c
> @@ -884,8 +884,9 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
>  			return result;
>  		if (val < 0)
>  			return -EIO;
> -		if (val >= MULDIV (INT_MAX, USER_HZ, HZ))
> -		    val = MULDIV (INT_MAX, USER_HZ, HZ);
> +		if (val >= MULDIV((s64)INT_MAX, USER_HZ, HZ))
> +			val = min_t(s64, MULDIV((s64)INT_MAX, USER_HZ, HZ),
> +				    INT_MAX);
>  		sfp->timeout_user = val;
>  		sfp->timeout = MULDIV (val, HZ, USER_HZ);
>
>


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

* Re: [PATCH 2/2] scsi: sg: Use mult_frac, drop MULDIV macro
  2016-08-19 16:43 ` [PATCH 2/2] scsi: sg: Use mult_frac, drop MULDIV macro Paul Burton
@ 2016-08-26 21:21   ` Douglas Gilbert
  2016-08-31  2:19   ` Martin K. Petersen
  1 sibling, 0 replies; 7+ messages in thread
From: Douglas Gilbert @ 2016-08-26 21:21 UTC (permalink / raw)
  To: Paul Burton, linux-scsi, James E . J . Bottomley,
	Martin K . Petersen

On 2016-08-19 06:43 PM, Paul Burton wrote:
> The MULDIV macro is essentially a duplicate of the more standard
> mult_frac macro. Replace use of MULDIV with mult_frac & drop the
> duplication.
>
> Signed-off-by: Paul Burton <paul.burton@imgtec.com>

I spoke too soon, as this patch changes the last one :-)
As far as I can determine mult_frac() is a cleaner version of
MULDIV(); so

Acked by: Douglas Gilbert <dgilbert@interlog.com>

> ---
>  drivers/scsi/sg.c | 19 ++++---------------
>  1 file changed, 4 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
> index bb5ec2d..070332e 100644
> --- a/drivers/scsi/sg.c
> +++ b/drivers/scsi/sg.c
> @@ -79,18 +79,7 @@ static void sg_proc_cleanup(void);
>   */
>  #define SG_MAX_CDB_SIZE 252
>
> -/*
> - * Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d)
> - * Then when using 32 bit integers x * m may overflow during the calculation.
> - * Replacing muldiv(x) by muldiv(x)=((x % d) * m) / d + int(x / d) * m
> - * calculates the same, but prevents the overflow when both m and d
> - * are "small" numbers (like HZ and USER_HZ).
> - * Of course an overflow is inavoidable if the result of muldiv doesn't fit
> - * in 32 bits.
> - */
> -#define MULDIV(X,MUL,DIV) ((((X % DIV) * MUL) / DIV) + ((X / DIV) * MUL))
> -
> -#define SG_DEFAULT_TIMEOUT MULDIV(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
> +#define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
>
>  int sg_big_buff = SG_DEF_RESERVED_SIZE;
>  /* N.B. This variable is readable and writeable via
> @@ -884,11 +873,11 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
>  			return result;
>  		if (val < 0)
>  			return -EIO;
> -		if (val >= MULDIV((s64)INT_MAX, USER_HZ, HZ))
> -			val = min_t(s64, MULDIV((s64)INT_MAX, USER_HZ, HZ),
> +		if (val >= mult_frac((s64)INT_MAX, USER_HZ, HZ))
> +			val = min_t(s64, mult_frac((s64)INT_MAX, USER_HZ, HZ),
>  				    INT_MAX);
>  		sfp->timeout_user = val;
> -		sfp->timeout = MULDIV (val, HZ, USER_HZ);
> +		sfp->timeout = mult_frac(val, HZ, USER_HZ);
>
>  		return 0;
>  	case SG_GET_TIMEOUT:	/* N.B. User receives timeout as return value */
>


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

* Re: [PATCH 1/2] scsi: sg: Avoid overflow when USER_HZ > HZ
  2016-08-19 16:43 [PATCH 1/2] scsi: sg: Avoid overflow when USER_HZ > HZ Paul Burton
                   ` (2 preceding siblings ...)
  2016-08-26 21:21 ` Douglas Gilbert
@ 2016-08-31  2:19 ` Martin K. Petersen
  3 siblings, 0 replies; 7+ messages in thread
From: Martin K. Petersen @ 2016-08-31  2:19 UTC (permalink / raw)
  To: Paul Burton
  Cc: linux-scsi, James E . J . Bottomley, Martin K . Petersen,
	Doug Gilbert

>>>>> "Paul" == Paul Burton <paul.burton@imgtec.com> writes:

Paul> Calculating the maximum timeout that a user can set via the
Paul> SG_SET_TIMEOUT ioctl involves multiplying INT_MAX by
Paul> USER_HZ/HZ. If USER_HZ is larger than HZ then this results in an
Paul> overflow when performed as a 32 bit integer calculation, resulting
Paul> in compiler warnings such as the following:

Applied to 4.9/scsi-queue.

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* Re: [PATCH 2/2] scsi: sg: Use mult_frac, drop MULDIV macro
  2016-08-19 16:43 ` [PATCH 2/2] scsi: sg: Use mult_frac, drop MULDIV macro Paul Burton
  2016-08-26 21:21   ` Douglas Gilbert
@ 2016-08-31  2:19   ` Martin K. Petersen
  1 sibling, 0 replies; 7+ messages in thread
From: Martin K. Petersen @ 2016-08-31  2:19 UTC (permalink / raw)
  To: Paul Burton
  Cc: linux-scsi, James E . J . Bottomley, Martin K . Petersen,
	Doug Gilbert

>>>>> "Paul" == Paul Burton <paul.burton@imgtec.com> writes:

Paul> The MULDIV macro is essentially a duplicate of the more standard
Paul> mult_frac macro. Replace use of MULDIV with mult_frac & drop the
Paul> duplication.

Applied to 4.9/scsi-queue.

-- 
Martin K. Petersen	Oracle Linux Engineering

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

end of thread, other threads:[~2016-08-31  2:20 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-19 16:43 [PATCH 1/2] scsi: sg: Avoid overflow when USER_HZ > HZ Paul Burton
2016-08-19 16:43 ` [PATCH 2/2] scsi: sg: Use mult_frac, drop MULDIV macro Paul Burton
2016-08-26 21:21   ` Douglas Gilbert
2016-08-31  2:19   ` Martin K. Petersen
2016-08-26  3:27 ` [PATCH 1/2] scsi: sg: Avoid overflow when USER_HZ > HZ Martin K. Petersen
2016-08-26 21:21 ` Douglas Gilbert
2016-08-31  2:19 ` Martin K. Petersen

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).