The Linuxulator currently returns incorrect error codes when some file-descriptor based operations are attempted on an O_PATH descriptor. In particular, LTP open13 expects these operations to fail with EBADF, matching Linux behavior, but FreeBSD currently returns different errors: - mmap() on an O_PATH fd returns EACCES - fgetxattr() on an O_PATH fd returns EOPNOTSUPP The same issue also affects other fd-based xattr operations, which should follow the same O_PATH semantics for consistency: - fsetxattr() - fremovexattr() - flistxattr() This appears to be a Linux compatibility bug rather than a functional limitation. For mmap(), the Linuxulator does not currently reject path_fileops descriptors early with EBADF. For xattr operations, the code reaches the extattr path and returns the underlying FreeBSD error instead of recognizing that an O_PATH fd is not a valid data-access descriptor for these operations. This is addressed by https://github.com/freebsd/freebsd-src/pull/2181
Using the current FreeBSD 16.0 code, there are 4 failures of the LTP test case open13 $ /opt/ltp/testcases/bin/open13 tst_tmpdir.c:317: TINFO: Using /tmp/LTP_opeJ6gQkD as tmpdir (tmpfs filesystem) tst_test.c:2047: TINFO: LTP version: 20260130 tst_test.c:2050: TINFO: Tested kernel: 5.15.0 FreeBSD 16.0-CURRENT #2 main-n286042-28d85db46b48: Sun May 24 21 x86_64 tst_kconfig.c:71: TINFO: Couldn't locate kernel config! tst_test.c:1877: TINFO: Overall timeout per run is 0h 00m 30s open13.c:77: TPASS: read() on original FD : EBADF (9) open13.c:79: TPASS: read() on duplicated FD : EBADF (9) open13.c:77: TPASS: write() on original FD : EBADF (9) open13.c:79: TPASS: write() on duplicated FD : EBADF (9) open13.c:77: TPASS: fchmod() on original FD : EBADF (9) open13.c:79: TPASS: fchmod() on duplicated FD : EBADF (9) open13.c:77: TPASS: fchown() on original FD : EBADF (9) open13.c:79: TPASS: fchown() on duplicated FD : EBADF (9) open13.c:77: TPASS: ioctl() on original FD : EBADF (9) open13.c:79: TPASS: ioctl() on duplicated FD : EBADF (9) open13.c:77: TFAIL: mmap() on original FD expected EBADF: EACCES (13) open13.c:79: TFAIL: mmap() on duplicated FD expected EBADF: EACCES (13) open13.c:77: TFAIL: fgetxattr() on original FD expected EBADF: EOPNOTSUPP (95) open13.c:79: TFAIL: fgetxattr() on duplicated FD expected EBADF: EOPNOTSUPP (95) Summary: passed 10 failed 4 broken 0 skipped 0 warnings 0 And all passed after the fix $ /opt/ltp/testcases/bin/open13 tst_tmpdir.c:317: TINFO: Using /tmp/LTP_opeiIAOHE as tmpdir (tmpfs filesystem) tst_test.c:2047: TINFO: LTP version: 20260130 tst_test.c:2050: TINFO: Tested kernel: 5.15.0 FreeBSD 16.0-CURRENT #10 open13-fix-src-22b97fbf255b-dirty: Thu x86_64 tst_kconfig.c:71: TINFO: Couldn't locate kernel config! tst_test.c:1877: TINFO: Overall timeout per run is 0h 00m 30s open13.c:77: TPASS: read() on original FD : EBADF (9) open13.c:79: TPASS: read() on duplicated FD : EBADF (9) open13.c:77: TPASS: write() on original FD : EBADF (9) open13.c:79: TPASS: write() on duplicated FD : EBADF (9) open13.c:77: TPASS: fchmod() on original FD : EBADF (9) open13.c:79: TPASS: fchmod() on duplicated FD : EBADF (9) open13.c:77: TPASS: fchown() on original FD : EBADF (9) open13.c:79: TPASS: fchown() on duplicated FD : EBADF (9) open13.c:77: TPASS: ioctl() on original FD : EBADF (9) open13.c:79: TPASS: ioctl() on duplicated FD : EBADF (9) open13.c:77: TPASS: mmap() on original FD : EBADF (9) open13.c:79: TPASS: mmap() on duplicated FD : EBADF (9) open13.c:77: TPASS: fgetxattr() on original FD : EBADF (9) open13.c:79: TPASS: fgetxattr() on duplicated FD : EBADF (9) Summary: passed 14 failed 0 broken 0 skipped 0 warnings 0
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=2c905456312b2e5986afe3402a9c87d49eb9cf86 commit 2c905456312b2e5986afe3402a9c87d49eb9cf86 Author: YAO, Xin <mr.yaoxin@outlook.com> AuthorDate: 2026-05-07 06:39:16 +0000 Commit: Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org> CommitDate: 2026-07-01 08:38:05 +0000 linuxulator: Fix O_PATH file descriptors errno for f*xattr(2) LTP open13 expects these operations to fail with EBADF, matching Linux behavior, but FreeBSD currently returns EOPNOTSUPP for fgetxattr() on an O_PATH fd Look up Linux fd-based xattr descriptors with getvnode() and route the operations through shared kern_extattr_*_fp() helpers so the O_PATH check and the extattr operation use the same referenced file. Apply the same EBADF handling to fsetxattr(), fremovexattr(), and flistxattr() so the xattr paths stay consistent. Signed-off-by: YAO, Xin <mr.yaoxin@outlook.com> PR: 295537 Reviewed by: kib Pull Request: https://github.com/freebsd/freebsd-src/pull/2263 sys/compat/linux/linux_xattr.c | 81 ++++++++++++++++++++++++++++++++++++------ sys/kern/vfs_extattr.c | 47 ++++++++++++++++++++---- sys/sys/syscallsubr.h | 10 ++++++ 3 files changed, 121 insertions(+), 17 deletions(-)
Thank you for your contributions!