From 1c035be269406d31046f7968b0127be03ae39aa7 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 17 May 2022 22:48:13 -0400 Subject: [PATCH] mkfs: don't trample the gid set in the protofile 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 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 Reviewed-by: Catherine Hoang Reviewed-by: Christoph Hellwig Reviewed-by: Christoph Hellwig Signed-off-by: Eric Sandeen Signed-off-by: Hongnan Li --- include/xfs_inode.h | 11 +++++++---- libxfs/util.c | 3 ++- mkfs/proto.c | 3 ++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/xfs_inode.h b/include/xfs_inode.h index ccf72d4a..d7001937 100644 --- a/include/xfs_inode.h +++ b/include/xfs_inode.h @@ -151,10 +151,13 @@ static inline bool xfs_inode_has_bigtime(struct xfs_inode *ip) return ip->i_d.di_flags2 & 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_inode_alloc (struct xfs_trans **, struct xfs_inode *, mode_t, nlink_t, xfs_dev_t, struct cred *, diff --git a/libxfs/util.c b/libxfs/util.c index fd4906f8..97413761 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -301,7 +301,8 @@ libxfs_ialloc( } if (pip && (VFS_I(pip)->i_mode & S_ISGID)) { - ip->i_d.di_gid = pip->i_d.di_gid; + if (!(cr->cr_flags & CRED_FORCE_GID)) + ip->i_d.di_gid = pip->i_d.di_gid; if ((VFS_I(pip)->i_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR) VFS_I(ip)->i_mode |= S_ISGID; } diff --git a/mkfs/proto.c b/mkfs/proto.c index 3bba4917..b15f7652 100644 --- a/mkfs/proto.c +++ b/mkfs/proto.c @@ -360,7 +360,7 @@ parseproto( xfs_trans_t *tp; int val; int isroot = 0; - cred_t creds; + struct cred_t creds; char *value; struct xfs_name xname; @@ -428,6 +428,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; -- Gitee