diff --git a/include/xfs_inode.h b/include/xfs_inode.h index ccf72d4a636a248303aa782896d6d7f661d12931..d7001937f9679e13492851d205c9e216e5cfa704 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 fd4906f8e98d72b7c1b276df3fe4c1ccfa277921..97413761e5f759067f755eeb32030238deb062be 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 3bba49171983a0bc3475152083c71f4331a6cdd8..b15f7652e56c5880d6ca0da9d1f7c735e835b600 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;