Whamcloud - gitweb
ChangeLog, dirblock.c:
authorTheodore Ts'o <tytso@mit.edu>
Sat, 5 May 2001 05:12:14 +0000 (05:12 +0000)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 5 May 2001 05:12:14 +0000 (05:12 +0000)
  dirblock.c (ext2fs_read_dir_block): Check for an directory record
   length which isn't a multiple four, and treat that as an invalid.
   Scan the directory and return an error (EXT2_ET_DIR_CORRUPTED) if the
   directory records are orrupted.
   (ext2fs_write_dir_block): If while byte-swapping the directory block,
   if there's an error, abort and return EXT2_ET_DIR_CORRUPTED.

lib/ext2fs/ChangeLog
lib/ext2fs/dirblock.c

index 13d7299..3dfc275 100644 (file)
@@ -1,3 +1,14 @@
+2001-05-04  Theodore Tso  <tytso@valinux.com>
+
+       * dirblock.c (ext2fs_read_dir_block): Check for an directory
+               record length which isn't a multiple four, and treat that
+               as an invalid.  Scan the directory and return an error
+               (EXT2_ET_DIR_CORRUPTED) if the directory records are
+               corrupted.
+               (ext2fs_write_dir_block): If while byte-swapping the
+               directory block, if there's an error, abort and return
+               EXT2_ET_DIR_CORRUPTED.
+
 2001-05-02  Theodore Tso  <tytso@valinux.com>
 
        * ext2fs.h (EXT2_FLAG_IMAGE_FILE): Add new flag, and add
index cb274b7..dd9fe5f 100644 (file)
@@ -30,23 +30,34 @@ errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
        errcode_t       retval;
        char            *p, *end;
        struct ext2_dir_entry *dirent;
+       struct ext2_dir_entry_2 *dirent2;
+       unsigned int    rec_len, do_swap;
 
        retval = io_channel_read_blk(fs->io, block, 1, buf);
        if (retval)
                return retval;
-       if ((fs->flags & (EXT2_FLAG_SWAP_BYTES|
-                         EXT2_FLAG_SWAP_BYTES_READ)) == 0)
-               return 0;
+       do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES|
+                               EXT2_FLAG_SWAP_BYTES_READ)) != 0;
        p = (char *) buf;
        end = (char *) buf + fs->blocksize;
        while (p < end-8) {
-               dirent = (struct ext2_dir_entry *) p;
-               dirent->inode = ext2fs_swab32(dirent->inode);
-               dirent->rec_len = ext2fs_swab16(dirent->rec_len);
-               dirent->name_len = ext2fs_swab16(dirent->name_len);
-               p += (dirent->rec_len < 8) ? 8 : dirent->rec_len;
+               dirent = (struct ext2_dir_entry_2 *) p;
+               if (do_swap) {
+                       dirent->inode = ext2fs_swab32(dirent->inode);
+                       dirent->rec_len = ext2fs_swab16(dirent->rec_len);
+                       dirent->name_len = ext2fs_swab16(dirent->name_len);
+               }
+               rec_len = dirent->rec_len;
+               if ((rec_len < 8) || (rec_len % 4)) {
+                       rec_len = 8;
+                       retval = EXT2_ET_DIR_CORRUPTED;
+               }
+               dirent2 = dirent;
+               if ((dirent2->name_len +8) > dirent2->rec_len)
+                       retval = EXT2_ET_DIR_CORRUPTED;
+               p += rec_len;
        }
-       return 0;
+       return retval;
 }
 
 errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
@@ -68,7 +79,12 @@ errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
                end = buf + fs->blocksize;
                while (p < end) {
                        dirent = (struct ext2_dir_entry *) p;
-                       p += (dirent->rec_len < 8) ? 8 : dirent->rec_len;
+                       if ((dirent->rec_len < 8) ||
+                           (dirent->rec_len % 4)) {
+                               retval = EXT2_ET_DIR_CORRUPTED;
+                               goto errout;
+                       }
+                       p += dirent->rec_len;
                        dirent->inode = ext2fs_swab32(dirent->inode);
                        dirent->rec_len = ext2fs_swab16(dirent->rec_len);
                        dirent->name_len = ext2fs_swab16(dirent->name_len);
@@ -76,6 +92,7 @@ errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
        } else
                write_buf = (char *) inbuf;
        retval = io_channel_write_blk(fs->io, block, 1, write_buf);
+errout:
        if (buf)
                ext2fs_free_mem((void **) &buf);
        return retval;