All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH -next 0/3] fix some bugs in ubifs_garbage_collect
@ 2021-11-15  1:31 ` Baokun Li
  0 siblings, 0 replies; 10+ messages in thread
From: Baokun Li @ 2021-11-15  1:31 UTC (permalink / raw)
  To: richard, linux-mtd, linux-kernel; +Cc: libaokun1, yukuai3

Baokun Li (3):
  ubifs: fix slab-out-of-bounds in ubifs_change_lp
  ubifs: fix double return leb in ubifs_garbage_collect
  ubifs: read-only if LEB may always be taken in ubifs_garbage_collect

 fs/ubifs/gc.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

-- 
2.31.1


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

* [PATCH -next 0/3] fix some bugs in ubifs_garbage_collect
@ 2021-11-15  1:31 ` Baokun Li
  0 siblings, 0 replies; 10+ messages in thread
From: Baokun Li @ 2021-11-15  1:31 UTC (permalink / raw)
  To: richard, linux-mtd, linux-kernel; +Cc: libaokun1, yukuai3

Baokun Li (3):
  ubifs: fix slab-out-of-bounds in ubifs_change_lp
  ubifs: fix double return leb in ubifs_garbage_collect
  ubifs: read-only if LEB may always be taken in ubifs_garbage_collect

 fs/ubifs/gc.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

-- 
2.31.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH -next 1/3] ubifs: fix slab-out-of-bounds in ubifs_change_lp
  2021-11-15  1:31 ` Baokun Li
@ 2021-11-15  1:31   ` Baokun Li
  -1 siblings, 0 replies; 10+ messages in thread
From: Baokun Li @ 2021-11-15  1:31 UTC (permalink / raw)
  To: richard, linux-mtd, linux-kernel; +Cc: libaokun1, yukuai3, Hulk Robot

Hulk Robot reported a KASAN report about slab-out-of-bounds:
 ==================================================================
 BUG: KASAN: slab-out-of-bounds in ubifs_change_lp+0x3a9/0x1390 [ubifs]
 Read of size 8 at addr ffff888101c961f8 by task fsstress/1068
 [...]
 Call Trace:
  check_memory_region+0x1c1/0x1e0
  ubifs_change_lp+0x3a9/0x1390 [ubifs]
  ubifs_change_one_lp+0x170/0x220 [ubifs]
  ubifs_garbage_collect+0x7f9/0xda0 [ubifs]
  ubifs_budget_space+0xfe4/0x1bd0 [ubifs]
  ubifs_write_begin+0x528/0x10c0 [ubifs]

 Allocated by task 1068:
  kmemdup+0x25/0x50
  ubifs_lpt_lookup_dirty+0x372/0xb00 [ubifs]
  ubifs_update_one_lp+0x46/0x260 [ubifs]
  ubifs_tnc_end_commit+0x98b/0x1720 [ubifs]
  do_commit+0x6cb/0x1950 [ubifs]
  ubifs_run_commit+0x15a/0x2b0 [ubifs]
  ubifs_budget_space+0x1061/0x1bd0 [ubifs]
  ubifs_write_begin+0x528/0x10c0 [ubifs]
 [...]
 ==================================================================

In ubifs_garbage_collect(), if ubifs_find_dirty_leb returns an error,
lp is an uninitialized variable. But lp.num might be used in the out
branch, which is a random value. If the value is -1 or another value
that can pass the check, soob may occur in the ubifs_change_lp() in
the following procedure.

To solve this problem, we initialize lp.lnum to -1, and then initialize
it correctly in ubifs_find_dirty_leb, which is not equal to -1, and
ubifs_return_leb is executed only when lp.lnum != -1.

if find a retained or indexing LEB and continue to next loop, but break
before find another LEB, the "taken" flag of this LEB will be cleaned
in ubi_return_lebi(). This bug has also been fixed in this patch.

Reported-by: Hulk Robot <hulkci@huawei.com>
Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
 fs/ubifs/gc.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index dc3e26e9ed7b..05e1eeae8457 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -692,6 +692,9 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
 	for (i = 0; ; i++) {
 		int space_before, space_after;
 
+		/* Maybe continue after find and break before find */
+		lp.lnum = -1;
+
 		cond_resched();
 
 		/* Give the commit an opportunity to run */
@@ -843,7 +846,8 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
 	ubifs_wbuf_sync_nolock(wbuf);
 	ubifs_ro_mode(c, ret);
 	mutex_unlock(&wbuf->io_mutex);
-	ubifs_return_leb(c, lp.lnum);
+	if (lp.lnum != -1)
+		ubifs_return_leb(c, lp.lnum);
 	return ret;
 }
 
-- 
2.31.1


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

