fd-util: beef up fd_verify_safe_flags() features
Let's make fd_verify_safe_flags() even more useful: 1. let's return the cleaned up flags (i.e. just the access mode) after validation, hiding all the noise, such as O_NOFOLLOW, O_LARGEFILE and similar. 2. let's add a "full" version of the call that allows passing additional flags that are OK to be set.
This commit is contained in:
+5
-5
@@ -913,21 +913,21 @@ int fd_is_opath(int fd) {
|
||||
return FLAGS_SET(r, O_PATH);
|
||||
}
|
||||
|
||||
int fd_verify_safe_flags(int fd) {
|
||||
int fd_verify_safe_flags_full(int fd, int extra_flags) {
|
||||
int flags, unexpected_flags;
|
||||
|
||||
/* Check if an extrinsic fd is safe to work on (by a privileged service). This ensures that clients
|
||||
* can't trick a privileged service into giving access to a file the client doesn't already have
|
||||
* access to (especially via something like O_PATH).
|
||||
*
|
||||
* O_NOFOLLOW: For some reason the kernel will return this flag from fcntl; it doesn't go away
|
||||
* O_NOFOLLOW: For some reason the kernel will return this flag from fcntl(); it doesn't go away
|
||||
* immediately after open(). It should have no effect whatsoever to an already-opened FD,
|
||||
* and since we refuse O_PATH it should be safe.
|
||||
*
|
||||
* RAW_O_LARGEFILE: glibc secretly sets this and neglects to hide it from us if we call fcntl.
|
||||
* See comment in missing_fcntl.h for more details about this.
|
||||
*
|
||||
* O_DIRECTORY: this is set for directories, which are totally fine
|
||||
* If 'extra_flags' is specified as non-zero the included flags are also allowed.
|
||||
*/
|
||||
|
||||
assert(fd >= 0);
|
||||
@@ -936,13 +936,13 @@ int fd_verify_safe_flags(int fd) {
|
||||
if (flags < 0)
|
||||
return -errno;
|
||||
|
||||
unexpected_flags = flags & ~(O_ACCMODE|O_NOFOLLOW|RAW_O_LARGEFILE|O_DIRECTORY);
|
||||
unexpected_flags = flags & ~(O_ACCMODE|O_NOFOLLOW|RAW_O_LARGEFILE|extra_flags);
|
||||
if (unexpected_flags != 0)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EREMOTEIO),
|
||||
"Unexpected flags set for extrinsic fd: 0%o",
|
||||
(unsigned) unexpected_flags);
|
||||
|
||||
return 0;
|
||||
return flags & (O_ACCMODE | extra_flags); /* return the flags variable, but remove the noise */
|
||||
}
|
||||
|
||||
int read_nr_open(void) {
|
||||
|
||||
+5
-1
@@ -114,7 +114,11 @@ int fd_reopen(int fd, int flags);
|
||||
int fd_reopen_condition(int fd, int flags, int mask, int *ret_new_fd);
|
||||
|
||||
int fd_is_opath(int fd);
|
||||
int fd_verify_safe_flags(int fd);
|
||||
|
||||
int fd_verify_safe_flags_full(int fd, int extra_flags);
|
||||
static inline int fd_verify_safe_flags(int fd) {
|
||||
return fd_verify_safe_flags_full(fd, 0);
|
||||
}
|
||||
|
||||
int read_nr_open(void);
|
||||
int fd_get_diskseq(int fd, uint64_t *ret);
|
||||
|
||||
Reference in New Issue
Block a user