[PATCH] fs/isofs/dir.c bug in 2.2.x

Oliver Mueschke (o@mueschke.de)
Sun, 01 Aug 1999 08:25:06 +0200


some people (including me) were complaining about missing
files when doing ls -lR or find in isofs file systems.
i tracked this down to a bug in fs/isofs/dir.c.

the bug is triggered when the following conditions apply:
i) a directory spans multiple blocks on cd,
ii) the last directory entry of one of the blocks ends
exactly at the last byte of the block.
in that case do_isofs_readdir() reads past the end of the
block buffer. if by chance the very next byte after the
valid buffer is 0 then do_isofs_readdir() incorrectly
assumes to have reached the end of the directory. the
entries in the subsequent blocks are silently ignored.

this bug was introduced in the 2.1.x days (i checked
2.1.60). the patch below fixes it. i think it should
go in 2.2.11.

oliver

--- dir.c.orig Sat Apr 24 06:20:38 1999
+++ dir.c Sun Aug 1 00:37:31 1999
@@ -157,12 +157,32 @@
block, offset, filp->f_pos);
printk("inode->i_size = %x\n",inode->i_size);
#endif
+ /* Next directory_record on next CDROM sector */
+ if (offset >= bufsize) {
+#ifdef DEBUG
+ printk("offset >= bufsize\n");
+#endif
+ brelse(bh);
+ offset = 0;
+ block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
+ if (!block)
+ return 0;
+ bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
+ if (!bh)
+ return 0;
+ continue;
+ }
+
+ de = (struct iso_directory_record *) (bh->b_data + offset);
+ if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1));
+
+
de = (struct iso_directory_record *) (bh->b_data + offset);
if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1));

de_len = *(unsigned char *) de;
#ifdef DEBUG
- printk("de_len = %ld\n", de_len);
+ printk("de_len = %d\n", de_len);
#endif


@@ -170,16 +190,11 @@
CDROM sector. If we are at the end of the directory, we
kick out of the while loop. */

- if ((de_len == 0) || (offset >= bufsize) ) {
+ if (de_len == 0) {
brelse(bh);
- if (de_len == 0) {
- filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
- + ISOFS_BLOCK_SIZE);
- offset = 0;
- } else {
- offset -= bufsize;
- filp->f_pos += offset;
- }
+ filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
+ + ISOFS_BLOCK_SIZE);
+ offset = 0;

if (filp->f_pos >= inode->i_size)
return 0;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/