arm64 fixes for -rc6
- Fix kernel oops when attemping kexec_file() with a NULL cmdline - Fix page table output in debugfs when CONFIG_ARM64_USER_VA_BITS_52=y -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEPxTL6PPUbjXGY88ct6xw3ITBYzQFAlxdeK4ACgkQt6xw3ITB YzTwrwgArV1AHQTG6HG0Xz86zNbjA25XHr1HFTl75Q7SRu8lufxUXJ/JbIfE5v/v D/a40PDsWQeXMHvZT0C/DyByfbfSSigLAwS/psZxmjT5KDgfQCor01UjtWvh+DS+ U7DnXjLxJFZZ13dJmMPGn3JGmNB5VoKv6w3+9f2rZgECZXdVBQzGPopmjhjmVx5/ ncGLF4ecxQ1+ldIGGTIC5NSYsFPyhcKxYRlQ/sT/d5oN3wIJNixj7yL14jzx3izG OEsu967q3Ajn5lMs2j3k1ixopeOLWYOsSB27oWczJ/XAB4EGU9bbuHOz4alDpE5X oDIFuJGrD6s6Ba5E62XtHfp62Iy5pg== =UCO2 -----END PGP SIGNATURE----- Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux Pull arm64 fixes from Will Deacon: "Two arm64 fixes for -rc6. They resolve a kernel NULL dereference in kexec and bogus kernel page table dumping when userspace is configured for 52-bit virtual addressing. Summary: - Fix kernel oops when attemping kexec_file() with a NULL cmdline - Fix page table output in debugfs when ARM64_USER_VA_BITS_52=y" * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64: kexec_file: handle empty command-line arm64: ptdump: Don't iterate kernel page tables using PTRS_PER_PXX
This commit is contained in:
commit
5bb513ed83
|
@ -120,10 +120,12 @@ static int create_dtb(struct kimage *image,
|
|||
{
|
||||
void *buf;
|
||||
size_t buf_size;
|
||||
size_t cmdline_len;
|
||||
int ret;
|
||||
|
||||
cmdline_len = cmdline ? strlen(cmdline) : 0;
|
||||
buf_size = fdt_totalsize(initial_boot_params)
|
||||
+ strlen(cmdline) + DTB_EXTRA_SPACE;
|
||||
+ cmdline_len + DTB_EXTRA_SPACE;
|
||||
|
||||
for (;;) {
|
||||
buf = vmalloc(buf_size);
|
||||
|
|
|
@ -286,74 +286,73 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
|
|||
|
||||
}
|
||||
|
||||
static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start)
|
||||
static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
pte_t *ptep = pte_offset_kernel(pmdp, 0UL);
|
||||
unsigned long addr;
|
||||
unsigned i;
|
||||
unsigned long addr = start;
|
||||
pte_t *ptep = pte_offset_kernel(pmdp, start);
|
||||
|
||||
for (i = 0; i < PTRS_PER_PTE; i++, ptep++) {
|
||||
addr = start + i * PAGE_SIZE;
|
||||
do {
|
||||
note_page(st, addr, 4, READ_ONCE(pte_val(*ptep)));
|
||||
}
|
||||
} while (ptep++, addr += PAGE_SIZE, addr != end);
|
||||
}
|
||||
|
||||
static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start)
|
||||
static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
pmd_t *pmdp = pmd_offset(pudp, 0UL);
|
||||
unsigned long addr;
|
||||
unsigned i;
|
||||
unsigned long next, addr = start;
|
||||
pmd_t *pmdp = pmd_offset(pudp, start);
|
||||
|
||||
for (i = 0; i < PTRS_PER_PMD; i++, pmdp++) {
|
||||
do {
|
||||
pmd_t pmd = READ_ONCE(*pmdp);
|
||||
next = pmd_addr_end(addr, end);
|
||||
|
||||
addr = start + i * PMD_SIZE;
|
||||
if (pmd_none(pmd) || pmd_sect(pmd)) {
|
||||
note_page(st, addr, 3, pmd_val(pmd));
|
||||
} else {
|
||||
BUG_ON(pmd_bad(pmd));
|
||||
walk_pte(st, pmdp, addr);
|
||||
walk_pte(st, pmdp, addr, next);
|
||||
}
|
||||
}
|
||||
} while (pmdp++, addr = next, addr != end);
|
||||
}
|
||||
|
||||
static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start)
|
||||
static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
pud_t *pudp = pud_offset(pgdp, 0UL);
|
||||
unsigned long addr;
|
||||
unsigned i;
|
||||
unsigned long next, addr = start;
|
||||
pud_t *pudp = pud_offset(pgdp, start);
|
||||
|
||||
for (i = 0; i < PTRS_PER_PUD; i++, pudp++) {
|
||||
do {
|
||||
pud_t pud = READ_ONCE(*pudp);
|
||||
next = pud_addr_end(addr, end);
|
||||
|
||||
addr = start + i * PUD_SIZE;
|
||||
if (pud_none(pud) || pud_sect(pud)) {
|
||||
note_page(st, addr, 2, pud_val(pud));
|
||||
} else {
|
||||
BUG_ON(pud_bad(pud));
|
||||
walk_pmd(st, pudp, addr);
|
||||
walk_pmd(st, pudp, addr, next);
|
||||
}
|
||||
}
|
||||
} while (pudp++, addr = next, addr != end);
|
||||
}
|
||||
|
||||
static void walk_pgd(struct pg_state *st, struct mm_struct *mm,
|
||||
unsigned long start)
|
||||
{
|
||||
pgd_t *pgdp = pgd_offset(mm, 0UL);
|
||||
unsigned i;
|
||||
unsigned long addr;
|
||||
unsigned long end = (start < TASK_SIZE_64) ? TASK_SIZE_64 : 0;
|
||||
unsigned long next, addr = start;
|
||||
pgd_t *pgdp = pgd_offset(mm, start);
|
||||
|
||||
for (i = 0; i < PTRS_PER_PGD; i++, pgdp++) {
|
||||
do {
|
||||
pgd_t pgd = READ_ONCE(*pgdp);
|
||||
next = pgd_addr_end(addr, end);
|
||||
|
||||
addr = start + i * PGDIR_SIZE;
|
||||
if (pgd_none(pgd)) {
|
||||
note_page(st, addr, 1, pgd_val(pgd));
|
||||
} else {
|
||||
BUG_ON(pgd_bad(pgd));
|
||||
walk_pud(st, pgdp, addr);
|
||||
walk_pud(st, pgdp, addr, next);
|
||||
}
|
||||
}
|
||||
} while (pgdp++, addr = next, addr != end);
|
||||
}
|
||||
|
||||
void ptdump_walk_pgd(struct seq_file *m, struct ptdump_info *info)
|
||||
|
|
Loading…
Reference in New Issue