for (msr = __readmsr(MSR_MTRRfix64K_00000), offset = 0x10000, base = 0;
msr != 0; msr >>= 8, base += offset)
make_mtrr_range(&ranges[idx++], true, msr & 0xff, base, base + 0x10000);
for (val = MSR_MTRRfix16K_80000, offset = 0x4000; val <= MSR_MTRRfix16K_A0000; ++val)
for (msr = __readmsr(val), base = 0x80000;
msr != 0; msr >>= 8, base += offset)
make_mtrr_range(&ranges[idx++], true, msr & 0xff, base, base + 0x4000);
for (val = MSR_MTRRfix4K_C0000, offset = 0x1000; val <= MSR_MTRRfix4K_F8000; ++val)
for (msr = __readmsr(val), base = 0xC0000;
msr != 0; msr >>= 8, base += offset)
make_mtrr_range(&ranges[idx++], true, msr & 0xff, base, base + 0x1000);
Here's the problem: for each fixed MTRR, there are actually 8 subranges.
Intel manual says:
11.11.2.2 Fixed Range MTRRs
The fixed memory ranges are mapped with 11 fixed-range registers of 64 bits each. Each of these registers is
divided into 8-bit fields that are used to specify the memory type for each of the sub-ranges the register controls:
• Register IA32_MTRR_FIX64K_00000 — Maps the 512-KByte address range from 0H to 7FFFFH. This range
is divided into eight 64-KByte sub-ranges.
• Registers IA32_MTRR_FIX16K_80000 and IA32_MTRR_FIX16K_A0000 — Maps the two 128-KByte
address ranges from 80000H to BFFFFH. This range is divided into sixteen 16-KByte sub-ranges, 8 ranges per
register.
• Registers IA32_MTRR_FIX4K_C0000 through IA32_MTRR_FIX4K_F8000 — Maps eight 32-KByte
address ranges from C0000H to FFFFFH. This range is divided into sixty-four 4-KByte sub-ranges, 8 ranges per
register.
Expected Behavior
I think fix is as simple as defining MAX_FIXED_MTRR to 11*8.
Type of this issue (please specify)
Issue description
mtrr_ranges array has wrong size and may eventually overflow if user gets really REALLY unlucky
Current Behavior
Let's deconstruct this issue: in ksm.h:
struct mtrr_range mtrr_ranges[MAX_MTRR];
in mm.h:
in ksm.c:
in mm.c:
Here's the problem: for each fixed MTRR, there are actually 8 subranges. Intel manual says:
Expected Behavior
I think fix is as simple as defining MAX_FIXED_MTRR to 11*8.
Inline code / patches to be used when reproducing