linux
Non-initialized buffer causes kernel panic in JFFS2
NOR flash setup function leaves struct field `wbuf_verify' uninitialized, but this buffer is used when JFFS2_FS_WBUF_VERIFY is enabled.
Bug fixed by commit bc8cec0dff0
| Type | UninitializedVariable |
| Config | "JFFS2_FS_WBUF_VERIFY" (1st degree) |
| C-features | FunctionPointers, Structs |
| Fix-in | code |
| Location | fs/jffs2/ |
#define ENOMEM 12 /* Out of memory */
typedef long unsigned int size_t;
extern void *malloc (size_t __size) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ;
extern void free (void *__ptr) __attribute__ ((__nothrow__ , __leaf__));
#define WBUF_PAGESIZE 32
unsigned char *wbuf; /* Write-behind buffer for NAND flash */
#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
unsigned char *wbuf_verify; /* read-back buffer for verification */
#endif
int jffs2_nor_wbuf_flash_setup() {
wbuf = malloc(WBUF_PAGESIZE);
if (!wbuf)
return -ENOMEM;
return 0;
}
#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
static int jffs2_verify_write()
{
return(int) *wbuf_verify; // ERROR (6)
}
#else
#define jffs2_verify_write() do { } while (0)
#endif
int __jffs2_flush_wbuf()
{
jffs2_verify_write(); // (5)
return 0;
}
int jffs2_flash_writev()
{
__jffs2_flush_wbuf(); // (4)
return 0;
}
int jffs2_flash_write()
{
return jffs2_flash_writev(); // (3)
}
int main()
{
jffs2_nor_wbuf_flash_setup(); // (1)
jffs2_flash_write(); // (2)
return 0;
}
diff --git a/simple/bc8cec0.c b/simple/bc8cec0.c
--- a/simple/bc8cec0.c
+++ b/simple/bc8cec0.c
@@ -19,6 +19,14 @@
if (!wbuf)
return -ENOMEM;
+#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
+ wbuf_verify = malloc(WBUF_PAGESIZE);
+ if (!wbuf_verify) {
+ free(wbuf);
+ return -ENOMEM;
+ }
+#endif
+
return 0;
}
#include <errno.h>
#include <stdlib.h>
#define WBUF_PAGESIZE 32
unsigned char *wbuf; /* Write-behind buffer for NAND flash */
#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
unsigned char *wbuf_verify; /* read-back buffer for verification */
#endif
int main()
{
// jffs2_nor_wbuf_flash_setup();
wbuf = malloc(WBUF_PAGESIZE);
if (!wbuf)
return -ENOMEM;
// jffs2_flash_write();
#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
return(int) *wbuf_verify; // ERROR
#else
do { } while (0);
#endif
return 0;
}
. // SETUP . // at fs/jffs2/super.c:234 jffs2_get_sb() is set as a method to read a super-block . call fs/jffs2/super.c:183:jffs2_get_sb() .. call drivers/mtd/mtdsuper.c:125:get_sb_mtd() ... call drivers/mtd/mtdsuper.c:53:get_sb_mtd_aux() ... 75: ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); .... dyn-call fs/jffs2/super.c:148:jffs2_fill_super() ..... call fs/jffs2/fs.c:474:jffs2_do_fill_super() ..... 515: ret = jffs2_flash_setup(c); ...... call fs/jffs2/fs.c:668:jffs2_flash_setup() ...... 687: ret = jffs2_nor_wbuf_flash_setup(c); ....... call fs/jffs2/wbuf.c:1257:jffs2_nor_wbuf_flash_setup() ....... // c->wbuf_verify is left uninitialized for NOR flash . // later... . call fs/jffs2/wbuf.c:930:jffs2_flash_write() .. call fs/jffs2/wbuf.c:782:jffs2_flash_writev() ... call fs/jffs2/wbuf.c:570:__jffs2_flush_wbuf() .... call fs/jffs2/wbuf.c:224:jffs2_verify_write() .... // this call only happens when JFFS2_FS_WBUF_VERIFY is enabled .... ERROR 231: ret = c->mtd->read(c->mtd, ofs, c->wbuf_pagesize, &retlen, c->wbuf_verify);