linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] jffs2: fix unbalanced locking
@ 2013-09-23  8:52 Li Zefan
  0 siblings, 0 replies; 3+ messages in thread
From: Li Zefan @ 2013-09-23  8:52 UTC (permalink / raw)
  To: David Woodhouse; +Cc: linux-mtd, LKML

In the failure path in jffs2_do_crccheck_inode() the lock isn't released
before returning.

This probably won't cause real bug, because the structure that contains
the lock is freed in this case.

Signed-off-by: Li Zefan <lizefan@huawei.com>
---
 fs/jffs2/readinode.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index ae81b01..55cf63d 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -1425,7 +1425,8 @@ int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
 		jffs2_do_clear_inode(c, f);
 	}
 	jffs2_xattr_do_crccheck_inode(c, ic);
-	kfree (f);
+	mutex_unlock(&f->sem);
+	kfree(f);
 	return ret;
 }
 
-- 
1.8.0.2

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH] jffs2: fix unbalanced locking
@ 2014-02-26  2:27 Brian Norris
  2015-05-07 23:21 ` Brian Norris
  0 siblings, 1 reply; 3+ messages in thread
From: Brian Norris @ 2014-02-26  2:27 UTC (permalink / raw)
  To: linux-mtd
  Cc: Artem Bityutskiy, Li Zefan, Brian Norris, David Woodhouse,
	Andrew Morton

Li Zefan reported an unbalanced locking issue, found by his
internal debugging feature on runtime. The particular case he was
looking at doesn't lead to a deadlock, as the structure that this lock
is embedded in is freed on error. But we should straighten out the error
handling.

Because several callers of jffs2_do_read_inode_internal() /
jffs2_do_read_inode() already handle the locking/unlocking and inode
clearing at their own level, let's just push any unlocks/clearing down
to the caller. This consistency is much easier to verify.

Reported-by: Li Zefan <lizefan@huawei.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
---
Not CC'd to -stable this time, since the bug seems non-critical, and it has
only limited testing (I did a few quick sanity tests, and Li tested an earlier
revision)

 fs/jffs2/fs.c        |  7 ++-----
 fs/jffs2/readinode.c | 27 ++++-----------------------
 2 files changed, 6 insertions(+), 28 deletions(-)

diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 560821bff038..ea753a2a893e 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -272,12 +272,9 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
 	mutex_lock(&f->sem);
 
 	ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
+	if (ret)
+		goto error;
 
-	if (ret) {
-		mutex_unlock(&f->sem);
-		iget_failed(inode);
-		return ERR_PTR(ret);
-	}
 	inode->i_mode = jemode_to_cpu(latest_node.mode);
 	i_uid_write(inode, je16_to_cpu(latest_node.uid));
 	i_gid_write(inode, je16_to_cpu(latest_node.gid));
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 386303dca382..5539ed46e89b 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -1203,17 +1203,13 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
 		JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n",
 			ret, retlen, sizeof(*latest_node));
 		/* FIXME: If this fails, there seems to be a memory leak. Find it. */
-		mutex_unlock(&f->sem);
-		jffs2_do_clear_inode(c, f);
-		return ret?ret:-EIO;
+		return ret ? ret : -EIO;
 	}
 
 	crc = crc32(0, latest_node, sizeof(*latest_node)-8);
 	if (crc != je32_to_cpu(latest_node->node_crc)) {
 		JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n",
 			f->inocache->ino, ref_offset(rii.latest_ref));
-		mutex_unlock(&f->sem);
-		jffs2_do_clear_inode(c, f);
 		return -EIO;
 	}
 
@@ -1250,16 +1246,11 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
 			 * keep in RAM to facilitate quick follow symlink
 			 * operation. */
 			uint32_t csize = je32_to_cpu(latest_node->csize);
-			if (csize > JFFS2_MAX_NAME_LEN) {
-				mutex_unlock(&f->sem);
-				jffs2_do_clear_inode(c, f);
+			if (csize > JFFS2_MAX_NAME_LEN)
 				return -ENAMETOOLONG;
-			}
 			f->target = kmalloc(csize + 1, GFP_KERNEL);
 			if (!f->target) {
 				JFFS2_ERROR("can't allocate %u bytes of memory for the symlink target path cache\n", csize);
-				mutex_unlock(&f->sem);
-				jffs2_do_clear_inode(c, f);
 				return -ENOMEM;
 			}
 
@@ -1271,8 +1262,6 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
 					ret = -EIO;
 				kfree(f->target);
 				f->target = NULL;
-				mutex_unlock(&f->sem);
-				jffs2_do_clear_inode(c, f);
 				return ret;
 			}
 
@@ -1289,15 +1278,11 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
 		if (f->metadata) {
 			JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n",
 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
-			mutex_unlock(&f->sem);
-			jffs2_do_clear_inode(c, f);
 			return -EIO;
 		}
 		if (!frag_first(&f->fragtree)) {
 			JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n",
 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
-			mutex_unlock(&f->sem);
-			jffs2_do_clear_inode(c, f);
 			return -EIO;
 		}
 		/* ASSERT: f->fraglist != NULL */
@@ -1305,8 +1290,6 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
 			JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n",
 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
 			/* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
-			mutex_unlock(&f->sem);
-			jffs2_do_clear_inode(c, f);
 			return -EIO;
 		}
 		/* OK. We're happy */
@@ -1400,10 +1383,8 @@ int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
 	f->inocache = ic;
 
 	ret = jffs2_do_read_inode_internal(c, f, &n);
-	if (!ret) {
-		mutex_unlock(&f->sem);
-		jffs2_do_clear_inode(c, f);
-	}
+	mutex_unlock(&f->sem);
+	jffs2_do_clear_inode(c, f);
 	jffs2_xattr_do_crccheck_inode(c, ic);
 	kfree (f);
 	return ret;
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] jffs2: fix unbalanced locking
  2014-02-26  2:27 Brian Norris
@ 2015-05-07 23:21 ` Brian Norris
  0 siblings, 0 replies; 3+ messages in thread
From: Brian Norris @ 2015-05-07 23:21 UTC (permalink / raw)
  To: linux-mtd; +Cc: Artem Bityutskiy, Andrew Morton, Li Zefan, David Woodhouse

On Tue, Feb 25, 2014 at 06:27:40PM -0800, Brian Norris wrote:
> Li Zefan reported an unbalanced locking issue, found by his
> internal debugging feature on runtime. The particular case he was
> looking at doesn't lead to a deadlock, as the structure that this lock
> is embedded in is freed on error. But we should straighten out the error
> handling.
> 
> Because several callers of jffs2_do_read_inode_internal() /
> jffs2_do_read_inode() already handle the locking/unlocking and inode
> clearing at their own level, let's just push any unlocks/clearing down
> to the caller. This consistency is much easier to verify.
> 
> Reported-by: Li Zefan <lizefan@huawei.com>
> Cc: David Woodhouse <dwmw2@infradead.org>
> Cc: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
> ---
> Not CC'd to -stable this time, since the bug seems non-critical, and it has
> only limited testing (I did a few quick sanity tests, and Li tested an earlier
> revision)

Pushed to l2-mtd.git.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-05-07 23:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-23  8:52 [PATCH] jffs2: fix unbalanced locking Li Zefan
  -- strict thread matches above, loose matches on Subject: below --
2014-02-26  2:27 Brian Norris
2015-05-07 23:21 ` Brian Norris

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).