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? 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); \ __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;