Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1211207 > unrolled thread

[PATCH] mtd: blktrans: fix integer overflow

Started byPeng Fan <van.freenix@gmail.com>
First post2015-08-21 17:00 +0200
Last post2015-09-10 01:40 +0200
Articles 4 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH] mtd: blktrans: fix integer overflow Peng Fan <van.freenix@gmail.com> - 2015-08-21 17:00 +0200
    Re: [PATCH] mtd: blktrans: fix integer overflow Brian Norris <computersforpeace@gmail.com> - 2015-09-02 19:10 +0200
      Re: [PATCH] mtd: blktrans: fix integer overflow Peng Fan <van.freenix@gmail.com> - 2015-09-05 15:50 +0200
        Re: [PATCH] mtd: blktrans: fix integer overflow Brian Norris <computersforpeace@gmail.com> - 2015-09-10 01:40 +0200

#1211207 — [PATCH] mtd: blktrans: fix integer overflow

FromPeng Fan <van.freenix@gmail.com>
Date2015-08-21 17:00 +0200
Subject[PATCH] mtd: blktrans: fix integer overflow
Message-ID<pZVXs-6N0-23@gated-at.bofh.it>
In drivers/mtd/mtd_blkdevs.c:
406	set_capacity(gd, (new->size * tr->blksize) >> 9);
The type of new->size is unsigned long and the type of tr->blksize is int,
the result of 'new->size * tr->blksize' may exceed ULONG_MAX on 32bit
machines.

I use nand chip MT29F32G08CBADBWP which is 4GB and the parameters passed
to kernel is 'mtdparts=gpmi-nand:-(user)', the whole nand chip will be
treated as a 4GB mtd partition. new->size is 0x800000 and tr->blksize is
0x200, 'new->size * tr->blksize' however is 0. This is what we do not want
to see.

Change the type of entry size of mtd_blktrans_dev to unsigned long long
to fix the overflow issue.

Signed-off-by: Peng Fan <van.freenix@gmail.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Brian Norris <computersforpeace@gmail.com>
---
 include/linux/mtd/blktrans.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
