diff --git a/sys/fs/ext2fs/ext2_lookup.c b/sys/fs/ext2fs/ext2_lookup.c --- a/sys/fs/ext2fs/ext2_lookup.c +++ b/sys/fs/ext2fs/ext2_lookup.c @@ -79,15 +79,8 @@ SDT_PROBE_DEFINE5(ext2fs, , trace, ext2_dirbadentry_error, "char*", "int", "uint32_t", "uint16_t", "uint8_t"); -#ifdef INVARIANTS -static int dirchk = 1; -#else -static int dirchk = 0; -#endif - static SYSCTL_NODE(_vfs, OID_AUTO, e2fs, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "EXT2FS filesystem"); -SYSCTL_INT(_vfs_e2fs, OID_AUTO, dircheck, CTLFLAG_RW, &dirchk, 0, ""); /* DIRBLKSIZE in ffs is DEV_BSIZE (in most cases 512) @@ -129,8 +122,8 @@ #define DTTOFT(dt) \ ((dt) < nitems(dt_to_ext2_ft) ? dt_to_ext2_ft[(dt)] : EXT2_FT_UNKNOWN) -static int ext2_dirbadentry(struct vnode *dp, struct ext2fs_direct_2 *de, - int entryoffsetinblock); +static int ext2_check_direntry(struct vnode *dp, + struct ext2fs_direct_2 *de, int entryoffsetinblock); static int ext2_is_dot_entry(struct componentname *cnp); static int ext2_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp, ino_t *dd_ino); @@ -734,20 +727,14 @@ ep = (struct ext2fs_direct_2 *)((char *)data + offset); top = (struct ext2fs_direct_2 *)((char *)data + bsize); while (ep < top) { - /* - * Full validation checks are slow, so we only check - * enough to insure forward progress through the - * directory. Complete checks can be run by setting - * "vfs.e2fs.dirchk" to be true. - */ - if (le16toh(ep->e2d_reclen) == 0 || - (dirchk && ext2_dirbadentry(vdp, ep, offset))) { + if (ext2_check_direntry(vdp, ep, offset)) { int i; ext2_dirbad(ip, *offp, "mangled entry"); i = bsize - (offset & (bsize - 1)); *offp += i; offset += i; + ep = (struct ext2fs_direct_2 *)((char *)data + offset); continue; } @@ -836,15 +823,11 @@ * name is not longer than MAXNAMLEN * name must be as long as advertised, and null terminated */ -/* - * changed so that it confirms to ext2_check_dir_entry - */ static int -ext2_dirbadentry(struct vnode *dp, struct ext2fs_direct_2 *de, +ext2_check_direntry(struct vnode *dp, struct ext2fs_direct_2 *de, int entryoffsetinblock) { - int DIRBLKSIZ = VTOI(dp)->i_e2fs->e2fs_bsize; - + struct m_ext2fs *fs = VTOI(dp)->i_e2fs; char *error_msg = NULL; if (le16toh(de->e2d_reclen) < EXT2_DIR_REC_LEN(1)) @@ -853,12 +836,10 @@ error_msg = "rec_len % 4 != 0"; else if (le16toh(de->e2d_reclen) < EXT2_DIR_REC_LEN(de->e2d_namlen)) error_msg = "reclen is too small for name_len"; - else if (entryoffsetinblock + le16toh(de->e2d_reclen)> DIRBLKSIZ) + else if (entryoffsetinblock + le16toh(de->e2d_reclen)> fs->e2fs_bsize) error_msg = "directory entry across blocks"; - /* else LATER - if (de->inode > dir->i_sb->u.ext2_sb.s_es->s_inodes_count) - error_msg = "inode out of bounds"; - */ + else if (le32toh(de->e2d_ino) > fs->e2fs->e2fs_icount) + error_msg = "directory entry inode out of bounds"; if (error_msg != NULL) { SDT_PROBE5(ext2fs, , trace, ext2_dirbadentry_error, @@ -866,7 +847,7 @@ le32toh(de->e2d_ino), le16toh(de->e2d_reclen), de->e2d_namlen); } - return (error_msg == NULL ? 0 : 1); + return (error_msg == NULL ? 0 : EINVAL); } /*