posix_acl: Clear SGID bit when setting file permissions
commit 073931017b49d9458aa351605b43a7e34598caef upstream. When file permissions are modified via chmod(2) and the user is not in the owning group or capable of CAP_FSETID, the setgid bit is cleared in inode_change_ok(). Setting a POSIX ACL via setxattr(2) sets the file permissions as well as the new ACL, but doesn't clear the setgid bit in a similar way; this allows to bypass the check in chmod(2). Fix that. Change-Id: Ibd68b4b3a43a463b55032442a879219001008f46
This commit is contained in:
parent
0a98a537be
commit
bdc15f09d9
|
@ -205,15 +205,11 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
|
|||
case ACL_TYPE_ACCESS:
|
||||
name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
|
||||
if (acl) {
|
||||
error = posix_acl_equiv_mode(acl, &inode->i_mode);
|
||||
error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
|
||||
if (error < 0)
|
||||
return error;
|
||||
else {
|
||||
inode->i_ctime = CURRENT_TIME_SEC;
|
||||
ext3_mark_inode_dirty(handle, inode);
|
||||
if (error == 0)
|
||||
acl = NULL;
|
||||
}
|
||||
inode->i_ctime = CURRENT_TIME_SEC;
|
||||
ext3_mark_inode_dirty(handle, inode);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -267,14 +267,14 @@ static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
|
|||
goto out_release;
|
||||
|
||||
if (type == ACL_TYPE_ACCESS) {
|
||||
umode_t mode;
|
||||
umode_t mode = inode->i_mode;
|
||||
struct posix_acl *old_acl = acl;
|
||||
|
||||
error = posix_acl_update_mode(inode, &mode, &acl);
|
||||
if (error < 0)
|
||||
goto out_release;
|
||||
if (!acl)
|
||||
posix_acl_release(old_acl);
|
||||
if (error)
|
||||
goto out_release;
|
||||
|
||||
error = gfs2_set_mode(inode, mode);
|
||||
if (error)
|
||||
|
|
|
@ -694,7 +694,6 @@ static int can_set_system_xattr(struct inode *inode, const char *name,
|
|||
}
|
||||
if (acl) {
|
||||
struct posix_acl *old_acl = acl;
|
||||
|
||||
rc = posix_acl_update_mode(inode, &inode->i_mode, &acl);
|
||||
posix_acl_release(old_acl);
|
||||
if (rc < 0) {
|
||||
|
|
|
@ -275,19 +275,13 @@ static int ocfs2_set_acl(handle_t *handle,
|
|||
name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
|
||||
if (acl) {
|
||||
umode_t mode;
|
||||
|
||||
ret = posix_acl_update_mode(inode, &mode, &acl);
|
||||
if (ret)
|
||||
return ret;
|
||||
else {
|
||||
if (ret == 0)
|
||||
acl = NULL;
|
||||
|
||||
ret = ocfs2_acl_set_mode(inode, di_bh,
|
||||
handle, mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = ocfs2_acl_set_mode(inode, di_bh,
|
||||
handle, mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
|
|
|
@ -407,24 +407,6 @@ posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p)
|
|||
}
|
||||
EXPORT_SYMBOL(posix_acl_create);
|
||||
|
||||
int
|
||||
posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode)
|
||||
{
|
||||
struct posix_acl *clone = posix_acl_clone(*acl, gfp);
|
||||
int err = -ENOMEM;
|
||||
if (clone) {
|
||||
err = posix_acl_chmod_masq(clone, mode);
|
||||
if (err) {
|
||||
posix_acl_release(clone);
|
||||
clone = NULL;
|
||||
}
|
||||
}
|
||||
posix_acl_release(*acl);
|
||||
*acl = clone;
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(posix_acl_chmod);
|
||||
|
||||
/**
|
||||
* posix_acl_update_mode - update mode in set_acl
|
||||
*
|
||||
|
@ -455,3 +437,21 @@ int posix_acl_update_mode(struct inode *inode, umode_t *mode_p,
|
|||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(posix_acl_update_mode);
|
||||
|
||||
int
|
||||
posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode)
|
||||
{
|
||||
struct posix_acl *clone = posix_acl_clone(*acl, gfp);
|
||||
int err = -ENOMEM;
|
||||
if (clone) {
|
||||
err = posix_acl_chmod_masq(clone, mode);
|
||||
if (err) {
|
||||
posix_acl_release(clone);
|
||||
clone = NULL;
|
||||
}
|
||||
}
|
||||
posix_acl_release(*acl);
|
||||
*acl = clone;
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(posix_acl_chmod);
|
||||
|
|
|
@ -392,10 +392,11 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name,
|
|||
struct posix_acl *old_acl = acl;
|
||||
|
||||
error = posix_acl_update_mode(inode, &mode, &acl);
|
||||
if (!acl)
|
||||
posix_acl_release(old_acl);
|
||||
|
||||
if (error)
|
||||
goto out_release;
|
||||
if (!acl)
|
||||
posix_acl_release(old_acl);
|
||||
|
||||
error = xfs_set_mode(inode, mode);
|
||||
if (error)
|
||||
|
|
Loading…
Reference in New Issue