Commit 0795e004 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: create structure verifier function for short form symlinks



Create a function to check the structure of short form symlink targets.

Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
parent 1e1bbd8e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -143,5 +143,6 @@ bool xfs_symlink_hdr_ok(xfs_ino_t ino, uint32_t offset,
			uint32_t size, struct xfs_buf *bp);
void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
				 struct xfs_inode *ip, struct xfs_ifork *ifp);
xfs_failaddr_t xfs_symlink_shortform_verify(struct xfs_inode *ip);

#endif /* __XFS_SHARED_H__ */
+34 −0
Original line number Diff line number Diff line
@@ -209,3 +209,37 @@ xfs_symlink_local_to_remote(
	xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsymlink_hdr) +
					ifp->if_bytes - 1);
}

/* Verify the consistency of an inline symlink. */
xfs_failaddr_t
xfs_symlink_shortform_verify(
	struct xfs_inode	*ip)
{
	char			*sfp;
	char			*endp;
	struct xfs_ifork	*ifp;
	int			size;

	ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL);
	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
	sfp = (char *)ifp->if_u1.if_data;
	size = ifp->if_bytes;
	endp = sfp + size;

	/* Zero length symlinks can exist while we're deleting a remote one. */
	if (size == 0)
		return NULL;

	/* No negative sizes or overly long symlink targets. */
	if (size < 0 || size > XFS_SYMLINK_MAXLEN)
		return __this_address;

	/* No NULLs in the target either. */
	if (memchr(sfp, 0, size - 1))
		return __this_address;

	/* We /did/ null-terminate the buffer, right? */
	if (*endp != 0)
		return __this_address;
	return NULL;
}