@@ -100,10 +100,7 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
pud_t *pud = pud_page + pud_index(addr);
pmd_t *pmd;
- next = (addr & PUD_MASK) + PUD_SIZE;
- if (next > end)
- next = end;
-
+ next = pud_addr_end(addr, end);
if (info->direct_gbpages) {
pud_t pudval;
@@ -141,10 +138,7 @@ static int ident_p4d_init(struct x86_mapping_info *info, p4d_t *p4d_page,
p4d_t *p4d = p4d_page + p4d_index(addr);
pud_t *pud;
- next = (addr & P4D_MASK) + P4D_SIZE;
- if (next > end)
- next = end;
-
+ next = p4d_addr_end(addr, end);
if (p4d_present(*p4d)) {
pud = pud_offset(p4d, 0);
result = ident_pud_init(info, pud, addr, next);
@@ -186,10 +180,7 @@ int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
pgd_t *pgd = pgd_page + pgd_index(addr);
p4d_t *p4d;
- next = (addr & PGDIR_MASK) + PGDIR_SIZE;
- if (next > end)
- next = end;
-
+ next = pgd_addr_end(addr, end);
if (pgd_present(*pgd)) {
p4d = p4d_offset(pgd, 0);
result = ident_p4d_init(info, p4d, addr, next);
Calculation of 'next' virtual address doesn't protect against wrapping to zero. It can result in page table corruption and hang. The problematic case is possible if user sets high x86_mapping_info::offset. Replace manual 'next' calculation with p?d_addr_and() which handles wrapping correctly. Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> --- arch/x86/mm/ident_map.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-)