summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libc/sys/open.212
-rw-r--r--sys/compat/linux/linux_file.c8
-rw-r--r--sys/kern/vfs_syscalls.c4
-rw-r--r--sys/kern/vfs_vnops.c4
4 files changed, 22 insertions, 6 deletions
diff --git a/lib/libc/sys/open.2 b/lib/libc/sys/open.2
index 3a5979f..04fa0fe 100644
--- a/lib/libc/sys/open.2
+++ b/lib/libc/sys/open.2
@@ -117,6 +117,7 @@ O_SYNC synchronous writes
O_NOFOLLOW do not follow symlinks
O_NOCTTY don't assign controlling terminal
O_TTY_INIT restore default terminal attributes
+O_DIRECTORY error if file is not a directory
.Ed
.Pp
Opening a file with
@@ -222,6 +223,14 @@ The initial call to
on a TTY will always restore default terminal attributes on
.Fx .
.Pp
+.Dv O_DIRECTORY
+may be used to ensure the resulting file descriptor refers to a
+directory.
+This flag can be used to prevent applications with elevated privileges
+from opening files which are even unsafe to open with
+.Dv O_RDONLY ,
+such as device nodes.
+.Pp
If successful,
.Fn open
returns a non-negative integer, termed a file descriptor.
@@ -413,6 +422,9 @@ argument is not an absolute path and
is neither
.Dv AT_FDCWD
nor a file descriptor associated with a directory.
+.It Bq Eq ENOTDIR
+.Dv O_DIRECTORY
+is specified and the file is not a directory.
.El
.Sh SEE ALSO
.Xr chmod 2 ,
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index 4e33eaa..9ff1cf0 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -128,6 +128,8 @@ linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mod
bsd_flags |= O_DIRECT;
if (l_flags & LINUX_O_NOFOLLOW)
bsd_flags |= O_NOFOLLOW;
+ if (l_flags & LINUX_O_DIRECTORY)
+ bsd_flags |= O_DIRECTORY;
/* XXX LINUX_O_NOATIME: unable to be easily implemented. */
error = kern_openat(td, dirfd, path, UIO_SYSSPACE, bsd_flags, mode);
@@ -154,12 +156,6 @@ linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mod
PROC_UNLOCK(p);
sx_sunlock(&proctree_lock);
}
- if (l_flags & LINUX_O_DIRECTORY) {
- if (fp->f_type != DTYPE_VNODE ||
- fp->f_vnode->v_type != VDIR) {
- error = ENOTDIR;
- }
- }
fdrop(fp, td);
/*
* XXX as above, fdrop()/kern_close() pair is racy.
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 9d535b5..bcc3cbb 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -4428,6 +4428,10 @@ fhopen(td, uap)
error = EOPNOTSUPP;
goto bad;
}
+ if (vp->v_type != VDIR && fmode & O_DIRECTORY) {
+ error = ENOTDIR;
+ goto bad;
+ }
accmode = 0;
if (fmode & (FWRITE | O_TRUNC)) {
if (vp->v_type == VDIR) {
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index d0b713c..a16fa67 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -200,6 +200,10 @@ restart:
error = EOPNOTSUPP;
goto bad;
}
+ if (vp->v_type != VDIR && fmode & O_DIRECTORY) {
+ error = ENOTDIR;
+ goto bad;
+ }
accmode = 0;
if (fmode & (FWRITE | O_TRUNC)) {
if (vp->v_type == VDIR) {
OpenPOWER on IntegriCloud