From f2538f999345405f7d2e1194c0c8efa4e11f7b3a Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Wed, 24 Jul 2019 10:46:58 +0800 Subject: jffs2: Fix possible null-pointer dereferences in jffs2_add_frag_to_fragtree() In jffs2_add_frag_to_fragtree(), there is an if statement on line 223 to check whether "this" is NULL: if (this) When "this" is NULL, it is used at several places, such as on line 249: if (this->node) and on line 260: if (newfrag->ofs > this->ofs) Thus possible null-pointer dereferences may occur. To fix these bugs, -EINVAL is returned when "this" is NULL. These bugs are found by a static analysis tool STCheck written by us. Signed-off-by: Jia-Ju Bai Signed-off-by: Richard Weinberger --- fs/jffs2/nodelist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/jffs2') diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index b86c78d178c6..021a4a2190ee 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -226,7 +226,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r lastend = this->ofs + this->size; } else { dbg_fragtree2("lookup gave no frag\n"); - lastend = 0; + return -EINVAL; } /* See if we ran off the end of the fragtree */ -- cgit v1.2.3 From 61b875e88a04fd626e68c657400f237af8afa95e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 24 Jul 2019 09:15:25 +0200 Subject: jffs2: Remove jffs2_gc_fetch_page and jffs2_gc_release_page Merge these two helpers into the only callers to get rid of some amazingly bad calling conventions. Suggested-by: Al Viro Signed-off-by: Christoph Hellwig Signed-off-by: Richard Weinberger --- fs/jffs2/fs.c | 27 --------------------------- fs/jffs2/gc.c | 21 +++++++++++++-------- fs/jffs2/os-linux.h | 3 --- 3 files changed, 13 insertions(+), 38 deletions(-) (limited to 'fs/jffs2') diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 8a20ddd25f2d..a3193c0f3a9b 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -678,33 +678,6 @@ struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, return JFFS2_INODE_INFO(inode); } -unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, - struct jffs2_inode_info *f, - unsigned long offset, - unsigned long *priv) -{ - struct inode *inode = OFNI_EDONI_2SFFJ(f); - struct page *pg; - - pg = read_cache_page(inode->i_mapping, offset >> PAGE_SHIFT, - jffs2_do_readpage_unlock, inode); - if (IS_ERR(pg)) - return (void *)pg; - - *priv = (unsigned long)pg; - return kmap(pg); -} - -void jffs2_gc_release_page(struct jffs2_sb_info *c, - unsigned char *ptr, - unsigned long *priv) -{ - struct page *pg = (void *)*priv; - - kunmap(pg); - put_page(pg); -} - static int jffs2_flash_setup(struct jffs2_sb_info *c) { int ret = 0; diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 9ed0f26cf023..373b3b7c9f44 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -1165,12 +1165,13 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, uint32_t start, uint32_t end) { + struct inode *inode = OFNI_EDONI_2SFFJ(f); struct jffs2_full_dnode *new_fn; struct jffs2_raw_inode ri; uint32_t alloclen, offset, orig_end, orig_start; int ret = 0; unsigned char *comprbuf = NULL, *writebuf; - unsigned long pg; + struct page *page; unsigned char *pg_ptr; memset(&ri, 0, sizeof(ri)); @@ -1325,15 +1326,18 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era * end up here trying to GC the *same* page that jffs2_write_begin() is * trying to write out, read_cache_page() will not deadlock. */ mutex_unlock(&f->sem); - pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg); - mutex_lock(&f->sem); - - if (IS_ERR(pg_ptr)) { + page = read_cache_page(inode->i_mapping, start >> PAGE_SHIFT, + jffs2_do_readpage_unlock, inode); + if (IS_ERR(page)) { pr_warn("read_cache_page() returned error: %ld\n", - PTR_ERR(pg_ptr)); - return PTR_ERR(pg_ptr); + PTR_ERR(page)); + mutex_lock(&f->sem); + return PTR_ERR(page); } + pg_ptr = kmap(page); + mutex_lock(&f->sem); + offset = start; while(offset < orig_end) { uint32_t datalen; @@ -1396,6 +1400,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era } } - jffs2_gc_release_page(c, pg_ptr, &pg); + kunmap(page); + put_page(page); return ret; } diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index bd3d5f0ddc34..f4895dda26a3 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -183,9 +183,6 @@ unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, struct jffs2_inode_info *f, unsigned long offset, unsigned long *priv); -void jffs2_gc_release_page(struct jffs2_sb_info *c, - unsigned char *pg, - unsigned long *priv); void jffs2_flash_cleanup(struct jffs2_sb_info *c); -- cgit v1.2.3 From 6a379f67454a3c740671ed6c7793b76ffecef50b Mon Sep 17 00:00:00 2001 From: Wenwen Wang Date: Mon, 19 Aug 2019 16:55:04 -0500 Subject: jffs2: Fix memory leak in jffs2_scan_eraseblock() error path In jffs2_scan_eraseblock(), 'sumptr' is allocated through kmalloc() if 'sumlen' is larger than 'buf_size'. However, it is not deallocated in the following execution if jffs2_fill_scan_buf() fails, leading to a memory leak bug. To fix this issue, free 'sumptr' before returning the error. Signed-off-by: Wenwen Wang Signed-off-by: Richard Weinberger --- fs/jffs2/scan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'fs/jffs2') diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 90431dd613b8..5f7e284e0df3 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -527,8 +527,11 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo err = jffs2_fill_scan_buf(c, sumptr, jeb->offset + c->sector_size - sumlen, sumlen - buf_len); - if (err) + if (err) { + if (sumlen > buf_size) + kfree(sumptr); return err; + } } } -- cgit v1.2.3