[LTP] [linux-next:master] [mm/mremap] d9339d9c10: ltp.mseal01.fail

Lorenzo Stoakes lorenzo.stoakes@oracle.com
Sun Jul 20 12:31:55 CEST 2025


TL; DR - there's undocumented mremap() behaviour on shrink that I accidentally
regressed. I will fix this (easy fix), document and add a self-test.

On Sun, Jul 20, 2025 at 04:30:52PM +0800, kernel test robot wrote:
>
>
> Hello,
>
> kernel test robot noticed "ltp.mseal01.fail" on:

OK, so I've looked into this, and it seems there's some undocumented mremap()
shrink behaviour even I wasn't aware of.

In mseal01.c, when you establish the mseal, you do it offset into the mapped VMA:

static void run(unsigned int n)
{
	...

		mem_addr = SAFE_MMAP(NULL, mem_size,
			tc->prot,
			MAP_ANONYMOUS | MAP_PRIVATE,
			-1, 0);

		...

		TST_EXP_PASS(sys_mseal(mem_addr + mem_offset, mem_alignment));
	...
}

This is splitting the originally mapped VMA to insert an mseal()'d region within
it:

	|------------------------|
	|            A           |
	|------------------------|

Becomes:

	 mem_offset
        <---------->
	|----------|---|---------|
	|    B     | C |    D    |
	|----------|---|---------|

You then try to mremap() and shrink B, C, and D in test_mremap_resize():

static void test_mremap_resize(void)
{
	void *new_addr;
	size_t new_size = 2 * mem_alignment;

	new_addr = SAFE_MMAP(NULL, mem_size,
		PROT_READ,
		MAP_ANONYMOUS | MAP_PRIVATE,
		-1, 0);

	TST_EXP_FAIL_PTR_VOID(mremap(mem_addr, mem_size, new_size,
		MREMAP_MAYMOVE | MREMAP_FIXED,
		new_addr),
		EPERM);

	...
}

(Note that in testing, I've found mem_size == 0x8000 and mem_alignment == 0x1000
so this is a shrink, also mem_offset == 0x2000).

So in ALL OTHER CASES you can't span multiple VMAs, let alone with gaps. But on
shrink hey you can!

So the operation becomes:

	           <- unmap this->
	|----------|---|---------|
	|    B     | C |    D    |
	|----------|---|---------|

	< move this>
	|----------|
	|    B     |
	|----------|

Obviously with C mseal()'d the unmap fails and we get the expected -EPERM fail.

The commit bisected to disallows an MREMAP_FIXED that spans multiple VMAs, which
makes the logic consistent with _every other operation_.

The manpage also appears to contradict this behaviour. So it's understandable
this was overlooked.

The fix is quick, will send shortly. It will be folded into existing series so
unfortunately can't apply tags as per below.

Thanks, Lorenzo

>
> commit: d9339d9c10d2452ae4d0087a3127359de6c2ed0e ("mm/mremap: check remap conditions earlier")
> https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git master
>
> [test failed on linux-next/master d086c886ceb9f59dea6c3a9dae7eb89e780a20c9]
>
> in testcase: ltp
> version: ltp-x86_64-a5dad8bc3-1_20250712
> with following parameters:
>
> 	disk: 1HDD
> 	fs: xfs
> 	test: syscalls-02/mseal01
>
>
>
> config: x86_64-rhel-9.4-ltp
> compiler: gcc-12
> test machine: 8 threads Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz (Skylake) with 16G memory
>
> (please refer to attached dmesg/kmsg for entire log/backtrace)
>
>
>
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <oliver.sang@intel.com>
> | Closes: https://lore.kernel.org/oe-lkp/202507201002.69144b74-lkp@intel.com
>
>
> Running tests.......
> <<<test_start>>>
> tag=mseal01 stime=1752886519
> cmdline="mseal01"
> contacts=""
> analysis=exit
> <<<test_output>>>
> tst_test.c:1999: TINFO: LTP version: 20250530-76-ga5dad8bc3
> tst_test.c:2002: TINFO: Tested kernel: 6.16.0-rc5-00302-gd9339d9c10d2 #1 SMP PREEMPT_DYNAMIC Sat Jul 19 08:39:24 CST 2025 x86_64
> tst_kconfig.c:88: TINFO: Parsing kernel config '/proc/config.gz'
> tst_kconfig.c:676: TINFO: CONFIG_KASAN kernel option detected which might slow the execution
> tst_test.c:1820: TINFO: Overall timeout per run is 0h 10m 00s
> mseal01.c:130: TINFO: Testing mprotect() availability
> mseal01.c:132: TPASS: sys_mseal(mem_addr + mem_offset, mem_alignment) passed
> mseal01.c:45: TPASS: mprotect(mem_addr, mem_size, PROT_NONE) : EPERM (1)
> mseal01.c:130: TINFO: Testing pkey_mprotect() availability
> mseal01.c:132: TPASS: sys_mseal(mem_addr + mem_offset, mem_alignment) passed
> ../../../../include/lapi/pkey.h:49: TCONF: pku is not supported on this CPU
> mseal01.c:130: TINFO: Testing madvise() availability
> mseal01.c:132: TPASS: sys_mseal(mem_addr + mem_offset, mem_alignment) passed
> mseal01.c:70: TPASS: madvise(mem_addr, mem_size, MADV_DONTNEED) : EPERM (1)
> mseal01.c:130: TINFO: Testing munmap() availability from child
> mseal01.c:132: TPASS: sys_mseal(mem_addr + mem_offset, mem_alignment) passed
> mseal01.c:75: TPASS: munmap(mem_addr, mem_size) : EPERM (1)
> mseal01.c:130: TINFO: Testing mremap() address move/resize
> mseal01.c:132: TPASS: sys_mseal(mem_addr + mem_offset, mem_alignment) passed
> mseal01.c:88: TFAIL: mremap(mem_addr, mem_size, new_size, MREMAP_MAYMOVE | MREMAP_FIXED, new_addr) expected EPERM: EFAULT (14)
> mseal01.c:130: TINFO: Testing mmap() protection change
> mseal01.c:132: TPASS: sys_mseal(mem_addr + mem_offset, mem_alignment) passed
> mseal01.c:98: TPASS: mmap(mem_addr, mem_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0) : EPERM (1)
>
> Summary:
> passed   10
> failed   1
> broken   0
> skipped  1
> warnings 0
> incrementing stop
> <<<execution_status>>>
> initiation_status="ok"
> duration=0 termination_type=exited termination_id=1 corefile=no
> cutime=0 cstime=1
> <<<test_end>>>
> INFO: ltp-pan reported some tests FAIL
> LTP Version: 20250530-76-ga5dad8bc3
>
>        ###############################################################
>
>             Done executing testcases.
>             LTP Version:  20250530-76-ga5dad8bc3
>        ###############################################################
>
>
>
>
> The kernel config and materials to reproduce are available at:
> https://download.01.org/0day-ci/archive/20250720/202507201002.69144b74-lkp@intel.com
>
>
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki
>


More information about the ltp mailing list