Fixes bug with ext2_readdir()
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 13 Oct 2010 01:15:42 +0000 (18:15 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:55 +0000 (17:35 -0700)
It was dropping some items near the end of directories (since not all
dirents are 8 + 256 bytes long).

kern/include/ext2fs.h
kern/src/ext2fs.c

index 9e948ad..9c9e504 100644 (file)
@@ -238,7 +238,7 @@ struct ext2_inode {
 struct ext2_dirent {
        uint32_t                                        dir_inode;                      /* inode */
        uint16_t                                        dir_reclen;                     /* len, including padding */
-       uint8_t                                         dir_namelen;            /* len of dir_name */
+       uint8_t                                         dir_namelen;            /* len of dir_name w/o \0 */
        uint8_t                                         dir_filetype;
        uint8_t                                         dir_name[256];          /* might be < 255 on disc */
 };
index d6ed1cb..2d1cb3d 100644 (file)
@@ -1057,10 +1057,8 @@ int ext2_readdir(struct file *dir, struct dirent *dirent)
 {
        void *blk_buf;
        /* Not enough data at the end of the directory */
-       if (dir->f_dentry->d_inode->i_size <
-           dirent->d_off + sizeof(struct ext2_dirent))
+       if (dir->f_dentry->d_inode->i_size < dirent->d_off + 8)
                return -ENOENT;
-       
        /* Figure out which block we need to read in for dirent->d_off */
        int block = dirent->d_off / dir->f_dentry->d_sb->s_blocksize;
        blk_buf = ext2_get_ino_metablock(dir->f_dentry->d_inode, block);
@@ -1070,6 +1068,8 @@ int ext2_readdir(struct file *dir, struct dirent *dirent)
        struct ext2_dirent *e2dir = (struct ext2_dirent*)(blk_buf + f_off);
        dirent->d_ino = le32_to_cpu(e2dir->dir_inode);
        dirent->d_off += le16_to_cpu(e2dir->dir_reclen);
+       if (dir->f_dentry->d_inode->i_size < dirent->d_off)
+               panic("Something is jacked with the dirent going beyond the dir/file");
        /* note, dir_namelen doesn't include the \0 */
        dirent->d_reclen = e2dir->dir_namelen;
        strncpy(dirent->d_name, (char*)e2dir->dir_name, e2dir->dir_namelen);