]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
mkfs: don't trample the gid set in the protofile
authorDarrick J. Wong <djwong@kernel.org>
Wed, 18 May 2022 02:48:13 +0000 (22:48 -0400)
committerEric Sandeen <sandeen@sandeen.net>
Wed, 18 May 2022 02:48:13 +0000 (22:48 -0400)
Catherine's recent changes to xfs/019 exposed a bug in how libxfs
handles setgid bits.  mkfs reads the desired gid in from the protofile,
but if the parent directory is setgid, it will override the user's
setting and (re)set the child's gid to the parent's gid.  Overriding
user settings is (probably) not the desired mode of operation, so create
a flag to struct cred to force the gid in the protofile.

It looks like this has been broken since ~2005.

Cc: Catherine Hoang <catherine.hoang@oracle.com>
Fixes: 9f064b7e ("Provide mkfs options to easily exercise all inheritable attributes, esp. the extsize allocator hint. Merge of master-melb:xfs-cmds:24370a by kenmcd.")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Catherine Hoang <catherine.hoang@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
include/xfs_inode.h
libxfs/util.c
mkfs/proto.c

index 08a62d833372bfaebad3afe7c0999ac30335dcd5..db9faa57d2510b575ebde61343472f00db456c90 100644 (file)
@@ -164,10 +164,13 @@ static inline bool xfs_inode_has_bigtime(struct xfs_inode *ip)
        return ip->i_diflags2 & XFS_DIFLAG2_BIGTIME;
 }
 
-typedef struct cred {
-       uid_t   cr_uid;
-       gid_t   cr_gid;
-} cred_t;
+/* Always set the child's GID to this value, even if the parent is setgid. */
+#define CRED_FORCE_GID (1U << 0)
+struct cred {
+       uid_t           cr_uid;
+       gid_t           cr_gid;
+       unsigned int    cr_flags;
+};
 
 extern int     libxfs_dir_ialloc (struct xfs_trans **, struct xfs_inode *,
                                mode_t, nlink_t, xfs_dev_t, struct cred *,
index 86deffae24a0f7a89807eb1474e05337a3a551ce..ef01fcf851db91d482e04f11b1818dedee9b3f67 100644 (file)
@@ -271,7 +271,8 @@ libxfs_init_new_inode(
        xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD);
 
        if (pip && (VFS_I(pip)->i_mode & S_ISGID)) {
-               VFS_I(ip)->i_gid = VFS_I(pip)->i_gid;
+               if (!(cr->cr_flags & CRED_FORCE_GID))
+                       VFS_I(ip)->i_gid = VFS_I(pip)->i_gid;
                if ((VFS_I(pip)->i_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR)
                        VFS_I(ip)->i_mode |= S_ISGID;
        }
index ef130ed625a5b5a9e893168d9b92de69ca2570b1..127d87dd4d9445a39e54c1f79a271e4ff54cfddd 100644 (file)
@@ -378,7 +378,7 @@ parseproto(
        xfs_trans_t     *tp;
        int             val;
        int             isroot = 0;
-       cred_t          creds;
+       struct cred     creds;
        char            *value;
        struct xfs_name xname;
 
@@ -446,6 +446,7 @@ parseproto(
        mode |= val;
        creds.cr_uid = (int)getnum(getstr(pp), 0, 0, false);
        creds.cr_gid = (int)getnum(getstr(pp), 0, 0, false);
+       creds.cr_flags = CRED_FORCE_GID;
        xname.name = (unsigned char *)name;
        xname.len = name ? strlen(name) : 0;
        xname.type = 0;