index e93837f..3853d74 100644
--- a/include/linux/mtd/blktrans.h
+++ b/include/linux/mtd/blktrans.h
@@ -38,7 +38,7 @@ struct mtd_blktrans_dev {
 	struct mutex lock;
 	int devnum;
 	bool bg_stop;
-	unsigned long size;
+	unsigned long long size;
 	int readonly;
 	int open;
 	struct kref ref;
-- 
1.8.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1217761

FromBrian Norris <computersforpeace@gmail.com>
Date2015-09-02 19:10 +0200
Message-ID<q4jHQ-2S4-25@gated-at.bofh.it>
In reply to#1211207
On Fri, Aug 21, 2015 at 10:57:31PM +0800, Peng Fan wrote:
> In drivers/mtd/mtd_blkdevs.c:
> 406	set_capacity(gd, (new->size * tr->blksize) >> 9);
> The type of new->size is unsigned long and the type of tr->blksize is int,
> the result of 'new->size * tr->blksize' may exceed ULONG_MAX on 32bit
> machines.
> 
> I use nand chip MT29F32G08CBADBWP which is 4GB and the parameters passed
> to kernel is 'mtdparts=gpmi-nand:-(user)', the whole nand chip will be
> treated as a 4GB mtd partition. new->size is 0x800000 and tr->blksize is
> 0x200, 'new->size * tr->blksize' however is 0. This is what we do not want
> to see.
> 
> Change the type of entry size of mtd_blktrans_dev to unsigned long long
> to fix the overflow issue.
> 
> Signed-off-by: Peng Fan <van.freenix@gmail.com>
> Cc: David Woodhouse <dwmw2@infradead.org>
> Cc: Brian Norris <computersforpeace@gmail.com>
> ---
>  include/linux/mtd/blktrans.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
> index e93837f..3853d74 100644
> --- a/include/linux/mtd/blktrans.h
> +++ b/include/linux/mtd/blktrans.h
> @@ -38,7 +38,7 @@ struct mtd_blktrans_dev {
>  	struct mutex lock;
>  	int devnum;
>  	bool bg_stop;
> -	unsigned long size;
> +	unsigned long long size;

Sorry, you can't just do that. Some builds won't have right arithmetic
instructions (or compiler helpers) to do certain 64-bit operations, so you
either need to go and fix all the blktrans users to be more careful (e.g., do
bit shifts instead of division/modulo), or else find another solution. See, on
an ARM32 build:

  LD      init/built-in.o
drivers/built-in.o: In function `nftl_add_mtd':
:(.text+0x1369dc): undefined reference to `__aeabi_uldivmod'
:(.text+0x1369f4): undefined reference to `__aeabi_uldivmod'
:(.text+0x136a70): undefined reference to `__aeabi_uldivmod'
drivers/built-in.o: In function `inftl_add_mtd':
:(.text+0x137eb0): undefined reference to `__aeabi_uldivmod'
:(.text+0x137ec8): undefined reference to `__aeabi_uldivmod'
drivers/built-in.o::(.text+0x137f4c): more undefined references to `__aeabi_uldivmod' follow

>  	int readonly;
>  	int open;
>  	struct kref ref;

One possibility, since you only point to a single computation that
overflows, is to just fix the overflow locally. It's not like the 'size'
(which represents number of sectors) is actually ever overflowing a
32-bit integer. It's just the multiplication that overflows. So you
could cast to 64-bit arithmetic just for the multiplication. e.g.:

	set_capcity(gd, ((u64)new->size * tr->blksize) >> 9);

Or some other creative solution.

Then, we don't have to address this problem till we start seeing 2TB
MTDs!

Brian
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1219548

FromPeng Fan <van.freenix@gmail.com>
Date2015-09-05 15:50 +0200
Message-ID<q5m0W-25G-35@gated-at.bofh.it>
In reply to#1217761
On Wed, Sep 02, 2015 at 10:02:49AM -0700, Brian Norris wrote:
> On Fri, Aug 21, 2015 at 10:57:31PM +0800, Peng Fan wrote:
> > In drivers/mtd/mtd_blkdevs.c:
> > 406	set_capacity(gd, (new->size * tr->blksize) >> 9);
> > The type of new->size is unsigned long and the type of tr->blksize is int,
> > the result of 'new->size * tr->blksize' may exceed ULONG_MAX on 32bit
> > machines.
> > 
> > I use nand chip MT29F32G08CBADBWP which is 4GB and the parameters passed
> > to kernel is 'mtdparts=gpmi-nand:-(user)', the whole nand chip will be
> > treated as a 4GB mtd partition. new->size is 0x800000 and tr->blksize is
> > 0x200, 'new->size * tr->blksize' however is 0. This is what we do not want
> > to see.
> > 
> > Change the type of entry size of mtd_blktrans_dev to unsigned long long
> > to fix the overflow issue.
> > 
> > Signed-off-by: Peng Fan <van.freenix@gmail.com>
> > Cc: David Woodhouse <dwmw2@infradead.org>
> > Cc: Brian Norris <computersforpeace@gmail.com>
> > ---
> >  include/linux/mtd/blktrans.h | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
> > index e93837f..3853d74 100644
> > --- a/include/linux/mtd/blktrans.h
> > +++ b/include/linux/mtd/blktrans.h
> > @@ -38,7 +38,7 @@ struct mtd_blktrans_dev {
> >  	struct mutex lock;
> >  	int devnum;
> >  	bool bg_stop;
> > -	unsigned long size;
> > +	unsigned long long size;
> 
> Sorry, you can't just do that. Some builds won't have right arithmetic
> instructions (or compiler helpers) to do certain 64-bit operations, so you
> either need to go and fix all the blktrans users to be more careful (e.g., do
> bit shifts instead of division/modulo), or else find another solution. See, on
> an ARM32 build:
> 
>   LD      init/built-in.o
> drivers/built-in.o: In function `nftl_add_mtd':
> :(.text+0x1369dc): undefined reference to `__aeabi_uldivmod'
> :(.text+0x1369f4): undefined reference to `__aeabi_uldivmod'
> :(.text+0x136a70): undefined reference to `__aeabi_uldivmod'
> drivers/built-in.o: In function `inftl_add_mtd':
> :(.text+0x137eb0): undefined reference to `__aeabi_uldivmod'
> :(.text+0x137ec8): undefined reference to `__aeabi_uldivmod'
> drivers/built-in.o::(.text+0x137f4c): more undefined references to `__aeabi_uldivmod' follow
> 

My bad. I only tested this patch on i.mx6 platform, but not take other platforms into consideration.

> >  	int readonly;
> >  	int open;
> >  	struct kref ref;
> 
> One possibility, since you only point to a single computation that
> overflows, is to just fix the overflow locally. It's not like the 'size'
> (which represents number of sectors) is actually ever overflowing a
> 32-bit integer. It's just the multiplication that overflows. So you
> could cast to 64-bit arithmetic just for the multiplication. e.g.:
> 
> 	set_capcity(gd, ((u64)new->size * tr->blksize) >> 9);

Yeah. It is the multiplication overflowing a 32-bit interger. My frist implementation is this way, using u64 to do type cast.
But I guess one day the number of sectors can be larger than UINT_MAX, so I change it to 'unsigned long long' from 'unsigned long', which is
not the right way, thanks for correcting me.
> 
> Or some other creative solution.

I think this should be a bug fix. If you need a quick fix, I can send out the simple patch that just do (u64) cast. If not, I can take
some time to "fix all the blktrans users".

Regards,
Peng.

> 
> Then, we don't have to address this problem till we start seeing 2TB
> MTDs!
> 
> Brian
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1221792

FromBrian Norris <computersforpeace@gmail.com>
Date2015-09-10 01:40 +0200
Message-ID<q6X85-12V-1@gated-at.bofh.it>
In reply to#1219548
On Sat, Sep 05, 2015 at 09:42:27PM +0800, Peng Fan wrote:
> On Wed, Sep 02, 2015 at 10:02:49AM -0700, Brian Norris wrote:
> > One possibility, since you only point to a single computation that
> > overflows, is to just fix the overflow locally. It's not like the 'size'
> > (which represents number of sectors) is actually ever overflowing a
> > 32-bit integer. It's just the multiplication that overflows. So you
> > could cast to 64-bit arithmetic just for the multiplication. e.g.:
> > 
> > 	set_capcity(gd, ((u64)new->size * tr->blksize) >> 9);
> 
> Yeah. It is the multiplication overflowing a 32-bit interger. My frist
> implementation is this way, using u64 to do type cast. But I guess one
> day the number of sectors can be larger than UINT_MAX, so I change it
> to 'unsigned long long' from 'unsigned long', which is
> not the right way, thanks for correcting me.
> > 
> > Or some other creative solution.
> 
> I think this should be a bug fix. If you need a quick fix, I can send
> out the simple patch that just do (u64) cast. If not, I can take some
> time to "fix all the blktrans users".

I think since you've identified (and tested) a fix, we might as well
include it. So I suppose the cast approach. The larger change would be
more invasive and may take a while.

> > 
> > Then, we don't have to address this problem till we start seeing 2TB
> > MTDs!

Brian
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web