kfifo: fix kernel BUG in dma example
PATCH 1/3 kfifo: fix kernel BUG in dma example
The scatterlist is used uninitialized in kfifo_dma_in_prepare(). This triggers the following bug if CONFIG_DEBUG_SG=y:
------------[ cut here ]------------ kernel BUG at include/linux/scatterlist.h:65! invalid opcode: 0000 [#1] PREEMPT SMP ... Call Trace: [<ffffffff810a1eab>] setup_sgl+0x6b/0xe0 [<ffffffffa03d7000>] ? example_init+0x0/0x265 [dma_example] [<ffffffff810a2021>] __kfifo_dma_in_prepare+0x21/0x30 [<ffffffffa03d7124>] example_init+0x124/0x265 [dma_example] [<ffffffff810f9c55>] ? trace_module_notify+0x25/0x370 [<ffffffff81110c6e>] ? free_pages_prepare+0x11e/0x1e0 [<ffffffff8106f2b1>] ? get_parent_ip+0x11/0x50 [<ffffffff810f9c55>] ? trace_module_notify+0x25/0x370 [<ffffffff810b65fd>] ? trace_hardirqs_on+0xd/0x10 [<ffffffff814beade>] ? mutex_unlock+0xe/0x10 [<ffffffff810f9c71>] ? trace_module_notify+0x41/0x370 [<ffffffff810a77d5>] ? __blocking_notifier_call_chain+0x45/0x80 [<ffffffff81137b7a>] ? vfree+0x2a/0x30 [<ffffffff810a6ac3>] ? up_read+0x23/0x40 [<ffffffff810a77f5>] ? __blocking_notifier_call_chain+0x65/0x80 [<ffffffff810001e3>] do_one_initcall+0x43/0x180 [<ffffffff810c577a>] sys_init_module+0xba/0x200 [<ffffffff8103819b>] system_call_fastpath+0x16/0x1b RIP [<ffffffff810a1e31>] setup_sgl_buf+0x1a1/0x1b0 RSP <ffff88006720dc98> ---[ end trace a72b979fd3c1d3a5 ]---
Add the proper initialization to avoid the bug.
--- samples/kfifo/dma-example.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
samples/kfifo/dma-example.c +1 -0
@@ -45,6 +45,7 @@ static int __init example_init(void)printk (KERN_INFO "queue len: %u\n" ,kfifo_len (&fifo)); +sg_init_table (sg,ARRAY_SIZE (sg)); ret =kfifo_dma_in_prepare (&fifo, sg,ARRAY_SIZE (sg),FIFO_SIZE );printk (KERN_INFO "DMA sgl entries: %d\n" , ret);
Signature · 1 line
1.7.0.4
PATCH 2/3 kfifo: fix a memory leak in dma example
We use a dynamically allocated kfifo in the dma example, so we need to free it when unloading the module.
--- samples/kfifo/dma-example.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-)
samples/kfifo/dma-example.c +1 -3
@@ -105,9 +105,7 @@ static int __init example_init(void) static void __exit example_exit(void) { -#ifdef DYNAMIC -kfifo_free (&test); -#endif +kfifo_free (&fifo); }module_init (example_init);
Signature · 1 line
1.7.0.4
Re: [PATCH 2/3] kfifo: fix a memory leak in dma example
We use a dynamically allocated kfifo in the dma example, so we need to free it when unloading the module.
--- samples/kfifo/dma-example.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-)
samples/kfifo/dma-example.c +1 -3
@@ -105,9 +105,7 @@ static int __init example_init(void) static void __exit example_exit(void) { -#ifdef DYNAMIC -kfifo_free (&test); -#endif +kfifo_free (&fifo); }module_init (example_init);
PATCH 3/3 kfifo: add explicit error checking in all the examples
In reply to Andrea RighiProvide a check in all the kfifo examples to validate the correct execution of each testcase.
[ Andrew: this depends on kfifo-add-explicit-error-checking-in-byte-stream-example.patch ]
--- samples/kfifo/bytestream-example.c | 7 ++- samples/kfifo/dma-example.c | 106 +++++++++++++++++++++++------------- samples/kfifo/inttype-example.c | 43 ++++++++++++--- samples/kfifo/record-example.c | 39 ++++++++++++- 4 files changed, 144 insertions(+), 51 deletions(-)
samples/kfifo/bytestream-example.c +6 -1
@@ -44,7 +44,7 @@ static struct kfifo test; static DECLARE_KFIFO(test, unsigned char, FIFO_SIZE);#endif -static unsigned char expected_result[FIFO_SIZE ] = { +static const unsigned char expected_result[FIFO_SIZE ] = {3 ,4 ,5 ,6 ,7 ,8 ,9 ,0 ,1 ,20 ,21 ,22 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 ,32 ,33 ,34 ,
@@ -90,9 +90,14 @@ static int __init testfunc(void)printk (KERN_INFO "queue len: %u\n" ,kfifo_len (&test)); +/* show the first value without removing from the fifo */ +if (kfifo_peek (&test, &i)) +printk (KERN_INFO "%d\n" , i); +/* check the correctness of all values in the fifo */ j =0 ;while (kfifo_get (&test, &i)) { +printk (KERN_INFO "item = %d\n" , i);if (i != expected_result[j++]) {printk (KERN_WARNING "value mismatch: test failed\n" );return -EIO ;
samples/kfifo/dma-example.c +67 -39
140 lines not on this page · raw message
samples/kfifo/inttype-example.c +35 -8
70 lines not on this page · raw message
samples/kfifo/record-example.c +36 -3
@@ -55,6 +55,19 @@ typedef STRUCT_KFIFO_REC_1(FIFO_SIZE) mytest;static mytest test;#endif +static const char *expected_result[] = { +"a" , +"bb" , +"ccc" , +"dddd" , +"eeeee" , +"ffffff" , +"ggggggg" , +"hhhhhhhh" , +"iiiiiiiii" , +"jjjjjjjjjj" , +}; +static int __init testfunc (void ) {char buf[100 ];
@@ -75,6 +88,10 @@ static int __init testfunc(void)kfifo_in (&test, buf, i +1 ); } +/* skip first element of the fifo */ +printk (KERN_INFO "skip 1st element\n" ); +kfifo_skip (&test); +printk (KERN_INFO "fifo len: %u\n" ,kfifo_len (&test));/* show the first record without removing from the fifo */
@@ -82,11 +99,22 @@ static int __init testfunc(void)if (ret)printk (KERN_INFO "%.*s\n" , ret, buf); -/* print out all records in the fifo */ +/* check the correctness of all values in the fifo */ + i =0 ;while (!kfifo_is_empty (&test)) { ret =kfifo_out (&test, buf,sizeof (buf)); -printk (KERN_INFO "%.*s\n" , ret, buf); + buf[ret] ='\0' ; +printk (KERN_INFO "item = %.*s\n" , ret, buf); +if (strcmp (buf, expected_result[i++])) { +printk (KERN_WARNING "value mismatch: test failed\n" ); +return -EIO ; + } + } +if (i !=ARRAY_SIZE (expected_result)) { +printk (KERN_WARNING "size mismatch: test failed\n" ); +return -EIO ; } +printk (KERN_INFO "test passed\n" );return 0 ; }
@@ -142,7 +170,12 @@ static int __init example_init(void)#else INIT_KFIFO (test);#endif -testfunc (); +if (testfunc () <0 ) { +#ifdef DYNAMIC +kfifo_free (&test); +#endif +return -EIO ; + }if (proc_create (PROC_FIFO ,0 ,NULL , &fifo_fops) ==NULL ) {#ifdef DYNAMIC
Signature · 1 line
1.7.0.4
Re: [PATCH 3/3] kfifo: add explicit error checking in all the examples
Provide a check in all the kfifo examples to validate the correct execution of each testcase.
[ Andrew: this depends on kfifo-add-explicit-error-checking-in-byte-stream-example.patch ]
--- samples/kfifo/bytestream-example.c | 7 ++- samples/kfifo/dma-example.c | 106 +++++++++++++++++++++++------------- samples/kfifo/inttype-example.c | 43 ++++++++++++--- samples/kfifo/record-example.c | 39 ++++++++++++- 4 files changed, 144 insertions(+), 51 deletions(-)
samples/kfifo/bytestream-example.c +6 -1
@@ -44,7 +44,7 @@ static struct kfifo test; static DECLARE_KFIFO(test, unsigned char, FIFO_SIZE);#endif -static unsigned char expected_result[FIFO_SIZE ] = { +static const unsigned char expected_result[FIFO_SIZE ] = {3 ,4 ,5 ,6 ,7 ,8 ,9 ,0 ,1 ,20 ,21 ,22 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 ,32 ,33 ,34 ,
@@ -90,9 +90,14 @@ static int __init testfunc(void)printk (KERN_INFO "queue len: %u\n" ,kfifo_len (&test)); +/* show the first value without removing from the fifo */ +if (kfifo_peek (&test, &i)) +printk (KERN_INFO "%d\n" , i); +/* check the correctness of all values in the fifo */ j =0 ;while (kfifo_get (&test, &i)) { +printk (KERN_INFO "item = %d\n" , i);if (i != expected_result[j++]) {printk (KERN_WARNING "value mismatch: test failed\n" );return -EIO ;
samples/kfifo/dma-example.c +67 -39
140 lines not on this page · raw message
samples/kfifo/inttype-example.c +35 -8
70 lines not on this page · raw message
samples/kfifo/record-example.c +36 -3
@@ -55,6 +55,19 @@ typedef STRUCT_KFIFO_REC_1(FIFO_SIZE) mytest;static mytest test;#endif +static const char *expected_result[] = { +"a" , +"bb" , +"ccc" , +"dddd" , +"eeeee" , +"ffffff" , +"ggggggg" , +"hhhhhhhh" , +"iiiiiiiii" , +"jjjjjjjjjj" , +}; +static int __init testfunc (void ) {char buf[100 ];
@@ -75,6 +88,10 @@ static int __init testfunc(void)kfifo_in (&test, buf, i +1 ); } +/* skip first element of the fifo */ +printk (KERN_INFO "skip 1st element\n" ); +kfifo_skip (&test); +printk (KERN_INFO "fifo len: %u\n" ,kfifo_len (&test));/* show the first record without removing from the fifo */
@@ -82,11 +99,22 @@ static int __init testfunc(void)if (ret)printk (KERN_INFO "%.*s\n" , ret, buf); -/* print out all records in the fifo */ +/* check the correctness of all values in the fifo */ + i =0 ;while (!kfifo_is_empty (&test)) { ret =kfifo_out (&test, buf,sizeof (buf)); -printk (KERN_INFO "%.*s\n" , ret, buf); + buf[ret] ='\0' ; +printk (KERN_INFO "item = %.*s\n" , ret, buf); +if (strcmp (buf, expected_result[i++])) { +printk (KERN_WARNING "value mismatch: test failed\n" ); +return -EIO ; + } + } +if (i !=ARRAY_SIZE (expected_result)) { +printk (KERN_WARNING "size mismatch: test failed\n" ); +return -EIO ; } +printk (KERN_INFO "test passed\n" );return 0 ; }
@@ -142,7 +170,12 @@ static int __init example_init(void)#else INIT_KFIFO (test);#endif -testfunc (); +if (testfunc () <0 ) { +#ifdef DYNAMIC +kfifo_free (&test); +#endif +return -EIO ; + }if (proc_create (PROC_FIFO ,0 ,NULL , &fifo_fops) ==NULL ) {#ifdef DYNAMIC
The scatterlist is used uninitialized in kfifo_dma_in_prepare(). This triggers the following bug if CONFIG_DEBUG_SG=y:
------------[ cut here ]------------ kernel BUG at include/linux/scatterlist.h:65! invalid opcode: 0000 [#1] PREEMPT SMP ... Call Trace: [<ffffffff810a1eab>] setup_sgl+0x6b/0xe0 [<ffffffffa03d7000>] ? example_init+0x0/0x265 [dma_example] [<ffffffff810a2021>] __kfifo_dma_in_prepare+0x21/0x30 [<ffffffffa03d7124>] example_init+0x124/0x265 [dma_example] [<ffffffff810f9c55>] ? trace_module_notify+0x25/0x370 [<ffffffff81110c6e>] ? free_pages_prepare+0x11e/0x1e0 [<ffffffff8106f2b1>] ? get_parent_ip+0x11/0x50 [<ffffffff810f9c55>] ? trace_module_notify+0x25/0x370 [<ffffffff810b65fd>] ? trace_hardirqs_on+0xd/0x10 [<ffffffff814beade>] ? mutex_unlock+0xe/0x10 [<ffffffff810f9c71>] ? trace_module_notify+0x41/0x370 [<ffffffff810a77d5>] ? __blocking_notifier_call_chain+0x45/0x80 [<ffffffff81137b7a>] ? vfree+0x2a/0x30 [<ffffffff810a6ac3>] ? up_read+0x23/0x40 [<ffffffff810a77f5>] ? __blocking_notifier_call_chain+0x65/0x80 [<ffffffff810001e3>] do_one_initcall+0x43/0x180 [<ffffffff810c577a>] sys_init_module+0xba/0x200 [<ffffffff8103819b>] system_call_fastpath+0x16/0x1b RIP [<ffffffff810a1e31>] setup_sgl_buf+0x1a1/0x1b0 RSP <ffff88006720dc98> ---[ end trace a72b979fd3c1d3a5 ]---
Add the proper initialization to avoid the bug.
--- samples/kfifo/dma-example.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
samples/kfifo/dma-example.c +1 -0
@@ -45,6 +45,7 @@ static int __init example_init(void)printk (KERN_INFO "queue len: %u\n" ,kfifo_len (&fifo)); +sg_init_table (sg,ARRAY_SIZE (sg)); ret =kfifo_dma_in_prepare (&fifo, sg,ARRAY_SIZE (sg),FIFO_SIZE );printk (KERN_INFO "DMA sgl entries: %d\n" , ret);