Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date: Mon, 6 Feb 2012 09:25:57 +0400
From: Solar Designer <>
Subject: Re: CVE Request -- kernel: jbd/jbd2: invalid value of first log block leads to oops

On Sun, Nov 13, 2011 at 08:55:00AM -0700, Kurt Seifried wrote:
> On 11/11/2011 03:50 PM, Petr Matousek wrote:
> > A flaw was found in the way Linux kernel's Journaling Block Device (JBD)
> > handled invalid log first block value. An attacker able to mount
> > malicious ext3 or ext4 image could use this flaw to crash the system.
> >
> > Upstream commit:
> > 8762202dd0d6e46854f786bdb6fb3780a1625efe
> >
> > Reference:
> >
> CVE-2011-4132 is for kernel: jbd/jbd2: invalid value of first log block
> leads to oops says "A flaw was found
in the Linux kernel's Journaling Block Device (JBD).
A local attacker could use this flaw to crash the system by mounting a
specially-crafted ext3 or ext4 disk. (CVE-2011-4132, Moderate)"

Even though the issue is of little relevance for us due to its attack
vector, I wanted to see if it's in fact limited to a DoS or maybe not.

Red Hat Bugzilla:

Upstream fix:;a=commitdiff;h=8762202dd0d6e46854f786bdb6fb3780a1625efe

The commit message is lengthy and it includes a reproducer script (I am
pleasantly surprised).  It says that for ext3 an assert failure occurs
when s_first == 0, so this case does in fact feel like just a DoS at
first glance at the commit message (not sure whether the same applies to
ext4, though).  (But please read below.)  However, the fix also adds a
check to reject "be32_to_cpu(sb->s_first) >= journal->j_maxlen", and it
is non-obvious what happens when s_first is above this limit.

Trying to follow the code, it appears that without the fix the
journal_get_superblock() call from load_superblock() does not return an
error for these invalid values of s_first, so we get to:

	journal->j_first = be32_to_cpu(sb->s_first);

j_first in turn gets into other fields in journal_reset() or/and in
journal_next_log_block().  However, journal_reset() has:

	journal->j_free = last - first;

and journal_next_log_block() has:

	J_ASSERT(journal->j_free > 1);

This could save us from worse-than-DoS impact, but j_free is unsigned
(so would-be-nagative values would look valid to the assert) and
additionally J_ASSERT() is jbd.h (unlike jbd2.h's) looks like it will
happily return control after merely dumping a backtrace.

...Speaking of the latter, this means that the assert mentioned in the
commit message is probably also insufficient to guarantee that there's
no worse-than-DoS impact for the "== 0" case.

journal_next_log_block() may set:

		journal->j_head = journal->j_first;

and the next call to it may do:

	blocknr = journal->j_head;
	return journal_bmap(journal, blocknr, retp);

which calls:

		ret = bmap(journal->j_inode, blocknr);

Thus, it appears that we may get an almost arbitrary out of range block
number passed down into:

sector_t bmap(struct inode * inode, sector_t block)
	sector_t res = 0;
	if (inode->i_mapping->a_ops->bmap)
		res = inode->i_mapping->a_ops->bmap(inode->i_mapping, block);
	return res;

Following my guess as to what the ->bmap pointer might be here (note: I
am not familiar with this code at all), I looked at ext3_bmap() and
ext4_bmap().  These simply pass the block number into
generic_block_bmap(), and they also pass a pointer to ext3_get_block()
and ext4_get_block(), respectively.  generic_block_bmap() does little
besides calling the specific get_block() function via the pointer, but
those fs-specific functions and those they call are non-trivial.

That's where I stopped spending/wasting my time on this, concluding that
I still do not know if it's just a DoS (likely) or worse (possibly).
If this were of more relevance to us, I'd probably figure it out, but as
it is I just leave it for someone more curious or actually requiring
proof.  Sorry for this xorl'ish "analysis"; I was hoping I'd arrive at
something more useful, but I just ran out of time on this. ;-(

The only maybe-useful outcome is another confirmation that this kind of
issues are rarely quick and easy to fully analyze and figure out their
precise impact.


Powered by blists - more mailing lists

Your e-mail address:

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Powered by Openwall GNU/*/Linux - Powered by OpenVZ