Re: [PATCH 7/9] Guard bvec iteration logic

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

 



On Wed, May 10, 2017 at 07:20:50PM +0400, Dmitry Monakhov wrote:
> Currently if some one try to advance bvec beyond it's size we simply
> dump WARN_ONCE and continue to iterate beyond bvec array boundaries.
> This simply means that we endup dereferencing/corrupting random memory
> region.
> 
> Sane reaction would be to propagate error back to calling context
> But bvec_iter_advance's calling context is not always good for error
> handling. For safity reason let truncate iterator size to zero which
> will break external iteration loop which prevent us from unpredictable
> memory range corruption. And even it caller ignores an error, it will
> corrupt it's own bvecs, not others.
> 
> This patch does:
> - Return error back to caller with hope that it will react on this
> - Truncate iterator size
> 
> Code was added long time ago here 4550dd6c, luckily no one hit it
> in real life :)
> 
> changes since V1:
>  - Replace  BUG_ON with error logic.
> 
> Signed-off-by: Dmitry Monakhov <dmonakhov@xxxxxxxxxx>
> ---
>  drivers/nvdimm/blk.c |  4 +++-
>  drivers/nvdimm/btt.c |  4 +++-
>  include/linux/bio.h  |  8 ++++++--
>  include/linux/bvec.h | 11 ++++++++---
>  4 files changed, 20 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c
> index 0b49336..c82331b 100644
> --- a/drivers/nvdimm/blk.c
> +++ b/drivers/nvdimm/blk.c
> @@ -106,7 +106,9 @@ static int nd_blk_rw_integrity(struct nd_namespace_blk *nsblk,
>  
>  		len -= cur_len;
>  		dev_offset += cur_len;
> -		bvec_iter_advance(bip->bip_vec, &bip->bip_iter, cur_len);
> +		err = bvec_iter_advance(bip->bip_vec, &bip->bip_iter, cur_len);
> +		if (err)
> +			return err;
>  	}
>  
>  	return err;
> diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
> index 3d7a9fe..5a68681 100644
> --- a/drivers/nvdimm/btt.c
> +++ b/drivers/nvdimm/btt.c
> @@ -942,7 +942,9 @@ static int btt_rw_integrity(struct btt *btt, struct bio_integrity_payload *bip,
>  
>  		len -= cur_len;
>  		meta_nsoff += cur_len;
> -		bvec_iter_advance(bip->bip_vec, &bip->bip_iter, cur_len);
> +		ret = bvec_iter_advance(bip->bip_vec, &bip->bip_iter, cur_len);
> +		if (ret)
> +			return ret;
>  	}
>  
>  	return ret;
> diff --git a/include/linux/bio.h b/include/linux/bio.h
> index 1b4ebb4..643ecba 100644
> --- a/include/linux/bio.h
> +++ b/include/linux/bio.h
> @@ -168,8 +168,12 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter,
>  
>  	if (bio_no_advance_iter(bio))
>  		iter->bi_size -= bytes;
> -	else
> -		bvec_iter_advance(bio->bi_io_vec, iter, bytes);
> +	else {
> +		int err;
> +
> +		err = bvec_iter_advance(bio->bi_io_vec, iter, bytes);
> +		/* TODO: It is reasonable to complete bio with error here. */
> +	}
>  }
>  
>  #define __bio_for_each_segment(bvl, bio, iter, start)			\
> diff --git a/include/linux/bvec.h b/include/linux/bvec.h
> index 89b65b8..984a7a8 100644
> --- a/include/linux/bvec.h
> +++ b/include/linux/bvec.h
> @@ -22,6 +22,7 @@
>  
>  #include <linux/kernel.h>
>  #include <linux/bug.h>
> +#include <linux/errno.h>
>  
>  /*
>   * was unsigned short, but we might as well be ready for > 64kB I/O pages
> @@ -66,12 +67,15 @@ struct bvec_iter {
>  	.bv_offset	= bvec_iter_offset((bvec), (iter)),	\
>  })
>  
> -static inline void bvec_iter_advance(const struct bio_vec *bv,
> +static inline int bvec_iter_advance(const struct bio_vec *bv,
>  				     struct bvec_iter *iter,
>  				     unsigned bytes)
>  {
> -	WARN_ONCE(bytes > iter->bi_size,
> -		  "Attempted to advance past end of bvec iter\n");
> +	if (WARN_ONCE(bytes > iter->bi_size,
> +		     "Attempted to advance past end of bvec iter\n")) {
> +		iter->bi_size = 0;
> +		return -EINVAL;
> +	}
>  
>  	while (bytes) {
>  		unsigned iter_len = bvec_iter_len(bv, *iter);
> @@ -86,6 +90,7 @@ static inline void bvec_iter_advance(const struct bio_vec *bv,
>  			iter->bi_idx++;
>  		}
>  	}
> +	return 0;
>  }
>  
>  #define for_each_bvec(bvl, bio_vec, iter, start)			\
> -- 
> 2.9.3
> 

Reviewed-by: Ming Lei <ming.lei@xxxxxxxxxx>

Thanks,
Ming



[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux