@@ -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);
}
@@ -912,6 +912,12 @@ static inline uint xfs_dinode_size(int version)
*/
#define XFS_MAXLINK ((1U << 31) - 1U)
+/*
+ * Any file that hits the maximum ondisk link count should be pinned to avoid
+ * a use-after-free situation.
+ */
+#define XFS_NLINK_PINNED (~0U)
+
/*
* Values for di_format
*
@@ -108,7 +108,8 @@ void add_inode_ref(struct ino_tree_node *irec, int ino_offset)
nlink_grow_16_to_32(irec);
/*FALLTHRU*/
case sizeof(uint32_t):
- irec->ino_un.ex_data->counted_nlinks.un32[ino_offset]++;
+ if (irec->ino_un.ex_data->counted_nlinks.un32[ino_offset] != XFS_NLINK_PINNED)
+ irec->ino_un.ex_data->counted_nlinks.un32[ino_offset]++;
break;
default:
ASSERT(0);