It needs to correctly participate in the inode numbers arithmetic. It is possible to have inode number that is negative if truncated to 32 bit, which causes OOB accesses in ginode() calculating inode location in the inode block: ip->i_dp = (union dinode *) &ip->i_bp->b_un.b_dinode2[inumber - ip->i_bp->b_index];
Details
Details
Diff Detail
Diff Detail
- Repository
- rG FreeBSD src repository
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
Event Timeline
Comment Actions
The patch is written to handle the real problem on my home machine.
I used a different change to get my (large) volume back:
diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c index f7b9b941fdb4..2538bf66d394 100644 --- a/sbin/fsck_ffs/inode.c +++ b/sbin/fsck_ffs/inode.c @@ -473,15 +473,15 @@ ginode(ino_t inumber, struct inode *ip) ip->i_bp = icachebp; } if (sblock.fs_magic == FS_UFS1_MAGIC) { - ip->i_dp = (union dinode *) - &ip->i_bp->b_un.b_dinode1[inumber - ip->i_bp->b_index]; + ip->i_dp = (union dinode *) &ip->i_bp->b_un.b_dinode1[ + inumber - (unsigned)ip->i_bp->b_index]; dpp.dp1 = (struct ufs1_dinode *)ip->i_dp; if (ffs_oldfscompat_inode_read(&sblock, dpp, now)) inodirty(ip); return; } ip->i_dp = (union dinode *) - &ip->i_bp->b_un.b_dinode2[inumber - ip->i_bp->b_index]; + &ip->i_bp->b_un.b_dinode2[inumber - (unsigned)ip->i_bp->b_index]; dpp.dp2 = dp = (struct ufs2_dinode *)ip->i_dp; /* Do not check hash of inodes being created */ if (dp->di_mode != 0 && ffs_verify_dinode_ckhash(&sblock, dp)) {
Then decided that this is really a missed place from ino64.