diff options
author | ed <ed@FreeBSD.org> | 2010-03-21 20:43:23 +0000 |
---|---|---|
committer | ed <ed@FreeBSD.org> | 2010-03-21 20:43:23 +0000 |
commit | 61565034678feb77b6c58414a124a3e2da5b51e7 (patch) | |
tree | bd53b22130f2318dc178cfea963b4c5affe6d99a | |
parent | ef7941cba28fcad604cef37d54a4b24af415b5f2 (diff) | |
download | FreeBSD-src-61565034678feb77b6c58414a124a3e2da5b51e7.zip FreeBSD-src-61565034678feb77b6c58414a124a3e2da5b51e7.tar.gz |
Actually make O_DIRECTORY work.
According to POSIX open() must return ENOTDIR when the path name does
not refer to a path name. Change vn_open() to respect this flag. This
also simplifies the Linuxolator a bit.
-rw-r--r-- | lib/libc/sys/open.2 | 12 | ||||
-rw-r--r-- | sys/compat/linux/linux_file.c | 8 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 4 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 4 |
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) { |