Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 06c03cac authored by Lennert Buytenhek's avatar Lennert Buytenhek Committed by Russell King
Browse files

[ARM] 3117/1: nwfpe kernel memory info leak



Patch from Lennert Buytenhek

The routine that nwfpe uses for converting floats/doubles to
extended precision fails to zero two bytes of kernel stack.  This
is not immediately obvious, as the floatx80 structure has 16 bits
of implicit padding (by design.)  These two bytes are copied to
userspace when an stfe is emulated, causing a possible info leak.

Make the padding explicit and zero it out in the relevant places.

Signed-off-by: default avatarLennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 862184fe
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -29,14 +29,14 @@

#ifdef CONFIG_FPE_NWFPE_XP
const floatx80 floatx80Constant[] = {
	{0x0000, 0x0000000000000000ULL},	/* extended 0.0 */
	{0x3fff, 0x8000000000000000ULL},	/* extended 1.0 */
	{0x4000, 0x8000000000000000ULL},	/* extended 2.0 */
	{0x4000, 0xc000000000000000ULL},	/* extended 3.0 */
	{0x4001, 0x8000000000000000ULL},	/* extended 4.0 */
	{0x4001, 0xa000000000000000ULL},	/* extended 5.0 */
	{0x3ffe, 0x8000000000000000ULL},	/* extended 0.5 */
	{0x4002, 0xa000000000000000ULL}		/* extended 10.0 */
	{ .high = 0x0000, .low = 0x0000000000000000ULL},/* extended 0.0 */
	{ .high = 0x3fff, .low = 0x8000000000000000ULL},/* extended 1.0 */
	{ .high = 0x4000, .low = 0x8000000000000000ULL},/* extended 2.0 */
	{ .high = 0x4000, .low = 0xc000000000000000ULL},/* extended 3.0 */
	{ .high = 0x4001, .low = 0x8000000000000000ULL},/* extended 4.0 */
	{ .high = 0x4001, .low = 0xa000000000000000ULL},/* extended 5.0 */
	{ .high = 0x3ffe, .low = 0x8000000000000000ULL},/* extended 0.5 */
	{ .high = 0x4002, .low = 0xa000000000000000ULL},/* extended 10.0 */
};
#endif

+1 −0
Original line number Diff line number Diff line
@@ -332,6 +332,7 @@ static floatx80 commonNaNToFloatx80( commonNaNT a )

    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
    z.__padding = 0;
    return z;

}
+6 −0
Original line number Diff line number Diff line
@@ -531,6 +531,7 @@ INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig )

    z.low = zSig;
    z.high = ( ( (bits16) zSign )<<15 ) + zExp;
    z.__padding = 0;
    return z;

}
@@ -2831,6 +2832,7 @@ static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, flo
        roundData->exception |= float_flag_invalid;
        z.low = floatx80_default_nan_low;
        z.high = floatx80_default_nan_high;
        z.__padding = 0;
        return z;
    }
    if ( aExp == 0 ) {
@@ -2950,6 +2952,7 @@ floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b )
            roundData->exception |= float_flag_invalid;
            z.low = floatx80_default_nan_low;
            z.high = floatx80_default_nan_high;
            z.__padding = 0;
            return z;
        }
        return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
@@ -3015,6 +3018,7 @@ floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b )
                roundData->exception |= float_flag_invalid;
                z.low = floatx80_default_nan_low;
                z.high = floatx80_default_nan_high;
                z.__padding = 0;
                return z;
            }
            roundData->exception |= float_flag_divbyzero;
@@ -3093,6 +3097,7 @@ floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b )
            roundData->exception |= float_flag_invalid;
            z.low = floatx80_default_nan_low;
            z.high = floatx80_default_nan_high;
            z.__padding = 0;
            return z;
        }
        normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
@@ -3184,6 +3189,7 @@ floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a )
        roundData->exception |= float_flag_invalid;
        z.low = floatx80_default_nan_low;
        z.high = floatx80_default_nan_high;
        z.__padding = 0;
        return z;
    }
    if ( aExp == 0 ) {
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ typedef unsigned long int float32;
typedef unsigned long long float64;
typedef struct {
    unsigned short high;
    unsigned short __padding;
    unsigned long long low;
} floatx80;