From: Darrick J. Wong <djwong@xxxxxxxxxx> Update userspace utilities not to allow integer overflows of inode link counts to result in a file that is referenced by parent directories but has zero link count. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> Reviewed-by: Christoph Hellwig <hch@xxxxxx> --- libxfs/util.c | 3 ++- repair/incore_ino.c | 14 +++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/libxfs/util.c b/libxfs/util.c index dc54e3ee6..74eea0fcb 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -252,7 +252,8 @@ libxfs_bumplink( xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); - inc_nlink(inode); + if (inode->i_nlink != XFS_NLINK_PINNED) + inc_nlink(inode); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); } diff --git a/repair/incore_ino.c b/repair/incore_ino.c index 0dd7a2f06..6618e534a 100644 --- a/repair/incore_ino.c +++ b/repair/incore_ino.c @@ -89,26 +89,30 @@ nlink_grow_16_to_32(ino_tree_node_t *irec) void add_inode_ref(struct ino_tree_node *irec, int ino_offset) { + union ino_nlink *c; + ASSERT(irec->ino_un.ex_data != NULL); pthread_mutex_lock(&irec->lock); + c = &irec->ino_un.ex_data->counted_nlinks; switch (irec->nlink_size) { case sizeof(uint8_t): - if (irec->ino_un.ex_data->counted_nlinks.un8[ino_offset] < 0xff) { - irec->ino_un.ex_data->counted_nlinks.un8[ino_offset]++; + if (c->un8[ino_offset] < 0xff) { + c->un8[ino_offset]++; break; } nlink_grow_8_to_16(irec); /*FALLTHRU*/ case sizeof(uint16_t): - if (irec->ino_un.ex_data->counted_nlinks.un16[ino_offset] < 0xffff) { - irec->ino_un.ex_data->counted_nlinks.un16[ino_offset]++; + if (c->un16[ino_offset] < 0xffff) { + c->un16[ino_offset]++; break; } nlink_grow_16_to_32(irec); /*FALLTHRU*/ case sizeof(uint32_t): - irec->ino_un.ex_data->counted_nlinks.un32[ino_offset]++; + if (c->un32[ino_offset] != XFS_NLINK_PINNED) + c->un32[ino_offset]++; break; default: ASSERT(0);