Index: RELNOTES =================================================================== --- RELNOTES +++ RELNOTES @@ -10,8 +10,17 @@ Changes to this file should not be MFCed. -r361238: - ZFS will now reject read(2) of a dirfd with EISDIR. +r361238, r36xxxx: + ZFS will now unconditionally reject read(2) of a directory with EISDIR. + Additionally, read(2) of a directory is now rejected with EISDIR by + default and may be re-enabled for non-ZFS filesystems that allow it with + the sysctl(8) MIB 'security.bsd.allow_read_dir'. + + Aliases for grep to default to '-d skip' may be desired if commonly + non-recursively grepping a list that includes directories and the + possibility of EISDIR errors in stderr is not tolerable. Example + aliases, commented out, have been installed in /root/.cshrc and + /root/.shrc, as well as the /usr/share/skel variants of these files. r361066: Add exec.prepare and exec.release hooks for jail(8) and jail.conf(5). Index: UPDATING =================================================================== --- UPDATING +++ UPDATING @@ -26,6 +26,17 @@ disable the most expensive debugging functionality run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +202005xx: + read(2) of a directory fd is now rejected by default. root may + re-enable it for themselves with the security.bsd.allow_read_dir + sysctl(8) MIB if security.bsd.suser_enabled=1. + + It may be advised to setup aliases for grep to default to `-d skip` if + commonly non-recursively grepping a list that includes directories and + the potential for the resulting stderr output is not tolerable. Example + aliases are now installed, commented out, in /root/.cshrc and + /root/.shrc as well as /usr/share/skel variants of these files. + 20200424: closefrom(2) has been moved under COMPAT12, and replaced in libc with a stub that calls close_range(2). If using a custom kernel configuration, Index: bin/csh/dot.cshrc =================================================================== --- bin/csh/dot.cshrc +++ bin/csh/dot.cshrc @@ -12,6 +12,10 @@ 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 Index: bin/sh/dot.shrc =================================================================== --- bin/sh/dot.shrc +++ 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 \\$ " Index: lib/libc/sys/read.2 =================================================================== --- lib/libc/sys/read.2 +++ lib/libc/sys/read.2 @@ -28,7 +28,7 @@ .\" @(#)read.2 8.4 (Berkeley) 2/26/94 .\" $FreeBSD$ .\" -.Dd May 13, 2020 +.Dd May 15, 2020 .Dt READ 2 .Os .Sh NAME @@ -200,7 +200,11 @@ and no data were ready to be read. .It Bq Er EISDIR The file descriptor is associated with a directory. -The +Directories may only be read directly by root 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 Index: share/skel/dot.cshrc =================================================================== --- share/skel/dot.cshrc +++ share/skel/dot.cshrc @@ -12,6 +12,10 @@ 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 + # These are normally set through /etc/login.conf. You may override them here # if wanted. # set path = (/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin $HOME/bin) Index: share/skel/dot.shrc =================================================================== --- share/skel/dot.shrc +++ share/skel/dot.shrc @@ -31,6 +31,10 @@ # 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 \\$ " Index: sys/kern/kern_jail.c =================================================================== --- sys/kern/kern_jail.c +++ sys/kern/kern_jail.c @@ -3323,6 +3323,14 @@ else return (EPERM); + /* + * Jails should hold no disposition on the PRIV_VFS_READ_DIR + * policy. priv_check_cred will not specifically allow it, and + * we may want a MAC policy to allow it. + */ + case PRIV_VFS_READ_DIR: + return (0); + /* * Conditionnaly allow locking (unlocking) physical pages * in memory. Index: sys/kern/kern_priv.c =================================================================== --- sys/kern/kern_priv.c +++ sys/kern/kern_priv.c @@ -194,6 +194,13 @@ goto out; } break; + case PRIV_VFS_READ_DIR: + /* + * Allow PRIV_VFS_READ_DIR for root if we're not in a + * jail, otherwise deny unless a MAC policy grants it. + */ + if (jailed(cred)) + break; default: if (cred->cr_uid == 0) { error = 0; Index: sys/kern/vfs_vnops.c =================================================================== --- sys/kern/vfs_vnops.c +++ sys/kern/vfs_vnops.c @@ -135,6 +135,11 @@ 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. @@ -1160,6 +1165,24 @@ 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, and + * restricted to root when it's turned on to make it relatively safe to + * leave on for longer sessions of need. + */ + if (vp->v_type == VDIR) { + KASSERT(uio->uio_rw == UIO_READ, + ("illegal write attempted on a directory")); + if (!vfs_allow_read_dir) + return (EISDIR); + if ((error = priv_check(td, PRIV_VFS_READ_DIR)) != 0) + return (EISDIR); + } + foffset_lock_uio(fp, uio, flags); if (do_vn_io_fault(vp, uio)) { args.kind = VN_IO_FAULT_FOP; Index: sys/sys/priv.h =================================================================== --- sys/sys/priv.h +++ sys/sys/priv.h @@ -283,6 +283,7 @@ #define PRIV_VFS_SYSFLAGS 342 /* Can modify system flags. */ #define PRIV_VFS_UNMOUNT 343 /* Can unmount(). */ #define PRIV_VFS_STAT 344 /* Override vnode MAC stat perm. */ +#define PRIV_VFS_READ_DIR 345 /* Can read(2) a dirfd, needs sysctl. */ /* * Virtual memory privileges.