zpoline nommu - #1
Conversation
9b86626 to
a754e79
Compare
a754e79 to
109311b
Compare
90042db to
3496039
Compare
3e8124f to
ddc2ef9
Compare
|
for the record: lmbench (usec)
do_getpid bench (nsec)
|
d53d51a to
3e28856
Compare
sometimes fs register is referenced before __kernel_vsyscall, resulitng an invalid access as it's on different value. this commit fixes this issue. Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
WIP/FIXME Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
…nd_for_mapping() ramfs_nommu_expand_for_mapping() sets the new i_size before it has allocated or inserted any of the contiguous backing pages. If alloc_pages() or add_to_page_cache_lru() fails, the inode is left with an inflated i_size and possibly a partial run of pages. As ramfs_nommu_setattr() treats a truncate to the current i_size as a no-op, the expansion cannot be retried and shared mmap() of the file fails with -ENOSYS. Setting i_size early also races with lockless readers: buffered reads and splice do not take i_rwsem, so once the new size is visible a concurrent read can instantiate a zero-filled folio, making the expansion's add_to_page_cache_lru() fail with -EEXIST. Fix this by taking mapping->invalidate_lock around the insertion, evicting any stray folios first, and only publishing i_size once every page is in place. On failure, after freeing the pages that were allocated but not inserted truncate the mapping back to empty so already inserted pages are also disposed of. Fixes: 642fb4d ("[PATCH] NOMMU: Provide shared-writable mmap support on ramfs") Reported-by: Sashiko <sashiko-bot@kernel.org> Closes: https://sashiko.dev/#/message/20260523130445.1101818-1-daniel%40thingy.jp Assisted-by: Claude:claude-5-fable # expanded my fix to address the reader race etc. Signed-off-by: Daniel Palmer <daniel@thingy.jp>
Currently trying to use memfd_create() on nommu returns an error with errno set to EFBIG. The manpage memfd_create() doesn't have EFBIG as a possible error value. Doing some digging this is coming from 0 getting passed as newsize to ramfs_nommu_expand_for_mapping() and that getting into get_order() and there "The result is undefined if the size is 0". Whatever comes out of get_order() is then used in the following logic and that results in the EFBIG that causes the syscall to fail and the errno in userspace. If newsize is 0 there is nothing to do so just return. Roughly tested on m68k nommu by creating a process, creating an memfd, forking another process, mmap()ing the memfd in the child, writing into the mapping, then mmap()ing in the parent and checking that the right data is there. Signed-off-by: Daniel Palmer <daniel@thingy.jp> Acked-by: Lorenzo Stoakes <ljs@kernel.org>
lmbench (usec)
do_getpid bench (nsec)
iperf3 bench (Mbps)
netperf bench (TCP_STREAM) (Mbps)
netperf bench (TCP_MAERTS) (Mbps)
LTP results
native report: https://github.com/thehajime/linux/actions/runs/31557789951/artifacts/9127779054 |
lmbench (usec)
do_getpid bench (nsec)
iperf3 bench (Mbps)
netperf bench (TCP_STREAM) (Mbps)
netperf bench (TCP_MAERTS) (Mbps)
LTP results
native report: https://github.com/thehajime/linux/actions/runs/31656195135/artifacts/9165723601 |
Upon a private file mapping request to /dev/zero, it calls kernel_read() in do_mmap_private(), getting a failure with the message like: "kernel reads not supported for file /dev/zero", which is because zero_fops defined in drivers/char/mem.c has both .read and .read_iter definitions. Even fixing this issue, the map request to /dev/zero works fine without errors but the allocated vma isn't marked with anonymous because mmap_zero_prepare() isn't called under nommu platform, resulting vma_desc_set_anonymous() isn't called either. This commit fixes those issues by: 1) use vfs_iter_read() instead to avoid failure at kernel_read() 2) calls .mmap_prepare on private mapping in do_mmap() so that required preparations are done even in private mapping. Cc: Arnd Bergmann <arnd@arndb.de> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org> Cc: Jan Kara <jack@suse.cz> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: "Liam R. Howlett" <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Jann Horn <jannh@google.com> Cc: Pedro Falcato <pfalcato@suse.de> Cc: linux-fsdevel@vger.kernel.org Cc: linux-mm@kvack.org (open list:PAGE CACHE) Fixes: 4d03e3c ("fs: don't allow kernel reads and writes without iter ops") Assisted-by: cubic.dev:unspecified Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
When shrinking a VMA via mremap, the bounds are modified directly:
mm/nommu.c:do_mremap() {
...
vma->vm_end = vma->vm_start + new_len;
...
}
This shrinks the VMA without updating its bounds in the maple tree.
If the maple tree (mm->mm_mt) still contains the old bounds, a user
process could access the freed portion. The stale maple tree would
incorrectly return the shrunk VMA for an address past its new vm_end.
This commit fixes this issue by calling vmi_shrink_vma() when shrink
happens. Additionally, if a file-backed, non-anonymous map is to be
shrunk, it reports -EINVAL like do_munmap() does.
Moreover, to maintain i_mmap interval tree, two functions,
add_vma_to_mapping() and remove_vma_from_mapping(), are decoupled from
setup_vma_to_mm() and cleanup_vma_from_mm() respectively.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: "Liam R. Howlett" <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Jann Horn <jannh@google.com>
Cc: Pedro Falcato <pfalcato@suse.de>
Cc: linux-mm@kvack.org
Closes: https://sashiko.dev/#/patchset/20260702012546.665383-1-thehajime@gmail.com
Closes: https://sashiko.dev/#/patchset/20260710021028.892645-1-thehajime%40gmail.com
Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
--
v1 -> v2:
- handle error when vmi_shrink_vma() failed (reported by Sashiko)
- prevents mremap() with being shrunk for file-backed one like munmap()
- consider i_mmap updates on shrink/expand by calling newly decoupled
functions, add_vma_to_mapping()/remove_vma_from_mapping()
v1: https://lore.kernel.org/linux-mm/20260710021028.892645-1-thehajime@gmail.com/
Then update split_vma() so both the old and newly created VMA remain covered by the same mapping lock:
For vmi_shrink_vma(), keep the mapping lock held through the Maple-tree operation and reinsert the VMA before releasing it:
And apply the same pattern to the growth branch:
response to sashiko review: This does not produce incorrect contents for /dev/zero, since reading /dev/zero also returns zeroes. However, private /dev/zero mappings are semantically anonymous, so the growth path now zero-fills them directly rather than performing unnecessary device I/O. Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Private file mappings (like those from /dev/zero) can have vma->vm_file set but remain structurally anonymous since they lack vm_ops. Testing vma->vm_file instead of vma_is_anonymous(vma) might cause mremap to return a spurious -EINVAL when userspace attempts to shrink these mappings. This commit fixes this issue by using vma_is_anonymous() instead of testing vma->vm_file to address the case of /dev/zero. Cc: Andrew Morton <akpm@linux-foundation.org> Cc: "Liam R. Howlett" <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Jann Horn <jannh@google.com> Cc: Pedro Falcato <pfalcato@suse.de> Cc: linux-mm@kvack.org Closes: https://sashiko.dev/#/patchset/20260710054648.924005-1-thehajime%40gmail.com Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Some nommu architectures only work on Alpine Linux, which doesn't use glibc for the standard library. It uses musl-libc and is implemented in a different way as glibc, resulting build failures. This commit fixes this issue by adding missing definitions. The fixes are now only covered to TARGETS=mm which was tested for the moment; future contributions are needed to fully build/execute tests on nommu platforms. Cc: Shuah Khan <shuah@kernel.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: David Hildenbrand <david@kernel.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: "Liam R. Howlett" <liam@infradead.org> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Mike Rapoport <rppt@kernel.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Michal Hocko <mhocko@suse.com> Cc: linux-kselftest@vger.kernel.org Cc: linux-mm@kvack.org Cc: linux-um@lists.infradead.org Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Architectures lacks MMU doesn't support fork(2) syscall and only vfork(2) is available with limitations. Thus, we cannot run kselftest on nommu architecture as is. This commit addresses this issue with the following changes: - on build stage, add -DCONFIG_NOMMU to CFLAGS when NOMMU=1 variable added to the build/make argument. - on test run stage, avoid calling timeout command when NOMMU=1 variable added to environmental variable, since timeout command uses fork syscall which nommu platform doesn't support. - kselftest_harness.h warns if the file is include when building for NOMMU platform, as there is no fork(2) syscall. - replace "cd -" use as it is not available a shell supported on nommu (e.g., busybox hush), use cd "$OLDDIR" instead. - describe the difference of nommu tests in the document. So command line to build/execute tests for nommu should be like below: $ make ARCH=um NOMMU=1 O=build kselftest $ make ARCH=um NOMMU=1 -C tools/testing/selftests/mm run_tests $ NOMMU=1 /tmp/kselftest_install/run_kselftest.sh -s -c mm Cc: Shuah Khan <shuah@kernel.org> Cc: Kees Cook <kees@kernel.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Will Drewry <wad@chromium.org> Cc: Mark Brown <broonie@kernel.org> Cc: Brendan Jackman <jackmanb@google.com> Cc: Hangbin Liu <liuhangbin@gmail.com> Cc: "Ricardo B. Marliere" <rbm@suse.com> Cc: linux-kselftest@vger.kernel.org Cc: linux-um@lists.infradead.org Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Introduce a kselftest utility to validate memory mapping capabilities under nommu kernels, aligned with Documentation/admin-guide/mm/nommu-mmap.rst. The test implements basic checks into a generic architecture-agnostic test matrix applicable across nommu targets. It evaluates: 1. MAP_FIXED allocation rejections. 2. Standard MAP_PRIVATE and MAP_ANONYMOUS allocation resilience. 3. MAP_UNINITIALIZED allocations via optional kernel configurations. 4. Regular file mappings via standard filesystem storage. 5. Memory-backed file mapping with /dev/zero 6. Block device subsystem mappings (gracefully skipping if node is missing). 7. Shared vs Private backing discrepancies under nommu conditions. 8. mremap limits, ensuring non-expandable restrictions behave properly. Cc: Andrew Morton <akpm@linux-foundation.org> Cc: David Hildenbrand <david@kernel.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: "Liam R. Howlett" <liam@infradead.org> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Mike Rapoport <rppt@kernel.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Michal Hocko <mhocko@suse.com> Cc: Shuah Khan <shuah@kernel.org> Cc: linux-kselftest@vger.kernel.org Cc: linux-mm@kvack.org Cc: linux-um@lists.infradead.org Assisted-by: Gemini:Pro [AI_Reviewer] [Sashiko_Linter] Assisted-by: cubic.dev:unspecified Signed-off-by: Hajime Tazaki <thehajime@gmail.com>







No description provided.