* [PATCH -next 1/3] ubifs: fix slab-out-of-bounds in ubifs_change_lp
@ 2021-11-15  1:31   ` Baokun Li
  0 siblings, 0 replies; 10+ messages in thread
From: Baokun Li @ 2021-11-15  1:31 UTC (permalink / raw)
  To: richard, linux-mtd, linux-kernel; +Cc: libaokun1, yukuai3, Hulk Robot

Hulk Robot reported a KASAN report about slab-out-of-bounds:
 ==================================================================
 BUG: KASAN: slab-out-of-bounds in ubifs_change_lp+0x3a9/0x1390 [ubifs]
 Read of size 8 at addr ffff888101c961f8 by task fsstress/1068
 [...]
 Call Trace:
  check_memory_region+0x1c1/0x1e0
  ubifs_change_lp+0x3a9/0x1390 [ubifs]
  ubifs_change_one_lp+0x170/0x220 [ubifs]
  ubifs_garbage_collect+0x7f9/0xda0 [ubifs]
  ubifs_budget_space+0xfe4/0x1bd0 [ubifs]
  ubifs_write_begin+0x528/0x10c0 [ubifs]

 Allocated by task 1068:
  kmemdup+0x25/0x50
  ubifs_lpt_lookup_dirty+0x372/0xb00 [ubifs]
  ubifs_update_one_lp+0x46/0x260 [ubifs]
  ubifs_tnc_end_commit+0x98b/0x1720 [ubifs]
  do_commit+0x6cb/0x1950 [ubifs]
  ubifs_run_commit+0x15a/0x2b0 [ubifs]
  ubifs_budget_space+0x1061/0x1bd0 [ubifs]
  ubifs_write_begin+0x528/0x10c0 [ubifs]
 [...]
 ==================================================================

In ubifs_garbage_collect(), if ubifs_find_dirty_leb returns an error,
lp is an uninitialized variable. But lp.num might be used in the out
branch, which is a random value. If the value is -1 or another value
that can pass the check, soob may occur in the ubifs_change_lp() in
the following procedure.

To solve this problem, we initialize lp.lnum to -1, and then initialize
it correctly in ubifs_find_dirty_leb, which is not equal to -1, and
ubifs_return_leb is executed only when lp.lnum != -1.

if find a retained or indexing LEB and continue to next loop, but break
before find another LEB, the "taken" flag of this LEB will be cleaned
in ubi_return_lebi(). This bug has also been fixed in this patch.

Reported-by: Hulk Robot <hulkci@huawei.com>
Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
 fs/ubifs/gc.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index dc3e26e9ed7b..05e1eeae8457 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -692,6 +692,9 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
 	for (i = 0; ; i++) {
 		int space_before, space_after;
 
+		/* Maybe continue after find and break before find */
+		lp.lnum = -1;
+
 		cond_resched();
 
 		/* Give the commit an opportunity to run */
@@ -843,7 +846,8 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
 	ubifs_wbuf_sync_nolock(wbuf);
 	ubifs_ro_mode(c, ret);
 	mutex_unlock(&wbuf->io_mutex);
-	ubifs_return_leb(c, lp.lnum);
+	if (lp.lnum != -1)
+		ubifs_return_leb(c, lp.lnum);
 	return ret;
 }
 
-- 
2.31.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH -next 2/3] ubifs: fix double return leb in ubifs_garbage_collect
  2021-11-15  1:31 ` Baokun Li
@ 2021-11-15  1:31   ` Baokun Li
  -1 siblings, 0 replies; 10+ messages in thread
From: Baokun Li @ 2021-11-15  1:31 UTC (permalink / raw)
  To: richard, linux-mtd, linux-kernel; +Cc: libaokun1, yukuai3, Hulk Robot

If ubifs_garbage_collect_leb() returns -EAGAIN and enters the "out"
branch, ubifs_return_leb will execute twice on the same lnum. This
can cause data loss in concurrency situations.

Reported-by: Hulk Robot <hulkci@huawei.com>
Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
 fs/ubifs/gc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index 05e1eeae8457..1f74a127fe3a 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -758,6 +758,8 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
 				err = ubifs_return_leb(c, lp.lnum);
 				if (err)
 					ret = err;
+				/*  Maybe double return LEB if goto out */
+				lp.lnum = -1;
 				break;
 			}
 			goto out;
-- 
2.31.1


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

* [PATCH -next 2/3] ubifs: fix double return leb in ubifs_garbage_collect
@ 2021-11-15  1:31   ` Baokun Li
  0 siblings, 0 replies; 10+ messages in thread
From: Baokun Li @ 2021-11-15  1:31 UTC (permalink / raw)
  To: richard, linux-mtd, linux-kernel; +Cc: libaokun1, yukuai3, Hulk Robot

If ubifs_garbage_collect_leb() returns -EAGAIN and enters the "out"
branch, ubifs_return_leb will execute twice on the same lnum. This
can cause data loss in concurrency situations.

Reported-by: Hulk Robot <hulkci@huawei.com>
Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
 fs/ubifs/gc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index 05e1eeae8457..1f74a127fe3a 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -758,6 +758,8 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
 				err = ubifs_return_leb(c, lp.lnum);
 				if (err)
 					ret = err;
+				/*  Maybe double return LEB if goto out */
+				lp.lnum = -1;
 				break;
 			}
 			goto out;
-- 
2.31.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH -next 3/3] ubifs: read-only if LEB may always be taken in ubifs_garbage_collect
  2021-11-15  1:31 ` Baokun Li
@ 2021-11-15  1:31   ` Baokun Li
  -1 siblings, 0 replies; 10+ messages in thread
