Bug 295537 - linuxulator: O_PATH file descriptors return wrong errno for f*xattr(2)
Summary: linuxulator: O_PATH file descriptors return wrong errno for f*xattr(2)
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 16.0-CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: Pouria Mousavizadeh Tehrani
URL: https://github.com/freebsd/freebsd-sr...
Keywords:
Depends on:
Blocks:
 
Reported: 2026-05-24 01:37 UTC by YAO, Xin
Modified: 2026-07-01 08:46 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description YAO, Xin 2026-05-24 01:37:18 UTC
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
Comment 1 YAO, Xin 2026-05-24 14:24:33 UTC
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
Comment 2 commit-hook freebsd_committer freebsd_triage 2026-07-01 08:45:02 UTC
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(-)
Comment 3 Pouria Mousavizadeh Tehrani freebsd_committer freebsd_triage 2026-07-01 08:46:17 UTC
Thank you for your contributions!