All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: Brian Foster <bfoster@redhat.com>
Cc: linux-xfs@vger.kernel.org
Subject: Re: [PATCH v2 1/3] xfs: more robust recovery xlog buffer validation
Date: Wed, 25 Oct 2017 15:12:08 -0700	[thread overview]
Message-ID: <20171025221208.GS5483@magnolia> (raw)
In-Reply-To: <20171025185705.64983-2-bfoster@redhat.com>

On Wed, Oct 25, 2017 at 02:57:03PM -0400, Brian Foster wrote:
> mkfs has a historical problem where it can format very small
> filesystems with too small of a physical log. Under certain
> conditions, log recovery of an associated filesystem can end up
> passing garbage parameter values to some of the cycle and log record
> verification functions due to bugs in log recovery not dealing with
> such filesystems properly. This results in attempts to read from
> bogus/underflowed log block addresses.
> 
> Since the buffer read may ultimately succeed, log recovery can
> proceed with bogus data and otherwise go off the rails and crash.
> One example of this is a negative last_blk being passed to
> xlog_find_verify_log_record() causing us to skip the loop, pass a
> NULL head pointer to xlog_header_check_mount() and crash.
> 
> Improve the xlog buffer verification to address this problem. We
> already verify xlog buffer length, so update this mechanism to also
> sanity check for a valid log relative block address and otherwise
> return an error. Pass a fixed, valid log block address from
> xlog_get_bp() since the target address will be validated when the
> buffer is read. This ensures that any bogus log block address/length
> calculations lead to graceful mount failure rather than risking a
> crash or worse if recovery proceeds with bogus data.
> 
> Reported-by: Zorro Lang <zlang@redhat.com>
> Signed-off-by: Brian Foster <bfoster@redhat.com>
> ---
>  fs/xfs/xfs_log_recover.c | 38 ++++++++++++++++++++++++--------------
>  1 file changed, 24 insertions(+), 14 deletions(-)
> 
> diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
> index ee34899..54494ab 100644
> --- a/fs/xfs/xfs_log_recover.c
> +++ b/fs/xfs/xfs_log_recover.c
> @@ -85,17 +85,21 @@ struct xfs_buf_cancel {
>   */
>  
>  /*
> - * Verify the given count of basic blocks is valid number of blocks
> - * to specify for an operation involving the given XFS log buffer.
> - * Returns nonzero if the count is valid, 0 otherwise.
> + * Verify the log-relative block number and length in basic blocks are valid for
> + * an operation involving the given XFS log buffer. Returns true if the fields
> + * are valid, false otherwise.
>   */
> -
> -static inline int
> -xlog_buf_bbcount_valid(
> +static inline bool
> +xlog_verify_bp(
>  	struct xlog	*log,
> +	xfs_daddr_t	blk_no,
>  	int		bbcount)
>  {
> -	return bbcount > 0 && bbcount <= log->l_logBBsize;
> +	if (blk_no < 0 || blk_no >= log->l_logBBsize)
> +		return false;
> +	if (bbcount <= 0 || bbcount > log->l_logBBsize)
> +		return false;

Shouldn't this be (blk_no + bbcount) > log->l_logBBsize, since the
blk_no/bbcount parameters identify an extent within the log?

--D

> +	return true;
>  }
>  
>  /*
> @@ -110,7 +114,11 @@ xlog_get_bp(
>  {
>  	struct xfs_buf	*bp;
>  
> -	if (!xlog_buf_bbcount_valid(log, nbblks)) {
> +	/*
> +	 * Pass log block 0 since we don't have an addr yet, buffer will be
> +	 * verified on read.
> +	 */
> +	if (!xlog_verify_bp(log, 0, nbblks)) {
>  		xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",
>  			nbblks);
>  		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);
> @@ -180,9 +188,10 @@ xlog_bread_noalign(
>  {
>  	int		error;
>  
> -	if (!xlog_buf_bbcount_valid(log, nbblks)) {
> -		xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",
> -			nbblks);
> +	if (!xlog_verify_bp(log, blk_no, nbblks)) {
> +		xfs_warn(log->l_mp,
> +			 "Invalid log block/length (0x%llx, 0x%x) for buffer",
> +			 blk_no, nbblks);
>  		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);
>  		return -EFSCORRUPTED;
>  	}
> @@ -265,9 +274,10 @@ xlog_bwrite(
>  {
>  	int		error;
>  
> -	if (!xlog_buf_bbcount_valid(log, nbblks)) {
> -		xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",
> -			nbblks);
> +	if (!xlog_verify_bp(log, blk_no, nbblks)) {
> +		xfs_warn(log->l_mp,
> +			 "Invalid log block/length (0x%llx, 0x%x) for buffer",
> +			 blk_no, nbblks);
>  		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);
>  		return -EFSCORRUPTED;
>  	}
> -- 
> 2.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

  reply	other threads:[~2017-10-25 22:12 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-25 18:57 [PATCH v2 0/3] xfs: miscellaneous log recovery fixes Brian Foster
2017-10-25 18:57 ` [PATCH v2 1/3] xfs: more robust recovery xlog buffer validation Brian Foster
2017-10-25 22:12   ` Darrick J. Wong [this message]
2017-10-26 10:21     ` Brian Foster
2017-10-26 13:27   ` [PATCH v3] " Brian Foster
2017-10-26 15:59     ` Darrick J. Wong
2017-10-25 18:57 ` [PATCH v2 2/3] xfs: fix log block underflow during recovery cycle verification Brian Foster
2017-10-25 18:57 ` [PATCH v2 3/3] xfs: drain the buffer LRU on mount Brian Foster
2017-10-26 16:31   ` Darrick J. Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171025221208.GS5483@magnolia \
    --to=darrick.wong@oracle.com \
    --cc=bfoster@redhat.com \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.