[PATCH 1/4] xfs: fix multiple problems when doing getparents by handle

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Darrick J. Wong <djwong@xxxxxxxxxx>

Fix a few problems in the file handle processing part of GETPARENTS.
First, we need to validate that the fsid of the handle matches the
filesystem that we're talking to.  Second, we can skip the iget if the
inode number matches the open file.  Third, if we are going to do the
iget file, we need to use an UNTRUSTED lookup to guard against crap.
Finally, we mustn't leak any inodes that we iget.

Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>
---
 fs/xfs/xfs_ioctl.c |   30 +++++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)


diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index df5a45b97f8f..a1929b08c539 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1694,8 +1694,9 @@ xfs_ioc_get_parent_pointer(
 {
 	struct xfs_pptr_info		*ppi = NULL;
 	int				error = 0;
-	struct xfs_inode		*ip = XFS_I(file_inode(filp));
-	struct xfs_mount		*mp = ip->i_mount;
+	struct xfs_inode		*file_ip = XFS_I(file_inode(filp));
+	struct xfs_inode		*call_ip = file_ip;
+	struct xfs_mount		*mp = file_ip->i_mount;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
@@ -1733,23 +1734,32 @@ xfs_ioc_get_parent_pointer(
 		return -ENOMEM;
 
 	if (ppi->pi_flags & XFS_PPTR_IFLAG_HANDLE) {
-		error = xfs_iget(mp, NULL, ppi->pi_handle.ha_fid.fid_ino,
-				0, 0, &ip);
-		if (error)
+		struct xfs_handle	*hanp = &ppi->pi_handle;
+
+		if (memcmp(&hanp->ha_fsid, mp->m_fixedfsid,
+							sizeof(xfs_fsid_t))) {
+			error = -EINVAL;
 			goto out;
+		}
 
-		if (VFS_I(ip)->i_generation != ppi->pi_handle.ha_fid.fid_gen) {
+		if (hanp->ha_fid.fid_ino != file_ip->i_ino) {
+			error = xfs_iget(mp, NULL, hanp->ha_fid.fid_ino,
+					XFS_IGET_UNTRUSTED, 0, &call_ip);
+			if (error)
+				goto out;
+		}
+
+		if (VFS_I(call_ip)->i_generation != hanp->ha_fid.fid_gen) {
 			error = -EINVAL;
 			goto out;
 		}
 	}
 
-	if (ip->i_ino == mp->m_sb.sb_rootino)
+	if (call_ip->i_ino == mp->m_sb.sb_rootino)
 		ppi->pi_flags |= XFS_PPTR_OFLAG_ROOT;
 
 	/* Get the parent pointers */
-	error = xfs_attr_get_parent_pointer(ip, ppi);
-
+	error = xfs_attr_get_parent_pointer(call_ip, ppi);
 	if (error)
 		goto out;
 
@@ -1762,6 +1772,8 @@ xfs_ioc_get_parent_pointer(
 	}
 
 out:
+	if (call_ip != file_ip)
+		xfs_irele(call_ip);
 	kmem_free(ppi);
 	return error;
 }




[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux