mptutil, mfitil, expand_number
Bruce Evans
brde at optusnet.com.au
Mon Nov 11 04:21:42 UTC 2013
On Sun, 10 Nov 2013, Eitan Adler wrote:
> On Sun, Nov 10, 2013 at 1:25 AM, Bruce Evans <brde at optusnet.com.au> wrote:
> Lets see if I understand everything you wanted me to do. I am not
> intending to fix any bugs in expand_number at the moment if any.
> diff --git a/usr.sbin/mptutil/mpt_config.c b/usr.sbin/mptutil/mpt_config.c
> index 17b9945..0d34d16 100644
> --- a/usr.sbin/mptutil/mpt_config.c
> +++ b/usr.sbin/mptutil/mpt_config.c
> ...
> @@ -615,7 +586,7 @@ create_volume(int ac, char **av)
> CONFIG_PAGE_RAID_VOL_0 *vol;
> struct config_id_state state;
> struct volume_info *info;
> - long stripe_size;
> + uint64_t stripe_size;
> int ch, error, fd, i, quick, raid_type, verbose;
> #ifdef DEBUG
> int dump;
Blindly changing the type is not clearly safe. In fact, it is not safe.
After initialization, it is only used to pass to functions expecting a
long, and there is a prototype that blindly converts it to long. Overflow
can then occur on 32-bit systems, since you didn't fix the range checking.
> @@ -666,7 +637,11 @@ create_volume(int ac, char **av)
> quick = 1;
> break;
> case 's':
> - stripe_size = dehumanize(optarg);
> + error = expand_number(optarg, &stripe_size);
> + if (error == -1) {
> + warnx("Invalid stripe size %s", optarg);
> + return (errno);
> + }
> if ((stripe_size < 512) || (!powerof2(stripe_size))) {
> warnx("Invalid stripe size %s", optarg);
> return (EINVAL);
Overflow occurs when stripe_size is used when it exceeds > LONG_MAX.
This can give a negative number. E.g., on 32-bit 2's complement
systems, stripe_size might be 0x80000000 here. This gets converted
to LONG_MIN. Dividing this by 512 gives -4194304 in vol->StripeSize.
The previous overflow bugs could never give a negative value, since
if dehumanize() overflows to a negative value then in the above it
doesn't pass the !(stripe_size < 512) test. Larger values can overflow
to anything.
This should be fixed by checking the range from above like I said before.
I forgot to check before if powerof2() works. It was invalid to call it
with a long arg, and the type change fixes this. powerof2() and nearby
functions in <sys/param.h> require an unsigned type, or a strictly positive
(nonzero) signed value, or pure 2's complement. A range check from above
would have fixed this too. Of course, systemish code like this assumes
pure 2's complement for everthing.
Bruce
More information about the freebsd-scsi
mailing list