lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Sat,  9 Jan 2021 16:40:53 -0600
From:   Steve Magnani <magnani@...e.org>
To:     Jan Kara <jack@...e.com>
Cc:     linux-kernel@...r.kernel.org,
        "Steven J . Magnani" <magnani@...e.org>
Subject: [PATCH 1/2] udf: fix hole append when File Tail exists

From: Steven J. Magnani <magnani@...e.org>

When an ALLOCATED_NOT_RECORDED extent ("File Tail") follows the
extents describing a file body, don't (improperly) try to make use of it
as part of appending a hole to the file.

Fixes: fa33cdbf3ece ("udf: Fix incorrect final NOT_ALLOCATED (hole) extent length")
Signed-off-by: Steven J. Magnani <magnani@...e.org>
---
--- a/fs/udf/inode.c	2020-12-28 20:51:29.000000000 -0600
+++ b/fs/udf/inode.c	2021-01-02 17:00:39.794157840 -0600
@@ -520,8 +520,7 @@ static int udf_do_extend_file(struct ino
 		prealloc_loc = last_ext->extLocation;
 		prealloc_len = last_ext->extLength;
 		/* Mark the extent as a hole */
-		last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
-			(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
+		last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
 		last_ext->extLocation.logicalBlockNum = 0;
 		last_ext->extLocation.partitionReferenceNum = 0;
 	}
@@ -626,7 +625,6 @@ static void udf_do_extend_final_block(st
 
 static int udf_extend_file(struct inode *inode, loff_t newsize)
 {
-
 	struct extent_position epos;
 	struct kernel_lb_addr eloc;
 	uint32_t elen;
@@ -639,6 +637,7 @@ static int udf_extend_file(struct inode
 	struct kernel_long_ad extent;
 	int err = 0;
 	int within_final_block;
+	loff_t hole_size = 0;
 
 	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
 		adsize = sizeof(struct short_ad);
@@ -648,7 +647,8 @@ static int udf_extend_file(struct inode
 		BUG();
 
 	etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
-	within_final_block = (etype != -1);
+	within_final_block = (etype == (EXT_RECORDED_ALLOCATED >> 30)) ||
+			     (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30));
 
 	if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) ||
 	    (epos.bh && epos.offset == sizeof(struct allocExtDesc))) {
@@ -658,9 +658,15 @@ static int udf_extend_file(struct inode
 		extent.extLocation.partitionReferenceNum = 0;
 		extent.extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
 	} else {
+		int8_t bmap_etype = etype;
 		epos.offset -= adsize;
 		etype = udf_next_aext(inode, &epos, &extent.extLocation,
 				      &extent.extLength, 0);
+		if ((bmap_etype == -1) &&
+		    (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))) {
+			/* offset is relative to prealloc extent end */
+			hole_size = extent.extLength;
+		}
 		extent.extLength |= etype << 30;
 	}
 
@@ -674,9 +680,9 @@ static int udf_extend_file(struct inode
 		udf_do_extend_final_block(inode, &epos, &extent,
 					  partial_final_block);
 	} else {
-		loff_t add = ((loff_t)offset << sb->s_blocksize_bits) |
+		hole_size += ((loff_t)offset << sb->s_blocksize_bits) |
 			     partial_final_block;
-		err = udf_do_extend_file(inode, &epos, &extent, add);
+		err = udf_do_extend_file(inode, &epos, &extent, hole_size);
 	}
 
 	if (err < 0)
@@ -700,7 +706,7 @@ static sector_t inode_getblk(struct inod
 	loff_t lbcount = 0, b_off = 0;
 	udf_pblk_t newblocknum, newblock;
 	sector_t offset = 0;
-	int8_t etype;
+	int8_t etype = -1;
 	struct udf_inode_info *iinfo = UDF_I(inode);
 	udf_pblk_t goal = 0, pgoal = iinfo->i_location.logicalBlockNum;
 	int lastblock = 0;
@@ -729,14 +735,22 @@ static sector_t inode_getblk(struct inod
 			cur_epos.bh = next_epos.bh;
 		}
 
-		lbcount += elen;
-
 		prev_epos.block = cur_epos.block;
 		cur_epos.block = next_epos.block;
 
 		prev_epos.offset = cur_epos.offset;
 		cur_epos.offset = next_epos.offset;
 
+		/* Corner case: preallocated extent that stops short of
+		 * desired block
+		 */
+		if ((etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) &&
+		    ((lbcount + elen) <= b_off)) {
+			etype = -1;
+			break;
+		}
+
+		lbcount += elen;
 		etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 1);
 		if (etype == -1)
 			break;

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