target-i386: Mask NX bit from cpu_get_phys_page_debug result
PATCH 1/1 target-i386: Mask NX bit from cpu_get_phys_page_debug result
This was a long pending bug, now revealed by the assert in phys_page_find that stumbled over the large page index returned by cpu_get_phys_page_debug for NX-marked pages.
---
Was easily triggerable by attaching gdb to the guest and doing some backtraces that reached into stack addresses.
target-i386/helper.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
target-i386/helper.c +1 -1
@@ -947,7 +947,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) } page_offset = (addr &TARGET_PAGE_MASK ) & (page_size -1 ); - paddr = (pte &TARGET_PAGE_MASK ) + page_offset; + paddr = (pte &TARGET_PAGE_MASK & ~PG_NX_MASK ) + page_offset;return paddr; }
Signature · 1 line
1.7.3.4
Quoted 18 lines · Jan Kiszka
This was a long pending bug, now revealed by the assert in
phys_page_findthat stumbled over the large page index returned bycpu_get_phys_page_debugfor NX-marked pages.Signed-off-by Jan Kiszka <[email protected]>---
Was easily triggerable by attaching gdb to the guest and doing some backtraces that reached into stack addresses.
target-i386/helper.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)target-i386/helper.c +0
-0
target-i386/helper.c target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) · line 953
Quoted 8 lines
target-i386/helper.c +1
-1@@ -947,7 +947,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) } page_offset = (addr &TARGET_PAGE_MASK ) & (page_size -1 ); - paddr = (pte &TARGET_PAGE_MASK ) + page_offset; + paddr = (pte &TARGET_PAGE_MASK & ~PG_NX_MASK ) + page_offset;return paddr; }
Should we not, in addition, mask the software available bits (53-62 IIRC)?
Signature · 1 line
error compiling committee.c: too many arguments to function
Quoted 7 lines · Avi Kivity
Quoted 7 lines
target-i386/helper.c +0
-0@@ -947,7 +947,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) }
Quoted 9 lines
target-i386/helper.c target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) · line 953
Quoted 6 lines
target-i386/helper.c +1
-1page_offset = (addr &TARGET_PAGE_MASK ) & (page_size -1 ); - paddr = (pte &TARGET_PAGE_MASK ) + page_offset; + paddr = (pte &TARGET_PAGE_MASK & ~PG_NX_MASK ) + page_offset;return paddr; }Should we not, in addition, mask the software available bits (53-62 IIRC)?
Also intermediate PTEs want this treatment, not just the last one.
Signature · 1 line
error compiling committee.c: too many arguments to function
PATCH v2 1/1 target-i386: Mask NX bit from cpu_get_phys_page_debug result
This was a long pending bug, now revealed by the assert in phys_page_find that stumbled over the large page index returned by cpu_get_phys_page_debug for NX-marked pages: We need to mask out NX and all user-definable bits 52..62 from PDEs and the final PTE to avoid corrupting physical addresses.
---
Changes in v2 (as suggested by Avi):
- Mask PDEs as well
- Mask user-definable bits
target-i386/cpu.h | 1 + target-i386/helper.c | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-)
target-i386/cpu.h +1 -0
@@ -241,6 +241,7 @@#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT)#define PG_PSE_MASK (1 << PG_PSE_BIT)#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT) +#define PG_HI_USER_MASK 0x7ff0000000000000LL#define PG_NX_MASK (1LL << PG_NX_BIT)#define PG_ERROR_W_BIT 1
target-i386/helper.c +7 -6
@@ -885,8 +885,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)if (!(pml4e &PG_PRESENT_MASK ))return -1 ; - pdpe_addr = ((pml4e & ~0xfff ) + (((addr >>30 ) &0x1ff ) <<3 )) & - env->a20_mask; + pdpe_addr = ((pml4e & ~0xfff & ~(PG_NX_MASK |PG_HI_USER_MASK )) + + (((addr >>30 ) &0x1ff ) <<3 )) & env->a20_mask; pdpe =ldq_phys (pdpe_addr);if (!(pdpe &PG_PRESENT_MASK ))return -1 ;
@@ -900,8 +900,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)return -1 ; } - pde_addr = ((pdpe & ~0xfff ) + (((addr >>21 ) &0x1ff ) <<3 )) & - env->a20_mask; + pde_addr = ((pdpe & ~0xfff & ~(PG_NX_MASK |PG_HI_USER_MASK )) + + (((addr >>21 ) &0x1ff ) <<3 )) & env->a20_mask; pde =ldq_phys (pde_addr);if (!(pde &PG_PRESENT_MASK )) {return -1 ;
@@ -912,11 +912,12 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) pte = pde & ~( (page_size -1 ) & ~0xfff );/* align to page_size */ }else {/* 4 KB page */ - pte_addr = ((pde & ~0xfff ) + (((addr >>12 ) &0x1ff ) <<3 )) & - env->a20_mask; + pte_addr = ((pde & ~0xfff & ~(PG_NX_MASK |PG_HI_USER_MASK )) + + (((addr >>12 ) &0x1ff ) <<3 )) & env->a20_mask; page_size =4096 ; pte =ldq_phys (pte_addr); } + pte &= ~(PG_NX_MASK |PG_HI_USER_MASK );if (!(pte &PG_PRESENT_MASK ))return -1 ; }else {
Signature · 1 line
1.7.3.4
Quoted 7 lines · Jan Kiszka
This was a long pending bug, now revealed by the assert in
phys_page_findthat stumbled over the large page index returned bycpu_get_phys_page_debugfor NX-marked pages: We need to mask out NX and all user-definable bits 52..62 from PDEs and the final PTE to avoid corrupting physical addresses.
Signature · 1 line
error compiling committee.c: too many arguments to function
Blue Swirl
AppliedThanks, applied.
Quoted 72 lines · Jan Kiszka
This was a long pending bug, now revealed by the assert in
phys_page_findthat stumbled over the large page index returned bycpu_get_phys_page_debugfor NX-marked pages: We need to mask out NX and all user-definable bits 52..62 from PDEs and the final PTE to avoid corrupting physical addresses.Signed-off-by Jan Kiszka <[email protected]>---
Changes in v2 (as suggested by Avi):
- Mask PDEs as well
- Mask user-definable bitstarget-i386/cpu.h | 1 +
target-i386/helper.c | 13 +++++++------2 files changed, 8 insertions(+), 6 deletions(-)target-i386/cpu.h +1
-0@@ -241,6 +241,7 @@ #define PG_DIRTY_MASK (1 << PG_DIRTY_BIT) #define PG_PSE_MASK (1 << PG_PSE_BIT) #define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT) +#define PG_HI_USER_MASK 0x7ff0000000000000LL #define PG_NX_MASK (1LL << PG_NX_BIT) #define PG_ERROR_W_BIT 1target-i386/helper.c +4
-4@@ -885,8 +885,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) if (!(pml4e & PG_PRESENT_MASK)) return -1; - pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & - env->a20_mask; + pdpe_addr = ((pml4e & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) + + (((addr >> 30) & 0x1ff) << 3)) & env->a20_mask; pdpe = ldq_phys(pdpe_addr); if (!(pdpe & PG_PRESENT_MASK)) return -1;@@ -900,8 +900,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) return -1; } - pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) & - env->a20_mask; + pde_addr = ((pdpe & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) + + (((addr >> 21) & 0x1ff) << 3)) & env->a20_mask; pde = ldq_phys(pde_addr); if (!(pde & PG_PRESENT_MASK)) { return -1;@@ -912,11 +912,12 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)pte = pde & ~( (
page_size- 1) & ~0xfff); /* align topage_size*/ } else {
/* 4 KB page */
- pte_addr = ((pde & ~0xfff) + (((addr >> 12) &0x1ff) << 3)) &
- env->a20_mask;
+ pte_addr = ((pde & ~0xfff & ~(PG_NX_MASK |PG_HI_USER_MASK)) +
+ (((addr >> 12) &0x1ff) << 3)) &env->a20_mask;page_size= 4096;
pte =ldq_phys(pte_addr);
}
+ pte &= ~(PG_NX_MASK |PG_HI_USER_MASK);
if (!(pte &PG_PRESENT_MASK))
return -1;
} else {
--
1.7.3.4