diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c --- a/sys/compat/linux/linux_stats.c +++ b/sys/compat/linux/linux_stats.c @@ -88,6 +88,23 @@ return (error); } +static int +linux_empty_path_error(const char *pathname, enum uio_seg pathseg, int error) +{ + char path[1]; + size_t len; + + if (pathseg == UIO_USERSPACE) { + if (copyinstr(pathname, path, sizeof(path), &len) != 0) + return (error); + } else + path[0] = pathname[0]; + if (path[0] == '\0') + return (ENOENT); + else + return (error); +} + static int linux_kern_statat(struct thread *td, int flag, int fd, const char *path, enum uio_seg pathseg, struct stat *sbp) @@ -104,9 +121,13 @@ AUDITVNODE1, pathseg, path, fd, &cap_fstat_rights); if ((error = namei(&nd)) != 0) { - if (error == ENOTDIR && - (nd.ni_resflags & NIRES_EMPTYPATH) != 0) - error = linux_kern_fstat(td, fd, sbp); + if (error == ENOTDIR) { + if ((nd.ni_resflags & NIRES_EMPTYPATH) != 0) + error = linux_kern_fstat(td, fd, sbp); + else if (fd != AT_FDCWD) + error = linux_empty_path_error(path, pathseg, + error); + } return (error); } error = VOP_STAT(nd.ni_vp, sbp, td->td_ucred, NOCRED);