mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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: Christoph Hellwig <hch@lst.de> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
This commit is contained in:
		
							parent
							
								
									5d3ddd84ea
								
							
						
					
					
						commit
						073931017b
					
				
					 16 changed files with 89 additions and 102 deletions
				
			
		
							
								
								
									
										40
									
								
								fs/9p/acl.c
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								fs/9p/acl.c
									
									
									
									
									
								
							| 
						 | 
					@ -276,32 +276,26 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
 | 
				
			||||||
	switch (handler->flags) {
 | 
						switch (handler->flags) {
 | 
				
			||||||
	case ACL_TYPE_ACCESS:
 | 
						case ACL_TYPE_ACCESS:
 | 
				
			||||||
		if (acl) {
 | 
							if (acl) {
 | 
				
			||||||
			umode_t mode = inode->i_mode;
 | 
								struct iattr iattr;
 | 
				
			||||||
			retval = posix_acl_equiv_mode(acl, &mode);
 | 
					
 | 
				
			||||||
			if (retval < 0)
 | 
								retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
 | 
				
			||||||
 | 
								if (retval)
 | 
				
			||||||
				goto err_out;
 | 
									goto err_out;
 | 
				
			||||||
			else {
 | 
								if (!acl) {
 | 
				
			||||||
				struct iattr iattr;
 | 
									/*
 | 
				
			||||||
				if (retval == 0) {
 | 
									 * ACL can be represented
 | 
				
			||||||
					/*
 | 
									 * by the mode bits. So don't
 | 
				
			||||||
					 * ACL can be represented
 | 
									 * update ACL.
 | 
				
			||||||
					 * 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
 | 
					 | 
				
			||||||
				 * mode ?
 | 
					 | 
				
			||||||
				 */
 | 
									 */
 | 
				
			||||||
				v9fs_vfs_setattr_dotl(dentry, &iattr);
 | 
									value = NULL;
 | 
				
			||||||
 | 
									size = 0;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								iattr.ia_valid = ATTR_MODE;
 | 
				
			||||||
 | 
								/* FIXME should we update ctime ?
 | 
				
			||||||
 | 
								 * What is the following setxattr update the
 | 
				
			||||||
 | 
								 * mode ?
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								v9fs_vfs_setattr_dotl(dentry, &iattr);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case ACL_TYPE_DEFAULT:
 | 
						case ACL_TYPE_DEFAULT:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,11 +79,9 @@ static int __btrfs_set_acl(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	case ACL_TYPE_ACCESS:
 | 
						case ACL_TYPE_ACCESS:
 | 
				
			||||||
		name = XATTR_NAME_POSIX_ACL_ACCESS;
 | 
							name = XATTR_NAME_POSIX_ACL_ACCESS;
 | 
				
			||||||
		if (acl) {
 | 
							if (acl) {
 | 
				
			||||||
			ret = posix_acl_equiv_mode(acl, &inode->i_mode);
 | 
								ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
 | 
				
			||||||
			if (ret < 0)
 | 
								if (ret)
 | 
				
			||||||
				return ret;
 | 
									return ret;
 | 
				
			||||||
			if (ret == 0)
 | 
					 | 
				
			||||||
				acl = NULL;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ret = 0;
 | 
							ret = 0;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,11 +95,9 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 | 
				
			||||||
	case ACL_TYPE_ACCESS:
 | 
						case ACL_TYPE_ACCESS:
 | 
				
			||||||
		name = XATTR_NAME_POSIX_ACL_ACCESS;
 | 
							name = XATTR_NAME_POSIX_ACL_ACCESS;
 | 
				
			||||||
		if (acl) {
 | 
							if (acl) {
 | 
				
			||||||
			ret = posix_acl_equiv_mode(acl, &new_mode);
 | 
								ret = posix_acl_update_mode(inode, &new_mode, &acl);
 | 
				
			||||||
			if (ret < 0)
 | 
								if (ret)
 | 
				
			||||||
				goto out;
 | 
									goto out;
 | 
				
			||||||
			if (ret == 0)
 | 
					 | 
				
			||||||
				acl = NULL;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case ACL_TYPE_DEFAULT:
 | 
						case ACL_TYPE_DEFAULT:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -190,15 +190,11 @@ ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 | 
				
			||||||
		case ACL_TYPE_ACCESS:
 | 
							case ACL_TYPE_ACCESS:
 | 
				
			||||||
			name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
 | 
								name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
 | 
				
			||||||
			if (acl) {
 | 
								if (acl) {
 | 
				
			||||||
				error = posix_acl_equiv_mode(acl, &inode->i_mode);
 | 
									error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
 | 
				
			||||||
				if (error < 0)
 | 
									if (error)
 | 
				
			||||||
					return error;
 | 
										return error;
 | 
				
			||||||
				else {
 | 
									inode->i_ctime = CURRENT_TIME_SEC;
 | 
				
			||||||
					inode->i_ctime = CURRENT_TIME_SEC;
 | 
									mark_inode_dirty(inode);
 | 
				
			||||||
					mark_inode_dirty(inode);
 | 
					 | 
				
			||||||
					if (error == 0)
 | 
					 | 
				
			||||||
						acl = NULL;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -193,15 +193,11 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type,
 | 
				
			||||||
	case ACL_TYPE_ACCESS:
 | 
						case ACL_TYPE_ACCESS:
 | 
				
			||||||
		name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
 | 
							name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
 | 
				
			||||||
		if (acl) {
 | 
							if (acl) {
 | 
				
			||||||
			error = posix_acl_equiv_mode(acl, &inode->i_mode);
 | 
								error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
 | 
				
			||||||
			if (error < 0)
 | 
								if (error)
 | 
				
			||||||
				return error;
 | 
									return error;
 | 
				
			||||||
			else {
 | 
								inode->i_ctime = ext4_current_time(inode);
 | 
				
			||||||
				inode->i_ctime = ext4_current_time(inode);
 | 
								ext4_mark_inode_dirty(handle, inode);
 | 
				
			||||||
				ext4_mark_inode_dirty(handle, inode);
 | 
					 | 
				
			||||||
				if (error == 0)
 | 
					 | 
				
			||||||
					acl = NULL;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -210,12 +210,10 @@ static int __f2fs_set_acl(struct inode *inode, int type,
 | 
				
			||||||
	case ACL_TYPE_ACCESS:
 | 
						case ACL_TYPE_ACCESS:
 | 
				
			||||||
		name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
 | 
							name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
 | 
				
			||||||
		if (acl) {
 | 
							if (acl) {
 | 
				
			||||||
			error = posix_acl_equiv_mode(acl, &inode->i_mode);
 | 
								error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
 | 
				
			||||||
			if (error < 0)
 | 
								if (error)
 | 
				
			||||||
				return error;
 | 
									return error;
 | 
				
			||||||
			set_acl_inode(inode, inode->i_mode);
 | 
								set_acl_inode(inode, inode->i_mode);
 | 
				
			||||||
			if (error == 0)
 | 
					 | 
				
			||||||
				acl = NULL;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,17 +92,11 @@ int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 | 
				
			||||||
	if (type == ACL_TYPE_ACCESS) {
 | 
						if (type == ACL_TYPE_ACCESS) {
 | 
				
			||||||
		umode_t mode = inode->i_mode;
 | 
							umode_t mode = inode->i_mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		error = posix_acl_equiv_mode(acl, &mode);
 | 
							error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
 | 
				
			||||||
		if (error < 0)
 | 
							if (error)
 | 
				
			||||||
			return error;
 | 
								return error;
 | 
				
			||||||
 | 
							if (mode != inode->i_mode)
 | 
				
			||||||
		if (error == 0)
 | 
					 | 
				
			||||||
			acl = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (mode != inode->i_mode) {
 | 
					 | 
				
			||||||
			inode->i_mode = mode;
 | 
					 | 
				
			||||||
			mark_inode_dirty(inode);
 | 
								mark_inode_dirty(inode);
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (acl) {
 | 
						if (acl) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,8 +65,8 @@ int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
 | 
				
			||||||
	case ACL_TYPE_ACCESS:
 | 
						case ACL_TYPE_ACCESS:
 | 
				
			||||||
		xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
 | 
							xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
 | 
				
			||||||
		if (acl) {
 | 
							if (acl) {
 | 
				
			||||||
			err = posix_acl_equiv_mode(acl, &inode->i_mode);
 | 
								err = posix_acl_update_mode(inode, &inode->i_mode, &acl);
 | 
				
			||||||
			if (err < 0)
 | 
								if (err)
 | 
				
			||||||
				return err;
 | 
									return err;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		err = 0;
 | 
							err = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -233,9 +233,10 @@ int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 | 
				
			||||||
	case ACL_TYPE_ACCESS:
 | 
						case ACL_TYPE_ACCESS:
 | 
				
			||||||
		xprefix = JFFS2_XPREFIX_ACL_ACCESS;
 | 
							xprefix = JFFS2_XPREFIX_ACL_ACCESS;
 | 
				
			||||||
		if (acl) {
 | 
							if (acl) {
 | 
				
			||||||
			umode_t mode = inode->i_mode;
 | 
								umode_t mode;
 | 
				
			||||||
			rc = posix_acl_equiv_mode(acl, &mode);
 | 
					
 | 
				
			||||||
			if (rc < 0)
 | 
								rc = posix_acl_update_mode(inode, &mode, &acl);
 | 
				
			||||||
 | 
								if (rc)
 | 
				
			||||||
				return rc;
 | 
									return rc;
 | 
				
			||||||
			if (inode->i_mode != mode) {
 | 
								if (inode->i_mode != mode) {
 | 
				
			||||||
				struct iattr attr;
 | 
									struct iattr attr;
 | 
				
			||||||
| 
						 | 
					@ -247,8 +248,6 @@ int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 | 
				
			||||||
				if (rc < 0)
 | 
									if (rc < 0)
 | 
				
			||||||
					return rc;
 | 
										return rc;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (rc == 0)
 | 
					 | 
				
			||||||
				acl = NULL;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case ACL_TYPE_DEFAULT:
 | 
						case ACL_TYPE_DEFAULT:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,13 +78,11 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
 | 
				
			||||||
	case ACL_TYPE_ACCESS:
 | 
						case ACL_TYPE_ACCESS:
 | 
				
			||||||
		ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
 | 
							ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
 | 
				
			||||||
		if (acl) {
 | 
							if (acl) {
 | 
				
			||||||
			rc = posix_acl_equiv_mode(acl, &inode->i_mode);
 | 
								rc = posix_acl_update_mode(inode, &inode->i_mode, &acl);
 | 
				
			||||||
			if (rc < 0)
 | 
								if (rc)
 | 
				
			||||||
				return rc;
 | 
									return rc;
 | 
				
			||||||
			inode->i_ctime = CURRENT_TIME;
 | 
								inode->i_ctime = CURRENT_TIME;
 | 
				
			||||||
			mark_inode_dirty(inode);
 | 
								mark_inode_dirty(inode);
 | 
				
			||||||
			if (rc == 0)
 | 
					 | 
				
			||||||
				acl = NULL;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case ACL_TYPE_DEFAULT:
 | 
						case ACL_TYPE_DEFAULT:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -241,13 +241,11 @@ int ocfs2_set_acl(handle_t *handle,
 | 
				
			||||||
	case ACL_TYPE_ACCESS:
 | 
						case ACL_TYPE_ACCESS:
 | 
				
			||||||
		name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
 | 
							name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
 | 
				
			||||||
		if (acl) {
 | 
							if (acl) {
 | 
				
			||||||
			umode_t mode = inode->i_mode;
 | 
								umode_t mode;
 | 
				
			||||||
			ret = posix_acl_equiv_mode(acl, &mode);
 | 
					 | 
				
			||||||
			if (ret < 0)
 | 
					 | 
				
			||||||
				return ret;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (ret == 0)
 | 
								ret = posix_acl_update_mode(inode, &mode, &acl);
 | 
				
			||||||
				acl = NULL;
 | 
								if (ret)
 | 
				
			||||||
 | 
									return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ret = ocfs2_acl_set_mode(inode, di_bh,
 | 
								ret = ocfs2_acl_set_mode(inode, di_bh,
 | 
				
			||||||
						 handle, mode);
 | 
											 handle, mode);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,14 +73,11 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 | 
				
			||||||
	case ACL_TYPE_ACCESS:
 | 
						case ACL_TYPE_ACCESS:
 | 
				
			||||||
		name = XATTR_NAME_POSIX_ACL_ACCESS;
 | 
							name = XATTR_NAME_POSIX_ACL_ACCESS;
 | 
				
			||||||
		if (acl) {
 | 
							if (acl) {
 | 
				
			||||||
			umode_t mode = inode->i_mode;
 | 
								umode_t mode;
 | 
				
			||||||
			/*
 | 
					
 | 
				
			||||||
			 * can we represent this with the traditional file
 | 
								error = posix_acl_update_mode(inode, &mode, &acl);
 | 
				
			||||||
			 * mode permission bits?
 | 
								if (error) {
 | 
				
			||||||
			 */
 | 
									gossip_err("%s: posix_acl_update_mode err: %d\n",
 | 
				
			||||||
			error = posix_acl_equiv_mode(acl, &mode);
 | 
					 | 
				
			||||||
			if (error < 0) {
 | 
					 | 
				
			||||||
				gossip_err("%s: posix_acl_equiv_mode err: %d\n",
 | 
					 | 
				
			||||||
					   __func__,
 | 
										   __func__,
 | 
				
			||||||
					   error);
 | 
										   error);
 | 
				
			||||||
				return error;
 | 
									return error;
 | 
				
			||||||
| 
						 | 
					@ -90,8 +87,6 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 | 
				
			||||||
				SetModeFlag(orangefs_inode);
 | 
									SetModeFlag(orangefs_inode);
 | 
				
			||||||
			inode->i_mode = mode;
 | 
								inode->i_mode = mode;
 | 
				
			||||||
			mark_inode_dirty_sync(inode);
 | 
								mark_inode_dirty_sync(inode);
 | 
				
			||||||
			if (error == 0)
 | 
					 | 
				
			||||||
				acl = NULL;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case ACL_TYPE_DEFAULT:
 | 
						case ACL_TYPE_DEFAULT:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -626,6 +626,37 @@ posix_acl_create(struct inode *dir, umode_t *mode,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(posix_acl_create);
 | 
					EXPORT_SYMBOL_GPL(posix_acl_create);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * posix_acl_update_mode  -  update mode in set_acl
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Update the file mode when setting an ACL: compute the new file permission
 | 
				
			||||||
 | 
					 * bits based on the ACL.  In addition, if the ACL is equivalent to the new
 | 
				
			||||||
 | 
					 * file mode, set *acl to NULL to indicate that no ACL should be set.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * As with chmod, clear the setgit bit if the caller is not in the owning group
 | 
				
			||||||
 | 
					 * or capable of CAP_FSETID (see inode_change_ok).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Called from set_acl inode operations.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int posix_acl_update_mode(struct inode *inode, umode_t *mode_p,
 | 
				
			||||||
 | 
								  struct posix_acl **acl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						umode_t mode = inode->i_mode;
 | 
				
			||||||
 | 
						int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						error = posix_acl_equiv_mode(*acl, &mode);
 | 
				
			||||||
 | 
						if (error < 0)
 | 
				
			||||||
 | 
							return error;
 | 
				
			||||||
 | 
						if (error == 0)
 | 
				
			||||||
 | 
							*acl = NULL;
 | 
				
			||||||
 | 
						if (!in_group_p(inode->i_gid) &&
 | 
				
			||||||
 | 
						    !capable_wrt_inode_uidgid(inode, CAP_FSETID))
 | 
				
			||||||
 | 
							mode &= ~S_ISGID;
 | 
				
			||||||
 | 
						*mode_p = mode;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL(posix_acl_update_mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Fix up the uids and gids in posix acl extended attributes in place.
 | 
					 * Fix up the uids and gids in posix acl extended attributes in place.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -242,13 +242,9 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
 | 
				
			||||||
	case ACL_TYPE_ACCESS:
 | 
						case ACL_TYPE_ACCESS:
 | 
				
			||||||
		name = XATTR_NAME_POSIX_ACL_ACCESS;
 | 
							name = XATTR_NAME_POSIX_ACL_ACCESS;
 | 
				
			||||||
		if (acl) {
 | 
							if (acl) {
 | 
				
			||||||
			error = posix_acl_equiv_mode(acl, &inode->i_mode);
 | 
								error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
 | 
				
			||||||
			if (error < 0)
 | 
								if (error)
 | 
				
			||||||
				return error;
 | 
									return error;
 | 
				
			||||||
			else {
 | 
					 | 
				
			||||||
				if (error == 0)
 | 
					 | 
				
			||||||
					acl = NULL;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case ACL_TYPE_DEFAULT:
 | 
						case ACL_TYPE_DEFAULT:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -257,16 +257,11 @@ xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 | 
				
			||||||
		return error;
 | 
							return error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (type == ACL_TYPE_ACCESS) {
 | 
						if (type == ACL_TYPE_ACCESS) {
 | 
				
			||||||
		umode_t mode = inode->i_mode;
 | 
							umode_t mode;
 | 
				
			||||||
		error = posix_acl_equiv_mode(acl, &mode);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (error <= 0) {
 | 
					 | 
				
			||||||
			acl = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (error < 0)
 | 
					 | 
				
			||||||
				return error;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							error = posix_acl_update_mode(inode, &mode, &acl);
 | 
				
			||||||
 | 
							if (error)
 | 
				
			||||||
 | 
								return error;
 | 
				
			||||||
		error = xfs_set_mode(inode, mode);
 | 
							error = xfs_set_mode(inode, mode);
 | 
				
			||||||
		if (error)
 | 
							if (error)
 | 
				
			||||||
			return error;
 | 
								return error;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,6 +93,7 @@ extern int set_posix_acl(struct inode *, int, struct posix_acl *);
 | 
				
			||||||
extern int posix_acl_chmod(struct inode *, umode_t);
 | 
					extern int posix_acl_chmod(struct inode *, umode_t);
 | 
				
			||||||
extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **,
 | 
					extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **,
 | 
				
			||||||
		struct posix_acl **);
 | 
							struct posix_acl **);
 | 
				
			||||||
 | 
					extern int posix_acl_update_mode(struct inode *, umode_t *, struct posix_acl **);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int simple_set_acl(struct inode *, struct posix_acl *, int);
 | 
					extern int simple_set_acl(struct inode *, struct posix_acl *, int);
 | 
				
			||||||
extern int simple_acl_create(struct inode *, struct inode *);
 | 
					extern int simple_acl_create(struct inode *, struct inode *);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue