mmap()返回意外EPERM错误而非预期EOPNOTSUPP问题排查
Let me break down this issue and walk through what might be happening here.
First, let's recap your scenario: you're running a test on Debian 4.19 where you're calling mmap() with flags outside the LEGACY_MAP_MASK (specifically combining ~legacy_flags with MAP_SHARED_VALIDATE). According to your expectations, this should trigger an EOPNOTSUPP error, but instead you're getting EPERM (Error 1).
Your Test Code
#define TEST_FILE "file_to_mmap" #define TEST_FILE_SIZE 1024 #define TEST_FILE_MODE 0600 unsigned long legacy_flags; unsigned long map_flags; int fd_file; void *mapped_address; fd_file = open(TEST_FILE, O_CREAT | O_RDWR, TEST_FILE_MODE); legacy_flags = LEGACY_MAP_MASK; map_flags = ~(legacy_flags) + MAP_SHARED_VALIDATE; mapped_address = mmap(NULL, TEST_FILE_SIZE, PROT_READ | PROT_WRITE, map_flags, fd_file, 0); if (errno == EOPNOTSUPP) printf("Have a nice day");
Error & System Info
Error message: mmap( ) failed with the unexpected error: EPERM (1)
System info:uname -aoutput → Linux debian 4.19.0-10-amd64 #1 SMP Debian 4.19.132-1 (2020-07-24) x86_64 GNU/Linux
What's Likely Going On
The key here is the behavior of the 4.19 Linux kernel, especially around the MAP_SHARED_VALIDATE flag and error code handling:
MAP_SHARED_VALIDATEBackground: This flag was introduced in Linux 4.15, but support isn't universal across all file systems. In older kernels like 4.19, the error handling for unsupported flags isn't always consistent with newer kernel versions.- Error Code Priority: In some code paths of the 4.19 kernel, when
MAP_SHARED_VALIDATEis used on a file system that doesn't support it (like standard ext4, common on Debian), the kernel may returnEPERMinstead ofEOPNOTSUPP. This happens because the kernel checks for certain permissions or feature support before reaching the code path that would emitEOPNOTSUPP. LEGACY_MAP_MASKCalculation: Your~(legacy_flags) + MAP_SHARED_VALIDATEmight be including other non-legacy flags besidesMAP_SHARED_VALIDATE, which could trigger permission checks that result inEPERMbefore the kernel evaluates flag support.
Steps to Verify & Debug
- Check
LEGACY_MAP_MASKDefinition: Rungrep LEGACY_MAP_MASK /usr/include/linux/mman.hto see exactly which flags are included in the legacy mask. This confirms that~legacy_flagstargets non-legacy flags correctly. - Isolate
MAP_SHARED_VALIDATE: Test using onlyMAP_SHARED_VALIDATE(without combining with~legacy_flags) to see if you still getEPERM. This tells you if the issue is specific to this flag or the combination. - Try a Different File System: Test the same code on a tmpfs mount (which often has better support for newer mmap flags). If you get
EOPNOTSUPPthere, it confirms the issue is file system-dependent in the 4.19 kernel.
Conclusion
This appears to be a behavior quirk in the 4.19 Linux kernel. Newer kernel versions (5.x+) have updated error handling for unsupported mmap flags and would likely return EOPNOTSUPP as you expect. For Debian 4.19, you'll need to account for EPERM as a possible error when using MAP_SHARED_VALIDATE on unsupported file systems.
内容的提问来源于stack exchange,提问作者Paul