From: Baokun Li @ 2021-11-15  1:31 UTC (permalink / raw)
  To: richard, linux-mtd, linux-kernel; +Cc: libaokun1, yukuai3

If ubifs_garbage_collect_leb() returns -EAGAIN and ubifs_return_leb
returns error, a LEB will always has a "taken" flag. In this case,
set the ubifs to read-only to prevent a worse situation.

Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
 fs/ubifs/gc.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index 1f74a127fe3a..3134d070fcc0 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -756,8 +756,17 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
 				 * caller instead of the original '-EAGAIN'.
 				 */
 				err = ubifs_return_leb(c, lp.lnum);
-				if (err)
+				if (err) {
 					ret = err;
+					/*
+					 * An LEB may always be "taken",
+					 * so setting ubifs to read-only,
+					 * and then executing sync wbuf will
+					 * return -EROFS and enter the "out"
+					 * error branch.
+					 */
+					ubifs_ro_mode(c, ret);
+				}
 				/*  Maybe double return LEB if goto out */
 				lp.lnum = -1;
 				break;
-- 
2.31.1


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

* [PATCH -next 3/3] ubifs: read-only if LEB may always be taken in ubifs_garbage_collect
@ 2021-11-15  1:31   ` Baokun Li
  0 siblings, 0 replies; 10+ messages in thread
From: Baokun Li @ 2021-11-15  1:31 UTC (permalink / raw)
  To: richard, linux-mtd, linux-kernel; +Cc: libaokun1, yukuai3

If ubifs_garbage_collect_leb() returns -EAGAIN and ubifs_return_leb
returns error, a LEB will always has a "taken" flag. In this case,
set the ubifs to read-only to prevent a worse situation.

Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
 fs/ubifs/gc.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index 1f74a127fe3a..3134d070fcc0 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -756,8 +756,17 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
 				 * caller instead of the original '-EAGAIN'.
 				 */
 				err = ubifs_return_leb(c, lp.lnum);
-				if (err)
+				if (err) {
 					ret = err;
+					/*
+					 * An LEB may always be "taken",
+					 * so setting ubifs to read-only,
+					 * and then executing sync wbuf will
+					 * return -EROFS and enter the "out"
+					 * error branch.
+					 */
+					ubifs_ro_mode(c, ret);
+				}
 				/*  Maybe double return LEB if goto out */
 				lp.lnum = -1;
 				break;
-- 
2.31.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH -next 0/3] fix some bugs in ubifs_garbage_collect
  2021-11-15  1:31 ` Baokun Li
@ 2021-12-21 12:35   ` libaokun (A)
  -1 siblings, 0 replies; 10+ messages in thread
From: libaokun (A) @ 2021-12-21 12:35 UTC (permalink / raw)
  To: richard, linux-mtd, linux-kernel; +Cc: yukuai3, Baokun Li

在 2021/11/15 9:31, Baokun Li 写道:

ping

> Baokun Li (3):
>    ubifs: fix slab-out-of-bounds in ubifs_change_lp
>    ubifs: fix double return leb in ubifs_garbage_collect
>    ubifs: read-only if LEB may always be taken in ubifs_garbage_collect
>
>   fs/ubifs/gc.c | 19 +++++++++++++++++--
>   1 file changed, 17 insertions(+), 2 deletions(-)
>


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

* Re: [PATCH -next 0/3] fix some bugs in ubifs_garbage_collect
@ 2021-12-21 12:35   ` libaokun (A)
  0 siblings, 0 replies; 10+ messages in thread
From: libaokun (A) @ 2021-12-21 12:35 UTC (permalink / raw)
  To: richard, linux-mtd, linux-kernel; +Cc: yukuai3, Baokun Li

在 2021/11/15 9:31, Baokun Li 写道:

ping

> Baokun Li (3):
>    ubifs: fix slab-out-of-bounds in ubifs_change_lp
>    ubifs: fix double return leb in ubifs_garbage_collect
>    ubifs: read-only if LEB may always be taken in ubifs_garbage_collect
>
>   fs/ubifs/gc.c | 19 +++++++++++++++++--
>   1 file changed, 17 insertions(+), 2 deletions(-)
>


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

end of thread, other threads:[~2021-12-21 12:35 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-15  1:31 [PATCH -next 0/3] fix some bugs in ubifs_garbage_collect Baokun Li
2021-11-15  1:31 ` Baokun Li
2021-11-15  1:31 ` [PATCH -next 1/3] ubifs: fix slab-out-of-bounds in ubifs_change_lp Baokun Li
2021-11-15  1:31   ` Baokun Li
2021-11-15  1:31 ` [PATCH -next 2/3] ubifs: fix double return leb in ubifs_garbage_collect Baokun Li
2021-11-15  1:31   ` Baokun Li
2021-11-15  1:31 ` [PATCH -next 3/3] ubifs: read-only if LEB may always be taken " Baokun Li
2021-11-15  1:31   ` Baokun Li
2021-12-21 12:35 ` [PATCH -next 0/3] fix some bugs " libaokun (A)
2021-12-21 12:35   ` libaokun (A)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.