aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/csh/dot.cshrc4
-rw-r--r--bin/sh/dot.shrc3
-rw-r--r--lib/libc/sys/read.213
-rw-r--r--sys/kern/vfs_vnops.c19
4 files changed, 35 insertions, 4 deletions
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;