From 50c5211c93bf3b185951ea530a16419782953f1a Mon Sep 17 00:00:00 2001 From: "YAO, Xin" Date: Tue, 2 Jun 2026 10:45:24 +0800 Subject: [PATCH] linuxulator: improve getxattr() error handling - Return ERANGE for short getxattr buffers: when the caller provides a buffer smaller than the xattr value, linux_getxattr() and linux_lgetxattr() should set the return value to the full size of the attribute and return ERANGE, matching Linux behavior. This fixes the LTP getxattr01 test. - Return ENODATA for getxattr on unsupported file types: for file types that do not support extended attributes (fifo, char device, block device, UNIX domain socket), the FreeBSD VFS layer returns EOPNOTSUPP via vop_eopnotsupp(). Map this to ENOATTR so that the Linux errno translation produces ENODATA (61), matching Linux behavior. This fixes the LTP getxattr02 test. Signed-off-by: YAO, Xin --- sys/compat/linux/linux_xattr.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/sys/compat/linux/linux_xattr.c b/sys/compat/linux/linux_xattr.c index 2eec33f8ef93fa..33ee9f48ff506f 100644 --- a/sys/compat/linux/linux_xattr.c +++ b/sys/compat/linux/linux_xattr.c @@ -310,18 +310,34 @@ static int getxattr(struct thread *td, struct getxattr_args *args) { char attrname[LINUX_XATTR_NAME_MAX + 1]; + ssize_t size; int attrnamespace, error; error = xattr_to_extattr(args->name, &attrnamespace, attrname); if (error != 0) return (error); + if (args->path != NULL) + error = kern_extattr_get_path(td, args->path, attrnamespace, + attrname, NULL, 0, args->follow, UIO_USERSPACE); + else + error = kern_extattr_get_fd(td, args->fd, attrnamespace, + attrname, NULL, 0); + if (error != 0) + goto out; + if (args->value == NULL || args->size == 0) + return (0); + size = td->td_retval[0]; + if (size > args->size) + return (ERANGE); if (args->path != NULL) error = kern_extattr_get_path(td, args->path, attrnamespace, attrname, args->value, args->size, args->follow, UIO_USERSPACE); else error = kern_extattr_get_fd(td, args->fd, attrnamespace, attrname, args->value, args->size); - return (error == EPERM ? ENOATTR : error); + +out: + return (error == EPERM || error == EOPNOTSUPP ? ENOATTR : error); } int