From: Al Viro <viro@ZenIV.linux.org.uk>
To: Josh Boyer <jwboyer@redhat.com>
Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org
Subject: Re: Oops in minixfs_statfs
Date: Wed, 17 Aug 2011 03:18:20 +0100 [thread overview]
Message-ID: <20110817021820.GU2203@ZenIV.linux.org.uk> (raw)
In-Reply-To: <20110816164809.GE2227@zod.bos.redhat.com>
On Tue, Aug 16, 2011 at 12:48:09PM -0400, Josh Boyer wrote:
> We've had a bug open in Fedora for a while[1] where it's fairly easy to
> generate an oops on a MinixV3 filesystem. I've looked at it a bit and
> it seems we're getting a negative number in this particular calculation
> in fs/minix/bitmap.c, count_free:
>
> i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2;
>
> which causes the loop below it to access bh->b_data outside it's bounds.
>
> I installed minix 3.1.8 (shoot me now) in a KVM guest today, and two out
> of the three filesystems work fine. / and /home are both relatively
> small, and a df seems to return fairly accurate numbers. However, a df
> on /usr (which is ~768M) causes the oops.
>
> I'm not familiar enough with minixfs to know what the above is trying to
> actually accomplish. I instrumented that function a bit and here is
> some data from the 3 filesytems in question:
>
> [ 49.114984] imap_blocks 2 zmap_blocks 1 firstdatazone 205
> log_zone_size 0 max_size 7fffffff magic 4d5a nzones 4000 blocksize: 1000
>
> [ 66.380824] imap_blocks 2 zmap_blocks 2 firstdatazone 2a2
> log_zone_size 0 max_size 7fffffff magic 4d5a nzones a700 blocksize: 1000
>
> [ 516.859103] imap_blocks 7 zmap_blocks 7 firstdatazone c11
> log_zone_size 0 max_size 7fffffff magic 4d5a nzones 3001c blocksize:
> 1000
>
> The calculation of i on line 38 results in fffffe80 for the last
> filesytem when minix_count_free_blocks is called for it.
>
> Does anyone have an idea of what that particular section is trying to
> count? (As an aside, the numbits variable is slightly confusing because
> it seems to be a number of blocks, not bits). I'd be happy to continue
> to poke at this, but I'm a bit stumped at the moment.
The arguments of that function are redundant and it smells like we have
numbits < numblocks * bits_per_block. Could you print both on that fs?
FWIW, it looks like this thing actually tries to be something like
/* count zero bits in bitmap; bitmap itself is an array of host-endian 16bit */
u32 count_free(struct super_block *sb, struct buffer_head *map[], u32 bits)
{
size_t size = sb->s_blocksize;
u32 sum = 0;
while (bits) {
struct buffer_head *bh = *map++;
__u16 *p = bh->b_data;
if (bits >= size * 8) { /* full block */
__u16 *end = bh->b_data + size;
while (p < end)
sum += hweight16(~*p++);
bits -= size * 8;
} else { /* bitmap takes only part of it */
__u16 *end = p + bits / 16;
/* full 16bit words */
while (p < end)
sum += hweight16(~*p++);
bits %= 16;
if (bits) { /* partial word, only lower bits matter */
sum += hweight16(~*p++ & ((1 << bits) - 1));
bits = 0;
}
}
}
return sum;
}
Note that this needs update of callers (both have the superblock ready)
*and* minix_fill_super() needs to verify that
a) sbi->s_ninodes < sbi->s_imap_blocks * sb->s_blocksize * 8
b) (sbi->s_nzones - sbi->s_firstdatazone + 1) <=
sbi->s_zmap_blocks * sb->s_blocksize * 8
and scream if it isn't.
I *think* that what's happening in your case is that we have more blocks
for block bitmap than we would need to hold all bits. That would explode
in exactly such a way, but I'd like to see confirmation; what arguments
does your count_free() actually get? The last two arguments, that is...
NOTE: the above is not even compile-testeed. It also needs an update to
deal with an atrocious kludge on several architectures - minix bitmaps
are *not* always host-endian on Linux and the things get really ugly
when we go into it; see CONFIG_MINIX_FS_.*_ENDIAN for gory details.
next prev parent reply other threads:[~2011-08-17 2:18 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-08-16 16:48 Oops in minixfs_statfs Josh Boyer
2011-08-16 22:20 ` Bob Copeland
2011-08-16 22:20 ` Bob Copeland
2011-08-17 0:31 ` Josh Boyer
2011-08-17 0:31 ` Josh Boyer
2011-08-17 2:18 ` Al Viro [this message]
2011-08-17 3:12 ` Bob Copeland
2011-08-17 17:18 ` Josh Boyer
2011-08-18 21:13 ` Josh Boyer
2011-08-18 21:16 ` Al Viro
2011-08-18 22:24 ` Josh Boyer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110817021820.GU2203@ZenIV.linux.org.uk \
--to=viro@zeniv.linux.org.uk \
--cc=jwboyer@redhat.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.