mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-08-03 09:55:57 -04:00
main: Fix file owner retrieval for chmod
do_fchmod () and do_chmod () used to call override_mode () directly to retrieve the owner information, but the usage of override_mode () was wrong; override_mode () expects struct stat is already populated by the information provided by the underlying filesystem, but do_fchmod () and do_chmod () only zeroed st_uid and st_gid. override_mode () does not update the owner information when st_mode is not S_IFDIR nor S_IFREG so this caused chmod to change the file owner to root at random. Use the logic rpl_stat () employs to file owner retrieval for chmod functions to ensure they provide the owner information consistent with rpl_stat (). Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
This commit is contained in:
parent
a13a9e71dc
commit
136aefd2f6
53
main.c
53
main.c
@ -622,22 +622,32 @@ do_fchownat (struct ovl_data *lo, int dfd, const char *path, uid_t uid, gid_t gi
|
||||
#define fchownat ERROR
|
||||
|
||||
static int
|
||||
do_fchmod (struct ovl_data *lo, int fd, mode_t mode)
|
||||
do_stat (struct ovl_node *node, int fd, const char *path, struct stat *st)
|
||||
{
|
||||
struct ovl_layer *l = node->layer;
|
||||
|
||||
if (fd >= 0)
|
||||
return l->ds->fstat (l, fd, path, STATX_BASIC_STATS, st);
|
||||
|
||||
if (path != NULL)
|
||||
return stat (path, st);
|
||||
|
||||
if (node->hidden)
|
||||
return fstatat (node_dirfd (node), node->path, st, AT_SYMLINK_NOFOLLOW);
|
||||
|
||||
return l->ds->statat (l, node->path, st, AT_SYMLINK_NOFOLLOW, STATX_BASIC_STATS);
|
||||
}
|
||||
|
||||
static int
|
||||
do_fchmod (struct ovl_data *lo, struct ovl_node *node, int fd, mode_t mode)
|
||||
{
|
||||
if (lo->xattr_permissions)
|
||||
{
|
||||
struct ovl_layer *upper = get_upper_layer (lo);
|
||||
struct stat st;
|
||||
|
||||
if (upper == NULL)
|
||||
{
|
||||
errno = EROFS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
st.st_uid = 0;
|
||||
st.st_gid = 0;
|
||||
if (override_mode (upper, fd, NULL, NULL, &st) < 0 && errno != ENODATA)
|
||||
if (do_stat (node, fd, NULL, &st) < 0)
|
||||
return -1;
|
||||
|
||||
return write_permission_xattr (lo, fd, NULL, st.st_uid, st.st_gid, mode);
|
||||
@ -648,22 +658,15 @@ do_fchmod (struct ovl_data *lo, int fd, mode_t mode)
|
||||
#define fchmod ERROR
|
||||
|
||||
static int
|
||||
do_chmod (struct ovl_data *lo, const char *path, mode_t mode)
|
||||
do_chmod (struct ovl_data *lo, struct ovl_node *node, const char *path, mode_t mode)
|
||||
{
|
||||
if (lo->xattr_permissions)
|
||||
{
|
||||
struct ovl_layer *upper = get_upper_layer (lo);
|
||||
struct stat st;
|
||||
|
||||
if (upper == NULL)
|
||||
{
|
||||
errno = EROFS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
st.st_uid = 0;
|
||||
st.st_gid = 0;
|
||||
if (override_mode (upper, -1, path, NULL, &st) < 0 && errno != ENODATA)
|
||||
if (do_stat (node, -1, path, &st) < 0)
|
||||
return -1;
|
||||
|
||||
return write_permission_xattr (lo, -1, path, st.st_uid, st.st_gid, mode);
|
||||
@ -921,14 +924,8 @@ rpl_stat (fuse_req_t req, struct ovl_node *node, int fd, const char *path, struc
|
||||
|
||||
if (st_in)
|
||||
memcpy (st, st_in, sizeof (*st));
|
||||
else if (fd >= 0)
|
||||
ret = l->ds->fstat (l, fd, path, STATX_BASIC_STATS, st);
|
||||
else if (path != NULL)
|
||||
ret = stat (path, st);
|
||||
else if (node->hidden)
|
||||
ret = fstatat (node_dirfd (node), node->path, st, AT_SYMLINK_NOFOLLOW);
|
||||
else
|
||||
ret = l->ds->statat (l, node->path, st, AT_SYMLINK_NOFOLLOW, STATX_BASIC_STATS);
|
||||
ret = do_stat (node, fd, path, st);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -3823,7 +3820,7 @@ ovl_write_buf (fuse_req_t req, fuse_ino_t ino,
|
||||
/* if it is a writepage request, make sure to restore the setuid bit. */
|
||||
if (fi->writepage && (inode->mode & (S_ISUID | S_ISGID)))
|
||||
{
|
||||
if (do_fchmod (lo, fi->fh, inode->mode) < 0)
|
||||
if (do_fchmod (lo, inode->node, fi->fh, inode->mode) < 0)
|
||||
{
|
||||
fuse_reply_err (req, errno);
|
||||
return;
|
||||
@ -4135,9 +4132,9 @@ ovl_setattr (fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, stru
|
||||
if (to_set & FUSE_SET_ATTR_MODE)
|
||||
{
|
||||
if (fd >= 0)
|
||||
ret = do_fchmod (lo, fd, attr->st_mode);
|
||||
ret = do_fchmod (lo, node, fd, attr->st_mode);
|
||||
else
|
||||
ret = do_chmod (lo, path, attr->st_mode);
|
||||
ret = do_chmod (lo, node, path, attr->st_mode);
|
||||
if (ret < 0)
|
||||
{
|
||||
fuse_reply_err (req, errno);
|
||||
|
Loading…
x
Reference in New Issue
Block a user