openat(2): add O_EMPTY_PATH

It reopens the passed file descriptor, checking the file backing vnode'
current access rights against open mode. In particular, this flag allows
to convert file descriptor opened with O_PATH, into operable file
descriptor, assuming permissions allow that.

Reviewed by:	markj
Tested by:	Andrew Walker <awalker@ixsystems.com>
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D30148
This commit is contained in:
Konstantin Belousov 2021-05-06 20:16:53 +03:00
parent c55b340f82
commit 5e7cdf1817
3 changed files with 22 additions and 1 deletions

View File

@ -28,7 +28,7 @@
.\" @(#)open.2 8.2 (Berkeley) 11/16/93
.\" $FreeBSD$
.\"
.Dd March 18, 2021
.Dd May 6, 2021
.Dt OPEN 2
.Os
.Sh NAME
@ -169,6 +169,7 @@ O_CLOEXEC set FD_CLOEXEC upon open
O_VERIFY verify the contents of the file
O_RESOLVE_BENEATH path resolution must not cross the fd directory
O_PATH record only the target path in the opened descriptor
O_EMPTY_PATH openat, open file referenced by fd if path is empty
.Ed
.Pp
Opening a file with
@ -355,6 +356,21 @@ are not allowed.
File opened with the
.Dv O_PATH
flag does not prevent non-forced unmount of the volume it belongs to.
.Pp
A file descriptor created with the
.Dv O_PATH
flag can be opened into normal (operable) file descriptor by
specifying it as the
.Fa fd
argument to
.Fn openat
with empty
.Fa path
and flag
.Dv O_EMPTY_PATH .
Such an open behaves as if the current path of the file referenced by
.Fa fd
is passed, except that the path walk permissions are not checked.
See also the description of
.Dv AT_EMPTY_PATH
flag for

View File

@ -200,6 +200,8 @@ open2nameif(int fmode, u_int vn_open_flags)
res = ISOPEN | LOCKLEAF;
if ((fmode & O_RESOLVE_BENEATH) != 0)
res |= RBENEATH;
if ((fmode & O_EMPTY_PATH) != 0)
res |= EMPTYPATH;
if ((vn_open_flags & VN_OPEN_NOAUDIT) == 0)
res |= AUDITVNODE1;
if ((vn_open_flags & VN_OPEN_NOCAPCHECK) != 0)

View File

@ -141,6 +141,9 @@ typedef __pid_t pid_t;
#endif
#define O_DSYNC 0x01000000 /* POSIX data sync */
#if __BSD_VISIBLE
#define O_EMPTY_PATH 0x02000000
#endif
/*
* XXX missing O_RSYNC.