MIPS: Don't clear _PAGE_SPECIAL in _PAGE_CHG_MASK
authorHenry Willard <henry.willard@oracle.com>
Wed, 12 Apr 2023 21:29:53 +0000 (15:29 -0600)
committerThomas Bogendoerfer <tsbogend@alpha.franken.de>
Mon, 24 Apr 2023 07:48:51 +0000 (09:48 +0200)
commit1492c6b1874ac5ed57d8ffef89e2b5c59f804aa8
tree97e8b222bc88a2c0f929c483530b73bc5e63f6b5
parentf4670a1b30f886e843258ca4a69c442811a90302
MIPS: Don't clear _PAGE_SPECIAL in _PAGE_CHG_MASK

In the special case where

p = mmap(NULL, ALLOC_SIZE, PROT_READ,
                MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);

is followed by

rc = mprotect(p, ALLOC_SIZE, PROT_NONE);

the _PAGE_SPECIAL bit in the page tables will be cleared by
mistake and the later unmapped operations will incorrectly
modify the struct page for the the zero page. This sequence
occurs in the madvise05 test of the Linux Test Project
suite of tests.

This was discovered while testing an older version of the kernel
(5.4.17) on a MIPS device. Unfortunately, support for this device
is not available in newer kernels, so I can't test this with the
latest Linux kernel code. It looks like the problem exists in
newer kernels, but I can't verify it. Except for the LTP test,
this sequence of calls is probably not common.

Passing it along in the hope it will be useful to someone.

Signed-off-by: Henry Willard <henry.willard@oracle.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
arch/mips/include/asm/pgtable-bits.h