Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61db68e8 authored by Jan Kara's avatar Jan Kara Committed by Amit Pundir
Browse files

BACKPORT: posix_acl: Clear SGID bit when setting file permissions



(cherry pick from commit 073931017b49d9458aa351605b43a7e34598caef)

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.

NB: conflicts resolution included extending the change to all visible
    users of the near deprecated function posix_acl_equiv_mode
    replaced with posix_acl_update_mode. We did not resolve the ACL
    leak in this CL, require additional upstream fixes.

References: CVE-2016-7097
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
Bug: 32458736
Change-Id: I19591ad452cc825ac282b3cfd2daaa72aa9a1ac1
parent f524fae4
Loading
Loading
Loading
Loading
+17 −23
Original line number Diff line number Diff line
@@ -320,25 +320,20 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
	case ACL_TYPE_ACCESS:
		name = POSIX_ACL_XATTR_ACCESS;
		if (acl) {
			umode_t mode = inode->i_mode;
			retval = posix_acl_equiv_mode(acl, &mode);
			if (retval < 0)
				goto err_out;
			else {
			struct iattr iattr;
				if (retval == 0) {

			retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
			if (retval)
				goto err_out;
			if (!acl) {
				/*
				 * ACL can be represented
				 * by the mode bits. So don't
				 * update ACL.
				 */
					acl = NULL;
				value = NULL;
				size = 0;
			}
				/* Updte the mode bits */
				iattr.ia_mode = ((mode & S_IALLUGO) |
						 (inode->i_mode & ~S_IALLUGO));
			iattr.ia_valid = ATTR_MODE;
			/* FIXME should we update ctime ?
			 * What is the following setxattr update the
@@ -346,7 +341,6 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
			 */
			v9fs_vfs_setattr_dotl(dentry, &iattr);
		}
		}
		break;
	case ACL_TYPE_DEFAULT:
		name = POSIX_ACL_XATTR_DEFAULT;
+2 −4
Original line number Diff line number Diff line
@@ -83,11 +83,9 @@ static int __btrfs_set_acl(struct btrfs_trans_handle *trans,
	case ACL_TYPE_ACCESS:
		name = POSIX_ACL_XATTR_ACCESS;
		if (acl) {
			ret = posix_acl_equiv_mode(acl, &inode->i_mode);
			if (ret < 0)
			ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
			if (ret)
				return ret;
			if (ret == 0)
				acl = NULL;
		}
		ret = 0;
		break;
+2 −4
Original line number Diff line number Diff line
@@ -108,11 +108,9 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
	case ACL_TYPE_ACCESS:
		name = POSIX_ACL_XATTR_ACCESS;
		if (acl) {
			ret = posix_acl_equiv_mode(acl, &new_mode);
			if (ret < 0)
			ret = posix_acl_update_mode(inode, &new_mode, &acl);
			if (ret)
				goto out;
			if (ret == 0)
				acl = NULL;
		}
		break;
	case ACL_TYPE_DEFAULT:
+4 −8
Original line number Diff line number Diff line
@@ -193,15 +193,11 @@ ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
		case ACL_TYPE_ACCESS:
			name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
			if (acl) {
				error = posix_acl_equiv_mode(acl, &inode->i_mode);
				if (error < 0)
				error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
				if (error)
					return error;
				else {
				inode->i_ctime = CURRENT_TIME_SEC;
				mark_inode_dirty(inode);
					if (error == 0)
						acl = NULL;
				}
			}
			break;

+4 −8
Original line number Diff line number Diff line
@@ -195,15 +195,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);
				if (error < 0)
				error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
				if (error)
					return error;
				else {
				inode->i_ctime = CURRENT_TIME_SEC;
				ext3_mark_inode_dirty(handle, inode);
					if (error == 0)
						acl = NULL;
				}
			}
			break;

Loading