ubifs: avoid assert failed in ubifs.c
PATCH 1/1 ubifs: avoid assert failed in ubifs.c
This patch solves assert failed displayed in the console during a boot. The root cause is that the ubifs_inode is not already allocated when ubifs_printdir and ubifs_finddir functions are called.
Trace showing the issue:
feed 'boot.scr.uimg', ino 94, new f_pos 0x17b40ece dent->ch.sqnum '7132', creat_sqnum 3886945402880 UBIFS assert failed in ubifs_finddir at 436 INODE ALLOCATION: creat_sqnum '7129'
Found U-Boot script /boot.scr.uimg
---
fs/ubifs/ubifs.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/ubifs/ubifs.c +4 -0
@@ -350,7 +350,9 @@ static int ubifs_printdir(struct file *file, void *dirent)dbg_gen ("feed '%s', ino %llu, new f_pos %#x" , dent->name, (unsigned long long )le64_to_cpu (dent->inum),key_hash_flash (c, &dent->key)); +#ifndef __UBOOT__ubifs_assert (le64_to_cpu (dent->ch.sqnum) >ubifs_inode (dir)->creat_sqnum); +#endif nm.len =le16_to_cpu (dent->nlen); over = filldir(c, (char *)dent->name, nm.len,
@@ -432,7 +434,9 @@ static int ubifs_finddir(struct super_block *sb, char *dirname,dbg_gen ("feed '%s', ino %llu, new f_pos %#x" , dent->name, (unsigned long long )le64_to_cpu (dent->inum),key_hash_flash (c, &dent->key)); +#ifndef __UBOOT__ubifs_assert (le64_to_cpu (dent->ch.sqnum) >ubifs_inode (dir)->creat_sqnum); +#endif nm.len =le16_to_cpu (dent->nlen); if ((strncmp(dirname, (char *)dent->name, nm.len) == 0) &&
Signature · 1 line
1.9.1
PATCH 1/1 ubifs: avoid assert failed in ubifs.c
Hello Patrice,
Am 27.04.2018 um 15:51 schrieb Patrice Chotard:
Quoted 11 lines
This patch solves assert failed displayed in the console during a boot. The root cause is that the
ubifs_inodeis not already allocated whenubifs_printdirandubifs_finddirfunctions are called.Trace showing the issue:
feed 'boot.scr.uimg', ino 94, newf_pos0x17b40ecedent->ch.sqnum'7132',creat_sqnum3886945402880 UBIFS assert failed inubifs_finddirat 436 INODE ALLOCATION:creat_sqnum'7129'
Found U-Boot script /boot.scr.uimg
Quoted 6 lines
Signed-off-by Christophe Kerello <[email protected]>Signed-off-by Patrice Chotard <[email protected]>---
fs/ubifs/ubifs.c | 4 ++++ 1 file changed, 4 insertions(+)
Applied to u-boot-ubi.git master
Thanks!
bye,
Heiko
Signature · 3 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-52 Fax: +49-8142-66989-80 Email: hs at denx.de
PATCH 1/1 ubifs: avoid assert failed in ubifs.c
In reply to Patrice ChotardQuoted 11 lines · Patrice Chotard
This patch solves assert failed displayed in the console during a boot. The root cause is that the
ubifs_inodeis not already allocated whenubifs_printdirandubifs_finddirfunctions are called.Trace showing the issue:
feed 'boot.scr.uimg', ino 94, newf_pos0x17b40ecedent->ch.sqnum'7132',creat_sqnum3886945402880 UBIFS assert failed inubifs_finddirat 436 INODE ALLOCATION:creat_sqnum'7129'
Found U-Boot script /boot.scr.uimg
Quoted 2 lines
Signed-off-by Christophe Kerello <[email protected]>Signed-off-by Patrice Chotard <[email protected]>
I ran into this too, but what I do not quite understand from the commit message is how hiding the error actually solves the problem that the assert points to.
Why does the assert trigger in the first place ?
What is the root cause of the issue that is being hidden by this patch?
Quoted 30 lines
---
fs/ubifs/ubifs.c | 4 ++++ 1 file changed, 4 insertions(+)fs/ubifs/ubifs.c +4
-0@@ -350,7 +350,9 @@ static int ubifs_printdir(struct file *file, void *dirent)dbg_gen ("feed '%s', ino %llu, new f_pos %#x" , dent->name, (unsigned long long )le64_to_cpu (dent->inum),key_hash_flash (c, &dent->key)); +#ifndef __UBOOT__ubifs_assert (le64_to_cpu (dent->ch.sqnum) >ubifs_inode (dir)->creat_sqnum); +#endif nm.len =le16_to_cpu (dent->nlen); over = filldir(c, (char *)dent->name, nm.len,@@ -432,7 +434,9 @@ static int ubifs_finddir(struct super_block *sb, char *dirname,dbg_gen ("feed '%s', ino %llu, new f_pos %#x" , dent->name, (unsigned long long )le64_to_cpu (dent->inum),key_hash_flash (c, &dent->key)); +#ifndef __UBOOT__ubifs_assert (le64_to_cpu (dent->ch.sqnum) >ubifs_inode (dir)->creat_sqnum); +#endif nm.len =le16_to_cpu (dent->nlen); if ((strncmp(dirname, (char *)dent->name, nm.len) == 0) &&
Signature · 2 lines
Best regards, Marek Vasut
PATCH 1/1 ubifs: avoid assert failed in ubifs.c
Quoted 15 lines · Marek Vasut
Quoted 11 lines · Patrice Chotard
This patch solves assert failed displayed in the console during a boot. The root cause is that the
ubifs_inodeis not already allocated whenubifs_printdirandubifs_finddirfunctions are called.Trace showing the issue:
feed 'boot.scr.uimg', ino 94, newf_pos0x17b40ecedent->ch.sqnum'7132',creat_sqnum3886945402880 UBIFS assert failed inubifs_finddirat 436 INODE ALLOCATION:creat_sqnum'7129'
Found U-Boot script /boot.scr.uimgQuoted 2 lines
Signed-off-by Christophe Kerello <[email protected]>Signed-off-by Patrice Chotard <[email protected]>
Quoted 7 lines
I ran into this too, but what I do not quite understand from the commit message is how hiding the error actually solves the problem that the assert points to.
Why does the assert trigger in the first place ?
What is the root cause of the issue that is being hidden by this patch?
Bump?
Quoted 32 lines
Quoted 30 lines
---
fs/ubifs/ubifs.c | 4 ++++ 1 file changed, 4 insertions(+)fs/ubifs/ubifs.c +4
-0@@ -350,7 +350,9 @@ static int ubifs_printdir(struct file *file, void *dirent)dbg_gen ("feed '%s', ino %llu, new f_pos %#x" , dent->name, (unsigned long long )le64_to_cpu (dent->inum),key_hash_flash (c, &dent->key)); +#ifndef __UBOOT__ubifs_assert (le64_to_cpu (dent->ch.sqnum) >ubifs_inode (dir)->creat_sqnum); +#endif nm.len =le16_to_cpu (dent->nlen); over = filldir(c, (char *)dent->name, nm.len,@@ -432,7 +434,9 @@ static int ubifs_finddir(struct super_block *sb, char *dirname,dbg_gen ("feed '%s', ino %llu, new f_pos %#x" , dent->name, (unsigned long long )le64_to_cpu (dent->inum),key_hash_flash (c, &dent->key)); +#ifndef __UBOOT__ubifs_assert (le64_to_cpu (dent->ch.sqnum) >ubifs_inode (dir)->creat_sqnum); +#endif nm.len =le16_to_cpu (dent->nlen); if ((strncmp(dirname, (char *)dent->name, nm.len) == 0) &&
Signature · 2 lines
Best regards, Marek Vasut
Richard Weinberger
maintainerPATCH 1/1 ubifs: avoid assert failed in ubifs.c
Am Dienstag, 22. Mai 2018, 12:56:48 CEST schrieb Marek Vasut:
Quoted 20 lines · Marek Vasut
Quoted 19 lines · Patrice Chotard
Quoted 11 lines
This patch solves assert failed displayed in the console during a boot. The root cause is that the
ubifs_inodeis not already allocated whenubifs_printdirandubifs_finddirfunctions are called.Trace showing the issue:
feed 'boot.scr.uimg', ino 94, newf_pos0x17b40ecedent->ch.sqnum'7132',creat_sqnum3886945402880 UBIFS assert failed inubifs_finddirat 436 INODE ALLOCATION:creat_sqnum'7129'
Found U-Boot script /boot.scr.uimgQuoted 2 lines
Signed-off-by Christophe Kerello <[email protected]>Signed-off-by Patrice Chotard <[email protected]>I ran into this too, but what I do not quite understand from the commit message is how hiding the error actually solves the problem that the assert points to.
Quoted 5 lines
Quoted 3 lines
Why does the assert trigger in the first place ?
What is the root cause of the issue that is being hidden by this patch?
Bump?
I had a look, the bug is deeper, ubifs_finddir() allocates a vfs inode manually and ignores UBIFS internals. ubifs_inode() will read beyond the allocated buffer. In best case the assert triggers because ->creat_sqnum is garbage, in worst case, U-Boot will just crash.
AFAICT, the correct solution is to use ubifs_iget(). Then we can keep the assert and it will check for the right thing.
Thanks,
//richard
PATCH 1/1 ubifs: avoid assert failed in ubifs.c
Quoted 21 lines · Richard Weinberger
Am Dienstag, 22. Mai 2018, 12:56:48 CEST schrieb Marek Vasut:
Quoted 20 lines · Marek Vasut
Quoted 19 lines · Patrice Chotard
Quoted 11 lines
This patch solves assert failed displayed in the console during a boot. The root cause is that the
ubifs_inodeis not already allocated whenubifs_printdirandubifs_finddirfunctions are called.Trace showing the issue:
feed 'boot.scr.uimg', ino 94, newf_pos0x17b40ecedent->ch.sqnum'7132',creat_sqnum3886945402880 UBIFS assert failed inubifs_finddirat 436 INODE ALLOCATION:creat_sqnum'7129'
Found U-Boot script /boot.scr.uimgQuoted 2 lines
Signed-off-by Christophe Kerello <[email protected]>Signed-off-by Patrice Chotard <[email protected]>I ran into this too, but what I do not quite understand from the commit message is how hiding the error actually solves the problem that the assert points to.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Why does the assert trigger in the first place ?
What is the root cause of the issue that is being hidden by this patch?
Bump?
I had a look, the bug is deeper,
ubifs_finddir()allocates a vfs inode manually
^^^^^^^^^^^^^^^
Hi Richard,
above triggered alert, so here's my old attempt to simplify ubifs_finddir(). Things could be further simplified, but I got distracted and never had time to look here again (which I'm affraid of).
Subject: [PATCH] Refactor ubifs_finddir
Just work in progress...
--- fs/ubifs/ubifs.c | 67 +++++++----------------------------------------- 1 file changed, 9 insertions(+), 58 deletions(-)
fs/ubifs/ubifs.c +9 -58
@@ -389,47 +389,20 @@ out:static int ubifs_finddir (struct super_block *sb,char *dirname,unsigned long root_inum,unsigned long *inum) { -int err;struct qstr nm;union ubifs_key key;struct ubifs_dent_node *dent; -struct ubifs_info *c; -struct file *file; -struct dentry *dentry; -struct inode *dir; -int ret =0 ; - - file =kzalloc (sizeof (struct file ),0 ); - dentry =kzalloc (sizeof (struct dentry ),0 ); - dir =kzalloc (sizeof (struct inode ),0 ); -if (!file || !dentry || !dir) { -printf ("%s: Error, no memory for malloc!\n" , __func__); - err = -ENOMEM ; - goto out; - } - - dir->i_sb = sb; - file->f_path.dentry = dentry; - file->f_path.dentry->d_parent = dentry; - file->f_path.dentry->d_inode = dir; - file->f_path.dentry->d_inode->i_ino = root_inum; - c = sb->s_fs_info; - -dbg_gen ("dir ino %lu, f_pos %#llx" , dir->i_ino, file->f_pos); +struct ubifs_info *c = sb->s_fs_info;/* Find the first entry in TNC and save it */ -lowest_dent_key (c, &key, dir->i_ino); +lowest_dent_key (c, &key, root_inum); nm.name =NULL ; - dent =ubifs_tnc_next_ent (c, &key, &nm); -if (IS_ERR (dent)) { - err =PTR_ERR (dent); - goto out; - } - - file->f_pos =key_hash_flash (c, &dent->key); - file->private_data = dent;while (1 ) { + dent =ubifs_tnc_next_ent (c, &key, &nm); +if (IS_ERR (dent)) +return PTR_ERR (dent); +dbg_gen ("feed '%s', ino %llu, new f_pos %#x" , dent->name, (unsigned long long )le64_to_cpu (dent->inum),key_hash_flash (c, &dent->key));
@@ -441,36 +414,14 @@ static int ubifs_finddir(struct super_block *sb, char *dirname,if ((strncmp (dirname, (char *)dent->name, nm.len) ==0 ) && (strlen (dirname) == nm.len)) { *inum =le64_to_cpu (dent->inum); - ret =1 ; - goto out_free; +kfree (dent); +return 0 ; } -/* Switch to the next entry */ key_read (c, &dent->key, &key); nm.name = (char *)dent->name; - dent =ubifs_tnc_next_ent (c, &key, &nm); -if (IS_ERR (dent)) { - err =PTR_ERR (dent); - goto out; - } - -kfree (file->private_data); - file->f_pos =key_hash_flash (c, &dent->key); - file->private_data = dent; -cond_resched (); +kfree (dent); } - -out: -if (err != -ENOENT ) -dbg_gen ("cannot find next direntry, error %d" , err); - -out_free: -kfree (file->private_data); -free (file); -free (dentry); -free (dir); - -return ret; }static unsigned long ubifs_findfile (struct super_block *sb,char *filename)
Signature · 1 line
2.17.0
Quoted 13 lines
and ignores UBIFS internals.
ubifs_inode()will read beyond the allocated buffer. In best case the assert triggers because ->creat_sqnum is garbage, in worst case, U-Boot will just crash.AFAICT, the correct solution is to use
ubifs_iget(). Then we can keep the assert and it will check for the right thing.Thanks,
//richard
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot