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

Commit b52a360b authored by Carlos Maiolino's avatar Carlos Maiolino Committed by Alex Elder
Browse files

xfs: Fix possible memory corruption in xfs_readlink



Fixes a possible memory corruption when the link is larger than
MAXPATHLEN and XFS_DEBUG is not enabled. This also remove the
S_ISLNK assert, since the inode mode is checked previously in
xfs_readlink_by_handle() and via VFS.

Updated to address concerns raised by Ben Hutchings about the loose
attention paid to 32- vs 64-bit values, and the lack of handling a
potentially negative pathlen value:
 - Changed type of "pathlen" to be xfs_fsize_t, to match that of
   ip->i_d.di_size
 - Added checking for a negative pathlen to the too-long pathlen
   test, and generalized the message that gets reported in that case
   to reflect the change
As a result, if a negative pathlen were encountered, this function
would return EFSCORRUPTED (and would fail an assertion for a debug
build)--just as would a too-long pathlen.

Signed-off-by: default avatarAlex Elder <aelder@sgi.com>
Signed-off-by: default avatarCarlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent 1ea6b8f4
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -112,7 +112,7 @@ xfs_readlink(
	char		*link)
{
	xfs_mount_t	*mp = ip->i_mount;
	int		pathlen;
	xfs_fsize_t	pathlen;
	int		error = 0;

	trace_xfs_readlink(ip);
@@ -122,13 +122,19 @@ xfs_readlink(

	xfs_ilock(ip, XFS_ILOCK_SHARED);

	ASSERT(S_ISLNK(ip->i_d.di_mode));
	ASSERT(ip->i_d.di_size <= MAXPATHLEN);

	pathlen = ip->i_d.di_size;
	if (!pathlen)
		goto out;

	if (pathlen < 0 || pathlen > MAXPATHLEN) {
		xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)",
			 __func__, (unsigned long long) ip->i_ino,
			 (long long) pathlen);
		ASSERT(0);
		return XFS_ERROR(EFSCORRUPTED);
	}


	if (ip->i_df.if_flags & XFS_IFINLINE) {
		memcpy(link, ip->i_df.if_u1.if_data, pathlen);
		link[pathlen] = '\0';