git: a3628327e7b6 - main - Ensure that files with no allocated blocks are trimmed to zero length.

Kirk McKusick mckusick at FreeBSD.org
Tue May 11 21:48:34 UTC 2021


The branch main has been updated by mckusick:

URL: https://cgit.FreeBSD.org/src/commit/?id=a3628327e7b62c955e7bad9e43044cdb01984d80

commit a3628327e7b62c955e7bad9e43044cdb01984d80
Author:     Kirk McKusick <mckusick at FreeBSD.org>
AuthorDate: 2021-05-11 21:51:06 +0000
Commit:     Kirk McKusick <mckusick at FreeBSD.org>
CommitDate: 2021-05-11 21:52:26 +0000

    Ensure that files with no allocated blocks are trimmed to zero length.
    
    UFS does not allow files to end with a hole; it requires that the
    last block of a file be allocated. As fsck_ffs(8) initially scans
    each allocated inode, it tracks the last allocated block in the
    inode. It then checks that the inode's size falls in the last
    allocated block. If the last allocated block falls before the size,
    a `file size beyond end of allocated file' warning is issued and
    the file is shortened to reference the last allocated block (to avoid
    having it reference a hole at its end). If the last allocated block
    falls after the size, a `partially truncated file' warning is issued
    and all blocks following the block referenced by the size are freed.
    
    Because of an incorrect unsigned comparison, this test was failing
    to handle files with no allocated blocks but non-zero size (which
    should have had their size reset to zero). Once that was fixed the
    test started incorrectly complaining about short symbolic links
    that place the link path in the inode rather than in a disk block.
    Because these symbolic links have a non-zero size, but no allocated
    blocks, fsck_ffs wanted to zero out their size. This patch has to
    detect and avoid changing the size of such symbolic links.
    
    Reported by:  Chuck Silvers
    Tested by:    Chuck Silvers
    MFC after:    1 week
    Sponsored by: Netflix
---
 sbin/fsck_ffs/pass1.c | 38 +++++++++++++++++++++++++-------------
 1 file changed, 25 insertions(+), 13 deletions(-)

diff --git a/sbin/fsck_ffs/pass1.c b/sbin/fsck_ffs/pass1.c
index c1f1b1ec04f5..319a324cc070 100644
--- a/sbin/fsck_ffs/pass1.c
+++ b/sbin/fsck_ffs/pass1.c
@@ -248,7 +248,7 @@ checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
 	off_t kernmaxfilesize;
 	ufs2_daddr_t ndb;
 	mode_t mode;
-	uintmax_t fixsize;
+	intmax_t size, fixsize;
 	int j, ret, offset;
 
 	if ((dp = getnextinode(inumber, rebuildcg)) == NULL)
@@ -429,25 +429,37 @@ checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
 		}
 	}
 	/*
+	 * UFS does not allow files to end with a hole; it requires that
+	 * the last block of a file be allocated. The last allocated block
+	 * in a file is tracked in id_lballoc. Here, we check for a size
+	 * past the last allocated block of the file and if that is found,
+	 * shorten the file to reference the last allocated block to avoid
+	 * having it reference a hole at its end.
+	 * 
 	 * Soft updates will always ensure that the file size is correct
 	 * for files that contain only direct block pointers. However
 	 * soft updates does not roll back sizes for files with indirect
 	 * blocks that it has set to unallocated because their contents
 	 * have not yet been written to disk. Hence, the file can appear
 	 * to have a hole at its end because the block pointer has been
-	 * rolled back to zero. Thus, id_lballoc tracks the last allocated
-	 * block in the file. Here, for files that extend into indirect
-	 * blocks, we check for a size past the last allocated block of
-	 * the file and if that is found, shorten the file to reference
-	 * the last allocated block to avoid having it reference a hole
-	 * at its end.
+	 * rolled back to zero. Thus finding a hole at the end of a file
+	 * that is located in an indirect block receives only a warning
+	 * while finding a hole at the end of a file in a direct block
+	 * receives a fatal error message.
 	 */
-	if (DIP(dp, di_size) > UFS_NDADDR * sblock.fs_bsize &&
-	    idesc->id_lballoc < lblkno(&sblock, DIP(dp, di_size) - 1)) {
-		fixsize = lblktosize(&sblock, idesc->id_lballoc + 1);
-		pwarn("INODE %lu: FILE SIZE %ju BEYOND END OF ALLOCATED FILE, "
-		      "SIZE SHOULD BE %ju", (u_long)inumber,
-		      (uintmax_t)DIP(dp, di_size), fixsize);
+	size = DIP(dp, di_size);
+	if (idesc->id_lballoc < lblkno(&sblock, size - 1) &&
+	    /* exclude embedded symbolic links */
+	    ((mode != IFLNK) || size >= sblock.fs_maxsymlinklen)) {
+ 		fixsize = lblktosize(&sblock, idesc->id_lballoc + 1);
+		if (size > UFS_NDADDR * sblock.fs_bsize)
+			pwarn("INODE %lu: FILE SIZE %ju BEYOND END OF "
+			      "ALLOCATED FILE, SIZE SHOULD BE %ju",
+			      (u_long)inumber, size, fixsize);
+		else
+			pfatal("INODE %lu: FILE SIZE %ju BEYOND END OF "
+			      "ALLOCATED FILE, SIZE SHOULD BE %ju",
+			      (u_long)inumber, size, fixsize);
 		if (preen)
 			printf(" (ADJUSTED)\n");
 		else if (reply("ADJUST") == 0)


More information about the dev-commits-src-all mailing list