Re: Bug report: KFIFO kfifo_init() may introduce buffer overflow

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

 



On Thu, Aug 29, 2019 at 12:32:41PM -0700, Linus Torvalds wrote:
> On Thu, Aug 29, 2019 at 11:48 AM Linus Torvalds
> <torvalds@xxxxxxxxxxxxxxxxxxxx> wrote:
> >
> > Anybody?
> 
> This is ENTIRELY UNTESTED.
> 
> Anybody willing to test and take ownership?

I don't know this code at all, but note below...

> 
>               Linus

>  include/linux/kfifo.h | 12 ++++++++----
>  lib/kfifo.c           |  4 +++-
>  2 files changed, 11 insertions(+), 5 deletions(-)
> 
> diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
> index fc4b0b10210f..078f52c20aad 100644
> --- a/include/linux/kfifo.h
> +++ b/include/linux/kfifo.h
> @@ -117,6 +117,12 @@ struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PTR(unsigned char, 2, void);
>   */
>  #define DECLARE_KFIFO(fifo, type, size)	STRUCT_KFIFO(type, size) fifo
>  
> +#define VERIFY_POWER_OF2(x) \
> +	((x)+BUILD_BUG_ON_ZERO((x) & ((x)-1)))
> +
> +#define __KFIFO_MASK_SIZE(fifo) \
> +	(__is_kfifo_ptr(&(fifo)) ? 0 : VERIFY_POWER_OF2(ARRAY_SIZE((fifo).buf)) - 1)
> +
>  /**
>   * INIT_KFIFO - Initialize a fifo declared by DECLARE_KFIFO
>   * @fifo: name of the declared fifo datatype
> @@ -127,7 +133,7 @@ struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PTR(unsigned char, 2, void);
>  	struct __kfifo *__kfifo = &__tmp->kfifo; \
>  	__kfifo->in = 0; \
>  	__kfifo->out = 0; \
> -	__kfifo->mask = __is_kfifo_ptr(__tmp) ? 0 : ARRAY_SIZE(__tmp->buf) - 1;\
> +	__kfifo->mask = __KFIFO_MASK_SIZE(fifo); \

I think this should be:

+	__kfifo->mask = __KFIFO_MASK_SIZE(*__tmp); \

? I didn't compile it, but I saw the others were using (fifo).buf but
this was using __tmp->buf.

>  	__kfifo->esize = sizeof(*__tmp->buf); \
>  	__kfifo->data = __is_kfifo_ptr(__tmp) ?  NULL : __tmp->buf; \
>  })
> @@ -147,9 +153,7 @@ struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PTR(unsigned char, 2, void);
>  			{ \
>  			.in	= 0, \
>  			.out	= 0, \
> -			.mask	= __is_kfifo_ptr(&(fifo)) ? \
> -				  0 : \
> -				  ARRAY_SIZE((fifo).buf) - 1, \
> +			.mask	= __KFIFO_MASK_SIZE(fifo), \
>  			.esize	= sizeof(*(fifo).buf), \
>  			.data	= __is_kfifo_ptr(&(fifo)) ? \
>  				NULL : \
> diff --git a/lib/kfifo.c b/lib/kfifo.c
> index 117ad0e7fbf4..7f145cb41e6d 100644
> --- a/lib/kfifo.c
> +++ b/lib/kfifo.c
> @@ -68,7 +68,9 @@ int __kfifo_init(struct __kfifo *fifo, void *buffer,
>  {
>  	size /= esize;
>  
> -	size = roundup_pow_of_two(size);
> +	/* Warn because we had a bug here and would round up */
> +	if (WARN_ON_ONCE(!is_power_of_2(size)))
> +		size = rounddown_pow_of_two(size);
>  
>  	fifo->in = 0;
>  	fifo->out = 0;


-- 
Kees Cook



[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux