git: 5628a0901987 - stable/13 - Avoid unaligned writes by fsck_ffs(8).

From: Kirk McKusick <mckusick_at_FreeBSD.org>
Date: Sun, 27 Feb 2022 01:35:17 UTC
The branch stable/13 has been updated by mckusick:

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

commit 5628a0901987c5f72403cf69e23701f4cc7bc2e2
Author:     Kirk McKusick <mckusick@FreeBSD.org>
AuthorDate: 2022-02-20 21:18:05 +0000
Commit:     Kirk McKusick <mckusick@FreeBSD.org>
CommitDate: 2022-02-26 21:34:11 +0000

    Avoid unaligned writes by fsck_ffs(8).
    
    (cherry picked from commit 7a1c1f6a0332c5b60349a5df0e3ce64e5005b2ff)
---
 sbin/fsck_ffs/setup.c | 30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c
index 87676e8ca7ce..375ba897199a 100644
--- a/sbin/fsck_ffs/setup.c
+++ b/sbin/fsck_ffs/setup.c
@@ -399,17 +399,19 @@ chkrecovery(int devfd)
 {
 	struct fsrecovery *fsr;
 	char *fsrbuf;
-	u_int secsize;
+	u_int secsize, rdsize;
 
 	/*
 	 * Could not determine if backup material exists, so do not
 	 * offer to create it.
 	 */
 	fsrbuf = NULL;
+	rdsize = sblock.fs_fsize;
 	if (ioctl(devfd, DIOCGSECTORSIZE, &secsize) == -1 ||
-	    (fsrbuf = Malloc(secsize)) == NULL ||
-	    blread(devfd, fsrbuf, (SBLOCK_UFS2 - secsize) / dev_bsize,
-	      secsize) != 0) {
+	    rdsize % secsize != 0 ||
+	    (fsrbuf = Malloc(rdsize)) == NULL ||
+	    blread(devfd, fsrbuf, (SBLOCK_UFS2 - rdsize) / dev_bsize,
+	      rdsize) != 0) {
 		free(fsrbuf);
 		return (1);
 	}
@@ -417,7 +419,7 @@ chkrecovery(int devfd)
 	 * Recovery material has already been created, so do not
 	 * need to create it again.
 	 */
-	fsr = (struct fsrecovery *)&fsrbuf[secsize - sizeof *fsr];
+	fsr = (struct fsrecovery *)&fsrbuf[rdsize - sizeof *fsr];
 	if (fsr->fsr_magic == FS_UFS2_MAGIC) {
 		free(fsrbuf);
 		return (1);
@@ -430,8 +432,8 @@ chkrecovery(int devfd)
 }
 
 /*
- * Read the last sector of the boot block, replace the last
- * 20 bytes with the recovery information, then write it back.
+ * Read the last filesystem-size piece of the boot block, replace the
+ * last 20 bytes with the recovery information, then write it back.
  * The recovery information only works for UFS2 filesystems.
  */
 static void
@@ -439,24 +441,26 @@ saverecovery(int readfd, int writefd)
 {
 	struct fsrecovery *fsr;
 	char *fsrbuf;
-	u_int secsize;
+	u_int secsize, rdsize;
 
 	fsrbuf = NULL;
+	rdsize = sblock.fs_fsize;
 	if (sblock.fs_magic != FS_UFS2_MAGIC ||
 	    ioctl(readfd, DIOCGSECTORSIZE, &secsize) == -1 ||
-	    (fsrbuf = Malloc(secsize)) == NULL ||
-	    blread(readfd, fsrbuf, (SBLOCK_UFS2 - secsize) / dev_bsize,
-	      secsize) != 0) {
+	    rdsize % secsize != 0 ||
+	    (fsrbuf = Malloc(rdsize)) == NULL ||
+	    blread(readfd, fsrbuf, (SBLOCK_UFS2 - rdsize) / dev_bsize,
+	      rdsize) != 0) {
 		printf("RECOVERY DATA COULD NOT BE CREATED\n");
 		free(fsrbuf);
 		return;
 	}
-	fsr = (struct fsrecovery *)&fsrbuf[secsize - sizeof *fsr];
+	fsr = (struct fsrecovery *)&fsrbuf[rdsize - sizeof *fsr];
 	fsr->fsr_magic = sblock.fs_magic;
 	fsr->fsr_fpg = sblock.fs_fpg;
 	fsr->fsr_fsbtodb = sblock.fs_fsbtodb;
 	fsr->fsr_sblkno = sblock.fs_sblkno;
 	fsr->fsr_ncg = sblock.fs_ncg;
-	blwrite(writefd, fsrbuf, (SBLOCK_UFS2 - secsize) / secsize, secsize);
+	blwrite(writefd, fsrbuf, (SBLOCK_UFS2 - rdsize) / dev_bsize, rdsize);
 	free(fsrbuf);
 }