Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: Correctly lock inode when removing suid and file capabilities

Currently XFS calls file_remove_privs() without holding i_mutex. This is
wrong because that function can end up messing with file permissions and
file capabilities stored in xattrs for which we need i_mutex held.

Fix the problem by grabbing iolock exclusively when we will need to
change anything in permissions / xattrs.

Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

authored by

Jan Kara and committed by
Al Viro
a6de82ca 45f147a1

+10 -1
+10 -1
fs/xfs/xfs_file.c
··· 563 563 if (error) 564 564 return error; 565 565 566 + /* For changing security info in file_remove_privs() we need i_mutex */ 567 + if (*iolock == XFS_IOLOCK_SHARED && !IS_NOSEC(inode)) { 568 + xfs_rw_iunlock(ip, *iolock); 569 + *iolock = XFS_IOLOCK_EXCL; 570 + xfs_rw_ilock(ip, *iolock); 571 + goto restart; 572 + } 566 573 /* 567 574 * If the offset is beyond the size of the file, we need to zero any 568 575 * blocks that fall between the existing EOF and the start of this ··· 630 623 * setgid bits if the process is not being run by root. This keeps 631 624 * people from modifying setuid and setgid binaries. 632 625 */ 633 - return file_remove_privs(file); 626 + if (!IS_NOSEC(inode)) 627 + return file_remove_privs(file); 628 + return 0; 634 629 } 635 630 636 631 /*