Index: sys/compat/linux/linux_file.c =================================================================== --- sys/compat/linux/linux_file.c +++ sys/compat/linux/linux_file.c @@ -1738,8 +1738,18 @@ char *path; int error, dfd, flag; - if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW) + if (args->flag & ~(LINUX_AT_SYMLINK_NOFOLLOW | LINUX_AT_EMPTY_PATH)) { + linux_msg(td, "fchownat unsupported flag 0x%x", args->flag); return (EINVAL); + } + + if (args->flag & LINUX_AT_EMPTY_PATH) { + if (args->dfd == AT_FDCWD) { + linux_msg(td, "unsupported fchownat with AT_FDCWD"); + return (EBADF); + } + return (kern_fchown(td, args->dfd, args->uid, args->gid)); + } dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) == 0 ? 0 : Index: sys/kern/vfs_syscalls.c =================================================================== --- sys/kern/vfs_syscalls.c +++ sys/kern/vfs_syscalls.c @@ -3023,16 +3023,23 @@ #endif int sys_fchown(struct thread *td, struct fchown_args *uap) +{ + + return (kern_fchown(td, uap->fd, uap->uid, uap->gid)); +} + +int +kern_fchown(struct thread *td, int fd, int uid, int gid) { struct file *fp; int error; - AUDIT_ARG_FD(uap->fd); - AUDIT_ARG_OWNER(uap->uid, uap->gid); - error = fget(td, uap->fd, &cap_fchown_rights, &fp); + AUDIT_ARG_FD(fd); + AUDIT_ARG_OWNER(uid, gid); + error = fget(td, fd, &cap_fchown_rights, &fp); if (error != 0) return (error); - error = fo_chown(fp, uap->uid, uap->gid, td->td_ucred, td); + error = fo_chown(fp, uid, gid, td->td_ucred, td); fdrop(fp, td); return (error); } Index: sys/sys/syscallsubr.h =================================================================== --- sys/sys/syscallsubr.h +++ sys/sys/syscallsubr.h @@ -134,6 +134,7 @@ struct mac *mac_p, struct vmspace *oldvmspace); int kern_fchmodat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, mode_t mode, int flag); +int kern_fchown(struct thread *td, int fd, int uid, int gid); int kern_fchownat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, int uid, int gid, int flag); int kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg);