• X
    ext4: fix undefined behavior in ext4_fill_flex_info() · d50f2ab6
    Xi Wang 提交于
    Commit 503358ae ("ext4: avoid divide by
    zero when trying to mount a corrupted file system") fixes CVE-2009-4307
    by performing a sanity check on s_log_groups_per_flex, since it can be
    set to a bogus value by an attacker.
    
    	sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex;
    	groups_per_flex = 1 << sbi->s_log_groups_per_flex;
    
    	if (groups_per_flex < 2) { ... }
    
    This patch fixes two potential issues in the previous commit.
    
    1) The sanity check might only work on architectures like PowerPC.
    On x86, 5 bits are used for the shifting amount.  That means, given a
    large s_log_groups_per_flex value like 36, groups_per_flex = 1 << 36
    is essentially 1 << 4 = 16, rather than 0.  This will bypass the check,
    leaving s_log_groups_per_flex and groups_per_flex inconsistent.
    
    2) The sanity check relies on undefined behavior, i.e., oversized shift.
    A standard-confirming C compiler could rewrite the check in unexpected
    ways.  Consider the following equivalent form, assuming groups_per_flex
    is unsigned for simplicity.
    
    	groups_per_flex = 1 << sbi->s_log_groups_per_flex;
    	if (groups_per_flex == 0 || groups_per_flex == 1) {
    
    We compile the code snippet using Clang 3.0 and GCC 4.6.  Clang will
    completely optimize away the check groups_per_flex == 0, leaving the
    patched code as vulnerable as the original.  GCC keeps the check, but
    there is no guarantee that future versions will do the same.
    Signed-off-by: NXi Wang <xi.wang@gmail.com>
    Signed-off-by: N"Theodore Ts'o" <tytso@mit.edu>
    Cc: stable@vger.kernel.org
    d50f2ab6
super.c 141.8 KB