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

Commit 05b2a01e authored by Jan Kara's avatar Jan Kara Committed by Dennis Cagle
Browse files

posix_acl: Clear SGID bit when setting file permissions



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.

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>
Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/


linux.git
Git-commit: 073931017b49d9458aa351605b43a7e34598caef
Change-Id: Idf7cd8d0fb030fedeabd46254e4c4a9c08bce8b5
[d-cagle@codeaurora.org: Resolve merge conflicts and style]
Signed-off-by: default avatarDennis Cagle <d-cagle@codeaurora.org>
parent a21201d2
Loading
Loading
Loading
Loading
+18 −23
Original line number Diff line number Diff line
@@ -320,25 +320,21 @@ 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 +342,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;
+3 −4
Original line number Diff line number Diff line
@@ -83,11 +83,10 @@ 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:
+5 −8
Original line number Diff line number Diff line
@@ -193,15 +193,12 @@ 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;

+5 −8
Original line number Diff line number Diff line
@@ -201,15 +201,12 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type,
	case ACL_TYPE_ACCESS:
		name_index = EXT4_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 = ext4_current_time(inode);
			ext4_mark_inode_dirty(handle, inode);
				if (error == 0)
					acl = NULL;
			}
		}
		break;

Loading