mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-08-04 02:15:58 -04:00
main: use openat2 where available
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
f040ab0343
commit
fb8eb3300e
4
direct.c
4
direct.c
@ -129,7 +129,7 @@ direct_opendir (struct ovl_layer *l, const char *path)
|
||||
cleanup_close int cleanup_fd = -1;
|
||||
DIR *dp = NULL;
|
||||
|
||||
cleanup_fd = TEMP_FAILURE_RETRY (openat (l->fd, path, O_DIRECTORY));
|
||||
cleanup_fd = TEMP_FAILURE_RETRY (safe_openat (l->fd, path, O_DIRECTORY, 0));
|
||||
if (cleanup_fd < 0)
|
||||
return NULL;
|
||||
|
||||
@ -151,7 +151,7 @@ direct_closedir (void *dirp)
|
||||
static int
|
||||
direct_openat (struct ovl_layer *l, const char *path, int flags, mode_t mode)
|
||||
{
|
||||
return TEMP_FAILURE_RETRY (openat (l->fd, path, flags, mode));
|
||||
return TEMP_FAILURE_RETRY (safe_openat (l->fd, path, flags, mode));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
|
36
main.c
36
main.c
@ -494,7 +494,7 @@ set_fd_opaque (int fd)
|
||||
return -1;
|
||||
}
|
||||
create_opq_whiteout:
|
||||
opq_whiteout_fd = TEMP_FAILURE_RETRY (openat (fd, OPAQUE_WHITEOUT, O_CREAT|O_WRONLY|O_NONBLOCK, 0700));
|
||||
opq_whiteout_fd = TEMP_FAILURE_RETRY (safe_openat (fd, OPAQUE_WHITEOUT, O_CREAT|O_WRONLY|O_NONBLOCK, 0700));
|
||||
return (opq_whiteout_fd >= 0 || ret == 0) ? 0 : -1;
|
||||
}
|
||||
|
||||
@ -2445,7 +2445,7 @@ create_directory (struct ovl_data *lo, int dirfd, const char *name, const struct
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = dfd = TEMP_FAILURE_RETRY (openat (lo->workdir_fd, wd_tmp_file_name, O_RDONLY));
|
||||
ret = dfd = TEMP_FAILURE_RETRY (safe_openat (lo->workdir_fd, wd_tmp_file_name, O_RDONLY, 0));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
@ -2645,11 +2645,11 @@ copyup (struct ovl_data *lo, struct ovl_node *node)
|
||||
goto success;
|
||||
}
|
||||
|
||||
ret = sfd = node->layer->ds->openat (node->layer, node->path, O_RDONLY|O_NONBLOCK, 0755);
|
||||
ret = sfd = node->layer->ds->openat (node->layer, node->path, O_RDONLY|O_NONBLOCK, 0);
|
||||
if (sfd < 0)
|
||||
goto exit;
|
||||
|
||||
ret = dfd = TEMP_FAILURE_RETRY (openat (lo->workdir_fd, wd_tmp_file_name, O_CREAT|O_WRONLY, st.st_mode));
|
||||
ret = dfd = TEMP_FAILURE_RETRY (safe_openat (lo->workdir_fd, wd_tmp_file_name, O_CREAT|O_WRONLY, st.st_mode));
|
||||
if (dfd < 0)
|
||||
goto exit;
|
||||
|
||||
@ -2865,7 +2865,7 @@ empty_dirfd (int fd)
|
||||
{
|
||||
int dfd;
|
||||
|
||||
dfd = openat (dirfd (dp), dent->d_name, O_DIRECTORY);
|
||||
dfd = safe_openat (dirfd (dp), dent->d_name, O_DIRECTORY, 0);
|
||||
if (dfd < 0)
|
||||
return -1;
|
||||
|
||||
@ -2893,7 +2893,7 @@ empty_dir (struct ovl_layer *l, const char *path)
|
||||
cleanup_close int cleanup_fd = -1;
|
||||
int ret;
|
||||
|
||||
cleanup_fd = TEMP_FAILURE_RETRY (openat (l->fd, path, O_DIRECTORY));
|
||||
cleanup_fd = TEMP_FAILURE_RETRY (safe_openat (l->fd, path, O_DIRECTORY, 0));
|
||||
if (cleanup_fd < 0)
|
||||
return -1;
|
||||
|
||||
@ -3171,7 +3171,7 @@ direct_create_file (struct ovl_layer *l, int dirfd, const char *path, uid_t uid,
|
||||
/* try to create directly the file if it doesn't need to be chowned. */
|
||||
if (uid == lo->uid && gid == lo->gid)
|
||||
{
|
||||
ret = TEMP_FAILURE_RETRY (openat (get_upper_layer (lo)->fd, path, flags, mode));
|
||||
ret = TEMP_FAILURE_RETRY (safe_openat (get_upper_layer (lo)->fd, path, flags, mode));
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
/* if it fails (e.g. there is a whiteout) then fallback to create it in
|
||||
@ -3180,7 +3180,7 @@ direct_create_file (struct ovl_layer *l, int dirfd, const char *path, uid_t uid,
|
||||
|
||||
sprintf (wd_tmp_file_name, "%lu", get_next_wd_counter ());
|
||||
|
||||
fd = TEMP_FAILURE_RETRY (openat (lo->workdir_fd, wd_tmp_file_name, flags, mode));
|
||||
fd = TEMP_FAILURE_RETRY (safe_openat (lo->workdir_fd, wd_tmp_file_name, flags, mode));
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
if (uid != lo->uid || gid != lo->gid)
|
||||
@ -3590,7 +3590,7 @@ ovl_setattr (fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, stru
|
||||
switch (mode & S_IFMT)
|
||||
{
|
||||
case S_IFREG:
|
||||
cleaned_up_fd = fd = TEMP_FAILURE_RETRY (openat (dirfd, node->path, O_NOFOLLOW|O_NONBLOCK|(to_set & FUSE_SET_ATTR_SIZE ? O_WRONLY : 0)));
|
||||
cleaned_up_fd = fd = TEMP_FAILURE_RETRY (safe_openat (dirfd, node->path, O_NOFOLLOW|O_NONBLOCK|(to_set & FUSE_SET_ATTR_SIZE ? O_WRONLY : 0), 0));
|
||||
if (fd < 0)
|
||||
{
|
||||
fuse_reply_err (req, errno);
|
||||
@ -3599,7 +3599,7 @@ ovl_setattr (fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, stru
|
||||
break;
|
||||
|
||||
case S_IFDIR:
|
||||
cleaned_up_fd = fd = TEMP_FAILURE_RETRY (openat (dirfd, node->path, O_NOFOLLOW|O_NONBLOCK));
|
||||
cleaned_up_fd = fd = TEMP_FAILURE_RETRY (safe_openat (dirfd, node->path, O_NOFOLLOW|O_NONBLOCK, 0));
|
||||
if (fd < 0)
|
||||
{
|
||||
if (errno != ELOOP)
|
||||
@ -3611,7 +3611,7 @@ ovl_setattr (fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, stru
|
||||
break;
|
||||
|
||||
case S_IFLNK:
|
||||
cleaned_up_fd = TEMP_FAILURE_RETRY (openat (dirfd, node->path, O_PATH|O_NOFOLLOW|O_NONBLOCK));
|
||||
cleaned_up_fd = TEMP_FAILURE_RETRY (safe_openat (dirfd, node->path, O_PATH|O_NOFOLLOW|O_NONBLOCK, 0));
|
||||
if (cleaned_up_fd < 0)
|
||||
{
|
||||
fuse_reply_err (req, errno);
|
||||
@ -3981,7 +3981,7 @@ ovl_rename_exchange (fuse_req_t req, fuse_ino_t parent, const char *name,
|
||||
if (pnode == NULL)
|
||||
goto error;
|
||||
|
||||
ret = TEMP_FAILURE_RETRY (openat (node_dirfd (pnode), pnode->path, O_DIRECTORY));
|
||||
ret = TEMP_FAILURE_RETRY (safe_openat (node_dirfd (pnode), pnode->path, O_DIRECTORY, 0));
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
srcfd = ret;
|
||||
@ -3990,7 +3990,7 @@ ovl_rename_exchange (fuse_req_t req, fuse_ino_t parent, const char *name,
|
||||
if (destpnode == NULL)
|
||||
goto error;
|
||||
|
||||
ret = TEMP_FAILURE_RETRY (openat (node_dirfd (destpnode), destpnode->path, O_DIRECTORY));
|
||||
ret = TEMP_FAILURE_RETRY (safe_openat (node_dirfd (destpnode), destpnode->path, O_DIRECTORY, 0));
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
destfd = ret;
|
||||
@ -4106,7 +4106,7 @@ ovl_rename_direct (fuse_req_t req, fuse_ino_t parent, const char *name,
|
||||
if (pnode == NULL)
|
||||
goto error;
|
||||
|
||||
ret = TEMP_FAILURE_RETRY (openat (node_dirfd (pnode), pnode->path, O_DIRECTORY));
|
||||
ret = TEMP_FAILURE_RETRY (safe_openat (node_dirfd (pnode), pnode->path, O_DIRECTORY, 0));
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
srcfd = ret;
|
||||
@ -4115,7 +4115,7 @@ ovl_rename_direct (fuse_req_t req, fuse_ino_t parent, const char *name,
|
||||
if (destpnode == NULL)
|
||||
goto error;
|
||||
|
||||
ret = TEMP_FAILURE_RETRY (openat (node_dirfd (destpnode), destpnode->path, O_DIRECTORY));
|
||||
ret = TEMP_FAILURE_RETRY (safe_openat (node_dirfd (destpnode), destpnode->path, O_DIRECTORY, 0));
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
destfd = ret;
|
||||
@ -4622,7 +4622,7 @@ direct_fsync (struct ovl_layer *l, int fd, const char *path, int datasync)
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
cfd = openat (l->fd, path, O_NOFOLLOW|O_DIRECTORY);
|
||||
cfd = safe_openat (l->fd, path, O_NOFOLLOW|O_DIRECTORY, 0);
|
||||
if (cfd < 0)
|
||||
return cfd;
|
||||
fd = cfd;
|
||||
@ -4813,7 +4813,7 @@ ovl_fallocate (fuse_req_t req, fuse_ino_t ino, int mode, off_t offset, off_t len
|
||||
}
|
||||
|
||||
dirfd = node_dirfd (node);
|
||||
fd = openat (dirfd, node->path, O_NONBLOCK|O_NOFOLLOW|O_WRONLY, 0755);
|
||||
fd = safe_openat (dirfd, node->path, O_NONBLOCK|O_NOFOLLOW|O_WRONLY, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
fuse_reply_err (req, errno);
|
||||
@ -4878,7 +4878,7 @@ ovl_copy_file_range (fuse_req_t req, fuse_ino_t ino_in, off_t off_in, struct fus
|
||||
return;
|
||||
}
|
||||
|
||||
fd_dest = TEMP_FAILURE_RETRY (openat (node_dirfd (dnode), dnode->path, O_NONBLOCK|O_NOFOLLOW|O_WRONLY));
|
||||
fd_dest = TEMP_FAILURE_RETRY (safe_openat (node_dirfd (dnode), dnode->path, O_NONBLOCK|O_NOFOLLOW|O_WRONLY, 0));
|
||||
if (fd_dest < 0)
|
||||
{
|
||||
fuse_reply_err (req, errno);
|
||||
|
62
utils.c
62
utils.c
@ -25,6 +25,10 @@
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef TEMP_FAILURE_RETRY
|
||||
#define TEMP_FAILURE_RETRY(expression) \
|
||||
@ -35,6 +39,62 @@
|
||||
__result; }))
|
||||
#endif
|
||||
|
||||
#ifndef RESOLVE_IN_ROOT
|
||||
# define RESOLVE_IN_ROOT 0x10
|
||||
#endif
|
||||
#ifndef __NR_openat2
|
||||
# define __NR_openat2 437
|
||||
#endif
|
||||
|
||||
/* List of all valid flags for the open/openat flags argument: */
|
||||
#define VALID_OPEN_FLAGS \
|
||||
(O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | \
|
||||
O_APPEND | O_NDELAY | O_NONBLOCK | O_NDELAY | O_SYNC | O_DSYNC | \
|
||||
FASYNC | O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \
|
||||
O_NOATIME | O_CLOEXEC | O_PATH | O_TMPFILE)
|
||||
|
||||
static int
|
||||
syscall_openat2 (int dirfd, const char *path, uint64_t flags, uint64_t mode, uint64_t resolve)
|
||||
{
|
||||
struct openat2_open_how
|
||||
{
|
||||
uint64_t flags;
|
||||
uint64_t mode;
|
||||
uint64_t resolve;
|
||||
}
|
||||
how =
|
||||
{
|
||||
.flags = flags & VALID_OPEN_FLAGS,
|
||||
.mode = (flags & O_CREAT) ? (mode & 07777) : 0,
|
||||
.resolve = resolve,
|
||||
};
|
||||
|
||||
return (int) syscall (__NR_openat2, dirfd, path, &how, sizeof (how), 0);
|
||||
}
|
||||
|
||||
int
|
||||
safe_openat (int dirfd, const char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
static bool openat2_supported = true;
|
||||
|
||||
if (openat2_supported)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = syscall_openat2 (dirfd, pathname, flags, mode, RESOLVE_IN_ROOT);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (errno == ENOSYS)
|
||||
openat2_supported = false;
|
||||
if (errno == ENOSYS || errno == EINVAL)
|
||||
goto fallback;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
fallback:
|
||||
return openat (dirfd, pathname, flags, mode);
|
||||
}
|
||||
|
||||
int
|
||||
file_exists_at (int dirfd, const char *pathname)
|
||||
{
|
||||
@ -148,7 +208,7 @@ open_fd_or_get_path (struct ovl_layer *l, const char *path, char *out, int *fd,
|
||||
{
|
||||
out[0] = '\0';
|
||||
|
||||
*fd = l->ds->openat (l, path, O_NONBLOCK|O_NOFOLLOW|flags, 0755);
|
||||
*fd = l->ds->openat (l, path, O_NONBLOCK|O_NOFOLLOW|flags, 0);
|
||||
if (*fd < 0 && (errno == ELOOP || errno == EISDIR || errno == ENXIO))
|
||||
{
|
||||
strconcat3 (out, PATH_MAX, l->path, "/", path);
|
||||
|
Loading…
x
Reference in New Issue
Block a user