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;
|
cleanup_close int cleanup_fd = -1;
|
||||||
DIR *dp = NULL;
|
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)
|
if (cleanup_fd < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ direct_closedir (void *dirp)
|
|||||||
static int
|
static int
|
||||||
direct_openat (struct ovl_layer *l, const char *path, int flags, mode_t mode)
|
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
|
static ssize_t
|
||||||
|
36
main.c
36
main.c
@ -494,7 +494,7 @@ set_fd_opaque (int fd)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
create_opq_whiteout:
|
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;
|
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)
|
if (ret < 0)
|
||||||
goto out;
|
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)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -2645,11 +2645,11 @@ copyup (struct ovl_data *lo, struct ovl_node *node)
|
|||||||
goto success;
|
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)
|
if (sfd < 0)
|
||||||
goto exit;
|
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)
|
if (dfd < 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
@ -2865,7 +2865,7 @@ empty_dirfd (int fd)
|
|||||||
{
|
{
|
||||||
int dfd;
|
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)
|
if (dfd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -2893,7 +2893,7 @@ empty_dir (struct ovl_layer *l, const char *path)
|
|||||||
cleanup_close int cleanup_fd = -1;
|
cleanup_close int cleanup_fd = -1;
|
||||||
int ret;
|
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)
|
if (cleanup_fd < 0)
|
||||||
return -1;
|
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. */
|
/* try to create directly the file if it doesn't need to be chowned. */
|
||||||
if (uid == lo->uid && gid == lo->gid)
|
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)
|
if (ret >= 0)
|
||||||
return ret;
|
return ret;
|
||||||
/* if it fails (e.g. there is a whiteout) then fallback to create it in
|
/* 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 ());
|
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)
|
if (fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (uid != lo->uid || gid != lo->gid)
|
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)
|
switch (mode & S_IFMT)
|
||||||
{
|
{
|
||||||
case S_IFREG:
|
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)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
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;
|
break;
|
||||||
|
|
||||||
case S_IFDIR:
|
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 (fd < 0)
|
||||||
{
|
{
|
||||||
if (errno != ELOOP)
|
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;
|
break;
|
||||||
|
|
||||||
case S_IFLNK:
|
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)
|
if (cleaned_up_fd < 0)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
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)
|
if (pnode == NULL)
|
||||||
goto error;
|
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)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
srcfd = ret;
|
srcfd = ret;
|
||||||
@ -3990,7 +3990,7 @@ ovl_rename_exchange (fuse_req_t req, fuse_ino_t parent, const char *name,
|
|||||||
if (destpnode == NULL)
|
if (destpnode == NULL)
|
||||||
goto error;
|
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)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
destfd = ret;
|
destfd = ret;
|
||||||
@ -4106,7 +4106,7 @@ ovl_rename_direct (fuse_req_t req, fuse_ino_t parent, const char *name,
|
|||||||
if (pnode == NULL)
|
if (pnode == NULL)
|
||||||
goto error;
|
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)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
srcfd = ret;
|
srcfd = ret;
|
||||||
@ -4115,7 +4115,7 @@ ovl_rename_direct (fuse_req_t req, fuse_ino_t parent, const char *name,
|
|||||||
if (destpnode == NULL)
|
if (destpnode == NULL)
|
||||||
goto error;
|
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)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
destfd = ret;
|
destfd = ret;
|
||||||
@ -4622,7 +4622,7 @@ direct_fsync (struct ovl_layer *l, int fd, const char *path, int datasync)
|
|||||||
|
|
||||||
if (fd < 0)
|
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)
|
if (cfd < 0)
|
||||||
return cfd;
|
return cfd;
|
||||||
fd = 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);
|
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)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
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;
|
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)
|
if (fd_dest < 0)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
fuse_reply_err (req, errno);
|
||||||
|
62
utils.c
62
utils.c
@ -25,6 +25,10 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#ifndef TEMP_FAILURE_RETRY
|
#ifndef TEMP_FAILURE_RETRY
|
||||||
#define TEMP_FAILURE_RETRY(expression) \
|
#define TEMP_FAILURE_RETRY(expression) \
|
||||||
@ -35,6 +39,62 @@
|
|||||||
__result; }))
|
__result; }))
|
||||||
#endif
|
#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
|
int
|
||||||
file_exists_at (int dirfd, const char *pathname)
|
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';
|
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))
|
if (*fd < 0 && (errno == ELOOP || errno == EISDIR || errno == ENXIO))
|
||||||
{
|
{
|
||||||
strconcat3 (out, PATH_MAX, l->path, "/", path);
|
strconcat3 (out, PATH_MAX, l->path, "/", path);
|
||||||
|
2
utils.h
2
utils.h
@ -53,4 +53,6 @@ int open_fd_or_get_path (struct ovl_layer *l, const char *path, char *out, int *
|
|||||||
void statx_to_stat (struct statx *stx, struct stat *st);
|
void statx_to_stat (struct statx *stx, struct stat *st);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
int safe_openat (int dirfd, const char *pathname, int flags, mode_t mode);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user