mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-09-08 14:52:31 -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
|
#define fchownat ERROR
|
||||||
|
|
||||||
static int
|
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)
|
if (lo->xattr_permissions)
|
||||||
{
|
{
|
||||||
struct ovl_layer *upper = get_upper_layer (lo);
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (upper == NULL)
|
|
||||||
{
|
|
||||||
errno = EROFS;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
st.st_uid = 0;
|
st.st_uid = 0;
|
||||||
st.st_gid = 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 -1;
|
||||||
|
|
||||||
return write_permission_xattr (lo, fd, NULL, st.st_uid, st.st_gid, mode);
|
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
|
#define fchmod ERROR
|
||||||
|
|
||||||
static int
|
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)
|
if (lo->xattr_permissions)
|
||||||
{
|
{
|
||||||
struct ovl_layer *upper = get_upper_layer (lo);
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (upper == NULL)
|
|
||||||
{
|
|
||||||
errno = EROFS;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
st.st_uid = 0;
|
st.st_uid = 0;
|
||||||
st.st_gid = 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 -1;
|
||||||
|
|
||||||
return write_permission_xattr (lo, -1, path, st.st_uid, st.st_gid, mode);
|
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)
|
if (st_in)
|
||||||
memcpy (st, st_in, sizeof (*st));
|
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
|
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)
|
if (ret < 0)
|
||||||
return ret;
|
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 it is a writepage request, make sure to restore the setuid bit. */
|
||||||
if (fi->writepage && (inode->mode & (S_ISUID | S_ISGID)))
|
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);
|
fuse_reply_err (req, errno);
|
||||||
return;
|
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 (to_set & FUSE_SET_ATTR_MODE)
|
||||||
{
|
{
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
ret = do_fchmod (lo, fd, attr->st_mode);
|
ret = do_fchmod (lo, node, fd, attr->st_mode);
|
||||||
else
|
else
|
||||||
ret = do_chmod (lo, path, attr->st_mode);
|
ret = do_chmod (lo, node, path, attr->st_mode);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
fuse_reply_err (req, errno);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user