diff --git a/bin/csh/dot.cshrc b/bin/csh/dot.cshrc index f7a9a3ed0226..2465cf42da6c 100644 --- a/bin/csh/dot.cshrc +++ b/bin/csh/dot.cshrc @@ -12,6 +12,10 @@ alias la ls -aF alias lf ls -FA alias ll ls -lAF +# read(2) of directories may not be desirable by default, as this will provoke +# EISDIR errors from each directory encountered. +# alias grep grep -d skip + # A righteous umask umask 22 diff --git a/bin/sh/dot.shrc b/bin/sh/dot.shrc index a8b75c9a67d3..5277e5b07b0a 100644 --- a/bin/sh/dot.shrc +++ b/bin/sh/dot.shrc @@ -31,6 +31,9 @@ # alias mv='mv -i' # alias rm='rm -i' +# read(2) of directories may not be desirable by default, as this will provoke +# EISDIR errors from each directory encountered. +# alias grep='grep -d skip' # set prompt: ``username@hostname:directory $ '' PS1="\u@\h:\w \\$ " diff --git a/lib/libc/sys/read.2 b/lib/libc/sys/read.2 index cc11f3cd440a..ad08c5a448e8 100644 --- a/lib/libc/sys/read.2 +++ b/lib/libc/sys/read.2 @@ -28,7 +28,7 @@ .\" @(#)read.2 8.4 (Berkeley) 2/26/94 .\" $FreeBSD$ .\" -.Dd March 30, 2020 +.Dd June 4, 2020 .Dt READ 2 .Os .Sh NAME @@ -199,9 +199,14 @@ was negative. The file was marked for non-blocking I/O, and no data were ready to be read. .It Bq Er EISDIR -The file descriptor is associated with a directory residing -on a file system that does not allow regular read operations on -directories (e.g.\& NFS). +The file descriptor is associated with a directory. +Directories may only be read directly if the filesystem supports it and +the +.Dv security.bsd.allow_read_dir +sysctl MIB is set to a non-zero value. +For most scenarios, the +.Xr readdir 3 +function should be used instead. .It Bq Er EOPNOTSUPP The file descriptor is associated with a file system and file type that do not allow regular read operations on it. diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 86b12230afdf..84c34501de4b 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -136,6 +136,11 @@ static u_long vn_io_faults_cnt; SYSCTL_ULONG(_debug, OID_AUTO, vn_io_faults, CTLFLAG_RD, &vn_io_faults_cnt, 0, "Count of vn_io_fault lock avoidance triggers"); +static int vfs_allow_read_dir = 0; +SYSCTL_INT(_security_bsd, OID_AUTO, allow_read_dir, CTLFLAG_RW, + &vfs_allow_read_dir, 0, + "Enable read(2) of directory by root for filesystems that support it"); + /* * Returns true if vn_io_fault mode of handling the i/o request should * be used. @@ -1216,6 +1221,20 @@ vn_io_fault(struct file *fp, struct uio *uio, struct ucred *active_cred, doio = uio->uio_rw == UIO_READ ? vn_read : vn_write; vp = fp->f_vnode; + + /* + * The ability to read(2) on a directory has historically been + * allowed for all users, but this can and has been the source of + * at least one security issue in the past. As such, it is now hidden + * away behind a sysctl for those that actually need it to use it. + */ + if (vp->v_type == VDIR) { + KASSERT(uio->uio_rw == UIO_READ, + ("illegal write attempted on a directory")); + if (!vfs_allow_read_dir) + return (EISDIR); + } + foffset_lock_uio(fp, uio, flags); if (do_vn_io_fault(vp, uio)) { args.kind = VN_IO_FAULT_FOP;