From: Chris Wright Date: Fri, 24 Mar 2006 18:05:58 +0000 (-0800) Subject: ext2_readdir fix X-Git-Tag: v2.6.16.1~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ac6dc5f654b2ac0d4e6b9683b1739b7b00ed0dad;p=thirdparty%2Fkernel%2Fstable-queue.git ext2_readdir fix --- diff --git a/queue/fix-ext2-readdir-f_pos-re-validation-logic.patch b/queue/fix-ext2-readdir-f_pos-re-validation-logic.patch new file mode 100644 index 00000000000..00856c71a55 --- /dev/null +++ b/queue/fix-ext2-readdir-f_pos-re-validation-logic.patch @@ -0,0 +1,105 @@ +From nobody Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Wed Mar 15 21:41:59 2006 +0000 +Subject: [PATCH] Fix ext2 readdir f_pos re-validation logic + +This fixes not one, but _two_, silly (but admittedly hard to hit) bugs +in the ext2 filesystem "readdir()" function. It also cleans up the code +to avoid the unnecessary goto mess. + +The bugs were related to re-valiating the f_pos value after somebody had +either done an "lseek()" on the directory to an invalid offset, or when +the offset had become invalid due to a file being unlinked in the +directory. The code would not only set the f_version too eagerly, it +would also not update f_pos appropriately for when the offset fixup took +place. + +When that happened, we'd occasionally subsequently fail the readdir() +even when we shouldn't (no real harm done, but an ugly printk, and +obviously you would end up not necessarily seeing all entries). + +Thanks to Masoud Sharbiani who noticed the problem +and had a test-case for it, and also fixed up a thinko in the first +version of this patch. + +Signed-off-by: Al Viro +Acked-by: Masoud Sharbiani +Signed-off-by: Linus Torvalds +Signed-off-by: Chris Wright +--- + + fs/ext2/dir.c | 28 ++++++++++++---------------- + 1 files changed, 12 insertions(+), 16 deletions(-) + +2d7f2ea9c989853310c7f6e8be52cc090cc8e66b +diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c +index 7442bdd..b3dbd71 100644 +--- linux-2.6.15.6.orig/fs/ext2/dir.c ++++ linux-2.6.15.6/fs/ext2/dir.c +@@ -256,11 +256,10 @@ ext2_readdir (struct file * filp, void * + unsigned long npages = dir_pages(inode); + unsigned chunk_mask = ~(ext2_chunk_size(inode)-1); + unsigned char *types = NULL; +- int need_revalidate = (filp->f_version != inode->i_version); +- int ret; ++ int need_revalidate = filp->f_version != inode->i_version; + + if (pos > inode->i_size - EXT2_DIR_REC_LEN(1)) +- goto success; ++ return 0; + + if (EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE)) + types = ext2_filetype_table; +@@ -275,12 +274,15 @@ ext2_readdir (struct file * filp, void * + "bad page in #%lu", + inode->i_ino); + filp->f_pos += PAGE_CACHE_SIZE - offset; +- ret = -EIO; +- goto done; ++ return -EIO; + } + kaddr = page_address(page); +- if (need_revalidate) { +- offset = ext2_validate_entry(kaddr, offset, chunk_mask); ++ if (unlikely(need_revalidate)) { ++ if (offset) { ++ offset = ext2_validate_entry(kaddr, offset, chunk_mask); ++ filp->f_pos = (n<f_version = inode->i_version; + need_revalidate = 0; + } + de = (ext2_dirent *)(kaddr+offset); +@@ -289,9 +291,8 @@ ext2_readdir (struct file * filp, void * + if (de->rec_len == 0) { + ext2_error(sb, __FUNCTION__, + "zero-length directory entry"); +- ret = -EIO; + ext2_put_page(page); +- goto done; ++ return -EIO; + } + if (de->inode) { + int over; +@@ -306,19 +307,14 @@ ext2_readdir (struct file * filp, void * + le32_to_cpu(de->inode), d_type); + if (over) { + ext2_put_page(page); +- goto success; ++ return 0; + } + } + filp->f_pos += le16_to_cpu(de->rec_len); + } + ext2_put_page(page); + } +- +-success: +- ret = 0; +-done: +- filp->f_version = inode->i_version; +- return ret; ++ return 0; + } + + /* diff --git a/queue/series b/queue/series index ff952e30f6c..b3c1dd868c6 100644 --- a/queue/series +++ b/queue/series @@ -5,3 +5,4 @@ cramfs-mounts-provide-corrupted-content-since-2.6.15.patch kconfig-video_decoder-must-select-fw_loader.patch tcp-do-not-use-inet-id-of-global-tcp_socket-when-sending-rst.patch net-ensure-device-name-passed-to-so_bindtodevice-is-null-terminated.patch +fix-ext2-readdir-f_pos-re-validation-logic.patch