The branch main has been updated by fsu:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=ced21728223016429242d1f7cd5e8a160c8a88cb

commit ced21728223016429242d1f7cd5e8a160c8a88cb
Author:     Fedor Uporov <f...@freebsd.org>
AuthorDate: 2021-12-24 14:11:25 +0000
Commit:     Fedor Uporov <f...@freebsd.org>
CommitDate: 2021-12-30 06:14:45 +0000

    Add more accurate check for root inode
    
    Check that root inode has links and is directory.
    
    PR:             259105
    Reported by:    Robert Morris
    MFC after:      2 weeks
---
 sys/fs/ext2fs/ext2_inode_cnv.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/sys/fs/ext2fs/ext2_inode_cnv.c b/sys/fs/ext2fs/ext2_inode_cnv.c
index 181ea3e04622..445000c509db 100644
--- a/sys/fs/ext2fs/ext2_inode_cnv.c
+++ b/sys/fs/ext2fs/ext2_inode_cnv.c
@@ -157,9 +157,17 @@ ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip)
                return (EINVAL);
        }
 
+       /*
+        * Godmar thinks - if the link count is zero, then the inode is
+        * unused - according to ext2 standards. Ufs marks this fact by
+        * setting i_mode to zero - why ? I can see that this might lead to
+        * problems in an undelete.
+        */
        ip->i_nlink = le16toh(ei->e2di_nlink);
-       if (ip->i_number == EXT2_ROOTINO && ip->i_nlink == 0) {
-               SDT_PROBE2(ext2fs, , trace, inode_cnv, 1, "root inode 
unallocated");
+       ip->i_mode = ip->i_nlink ? le16toh(ei->e2di_mode) : 0;
+       if (ip->i_number == EXT2_ROOTINO &&
+           (ip->i_nlink < 2 || !S_ISDIR(ip->i_mode))) {
+               SDT_PROBE2(ext2fs, , trace, inode_cnv, 1, "root inode invalid");
                return (EINVAL);
        }
 
@@ -174,13 +182,6 @@ ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip)
                }
        }
 
-       /*
-        * Godmar thinks - if the link count is zero, then the inode is
-        * unused - according to ext2 standards. Ufs marks this fact by
-        * setting i_mode to zero - why ? I can see that this might lead to
-        * problems in an undelete.
-        */
-       ip->i_mode = ip->i_nlink ? le16toh(ei->e2di_mode) : 0;
        ip->i_size = le32toh(ei->e2di_size);
        if (S_ISREG(ip->i_mode))
                ip->i_size |= (uint64_t)le32toh(ei->e2di_size_high) << 32;

Reply via email to