Skip to contentSkip to conversation

gfs2: Check for the end of metadata in punch_hole

PATCH New Andreas Gruenbacher 2 participants 2 messages Mar 23, 2018 GFS2 file system

lore
Share & tools
lore

Andreas Gruenbacher

author maintainer
#0 lore raw

PATCH 1/1 gfs2: Check for the end of metadata in punch_hole

When punching a hole or truncating an inode down to a given size, also check if the truncate point / start of the hole is within the range we have metadata for. Otherwise, we can end up freeing blocks that shouldn't be freed, corrupting the inode, or crashing the machine when trying to punch a hole into the void.

When growing an inode via truncate, we set the new size but we don't allocate additional levels of indirect blocks and grow the inode height. When shrinking that inode again, the new size may still point beyond the end of the inode's metadata.

Fixes xfstest generic/476.

---
 fs/gfs2/bmap.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
fs/gfs2/bmap.c +9 -1
index 51f940e76c5e..cec1d4a0d12c 100644
@@ -1344,6 +1344,7 @@ static inline bool walk_done(struct gfs2_sbd *sdp,
 static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+	u64 maxsize = sdp->sd_heightsize[ip->i_height];
 	struct metapath mp = {};
 	struct buffer_head *dibh, *bh;
 	struct gfs2_holder rd_gh;
@@ -1371,8 +1372,15 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
 	 * needs to be preserved for the remaining data.
 	 */
 
+	if (offset >= maxsize) {
+		/*
+		 * The starting point lies beyond the allocated meta-data;
+		 * there are no blocks do deallocate.
+		 */
+		return 0;
+	}
+
 	if (length) {
-		u64 maxsize = sdp->sd_heightsize[ip->i_height];
 		u64 end_offset = offset + length;
 		u64 lend;
 
Signature · 1 line
2.14.3
#1 lore raw

PATCH 1/1 gfs2: Check for the end of metadata in punch_hole

----- Original Message -----

| When punching a hole or truncating an inode down to a given size, also
| check if the truncate point / start of the hole is within the range we
| have metadata for.  Otherwise, we can end up freeing blocks that
| shouldn't be freed, corrupting the inode, or crashing the machine when
| trying to punch a hole into the void.
| 
| When growing an inode via truncate, we set the new size but we don't
| allocate additional levels of indirect blocks and grow the inode height.
| When shrinking that inode again, the new size may still point beyond the
| end of the inode's metadata.
| 
| Fixes xfstest generic/476.
| 
| Debugged-by: Bob Peterson <[email protected]>
| Signed-off-by: Andreas Gruenbacher <[email protected]>
| ---

Hi,

Thanks. This is now pushed to the for-next branch of the linux-gfs2 tree:
https://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git/commit/fs/gfs2?h=for-next&id=bb491ce67aa7c1635e5ae4f2f304a7d13d3dbe71

Regards,

Bob Peterson
Red Hat File Systems