svn commit: r300257 - in head/sys/boot/i386: libi386 zfsboot

Allan Jude allanjude at FreeBSD.org
Fri May 20 01:41:48 UTC 2016


Author: allanjude
Date: Fri May 20 01:41:47 2016
New Revision: 300257
URL: https://svnweb.freebsd.org/changeset/base/300257

Log:
  Fixup the geliboot sector rounding code
  
  Replace all rounding with the round{up,down}2 macros
  a missing set of braces caused the previous code to be incorrect
  
  replace alloca() with malloc() because alloca() can return an allocation
  that is actually invalid, causing boot to fail
  
  Reviewed by:	emaste, ed
  Thanks To:	peter
  Sponsored by:	ScaleEngine Inc.
  Differential Revision:	https://reviews.freebsd.org/D6213

Modified:
  head/sys/boot/i386/libi386/biosdisk.c
  head/sys/boot/i386/zfsboot/zfsboot.c

Modified: head/sys/boot/i386/libi386/biosdisk.c
==============================================================================
--- head/sys/boot/i386/libi386/biosdisk.c	Fri May 20 01:38:31 2016	(r300256)
+++ head/sys/boot/i386/libi386/biosdisk.c	Fri May 20 01:41:47 2016	(r300257)
@@ -749,21 +749,29 @@ bd_read(struct disk_devdesc *dev, daddr_
 		 * sectors cannot be decrypted. Round the requested LBA down to
 		 * nearest multiple of DEV_GELIBOOT_BSIZE bytes.
 		 */
-		alignlba = dblk &
-		    ~(daddr_t)((DEV_GELIBOOT_BSIZE / BIOSDISK_SECSIZE) - 1);
+		alignlba = rounddown2(dblk * BD(dev).bd_sectorsize,
+		    DEV_GELIBOOT_BSIZE) / BD(dev).bd_sectorsize;
 		/*
 		 * Round number of blocks to read up to nearest multiple of
 		 * DEV_GELIBOOT_BSIZE
 		 */
-		alignblks = blks + (dblk - alignlba) +
-		    ((DEV_GELIBOOT_BSIZE / BIOSDISK_SECSIZE) - 1) &
-		    ~(int)((DEV_GELIBOOT_BSIZE / BIOSDISK_SECSIZE) - 1);
-		diff = (dblk - alignlba) * BIOSDISK_SECSIZE;
+		diff = (dblk - alignlba) * BD(dev).bd_sectorsize;
+		alignblks = roundup2(blks * BD(dev).bd_sectorsize + diff,
+		    DEV_GELIBOOT_BSIZE) / BD(dev).bd_sectorsize;
+
 		/*
-		 * Use a temporary buffer here because the buffer provided by
-		 * the caller may be too small.
+		 * If the read is rounded up to a larger size, use a temporary
+		 * buffer here because the buffer provided by the caller may be
+		 * too small.
 		 */
-		tmpbuf = alloca(alignblks * BIOSDISK_SECSIZE);
+		if (diff == 0) {
+			tmpbuf = dest;
+		} else {
+			tmpbuf = malloc(alignblks * BD(dev).bd_sectorsize);
+			if (tmpbuf == NULL) {
+				return (-1);
+			}
+		}
 
 		err = bd_io(dev, alignlba, alignblks, tmpbuf, 0);
 		if (err)
@@ -779,12 +787,15 @@ bd_read(struct disk_devdesc *dev, daddr_
 		/* GELI needs the offset relative to the partition start */
 		p_off = alignlba - dskp.start;
 
-		err = geli_read(&dskp, p_off * BIOSDISK_SECSIZE, tmpbuf,
-		    alignblks * BIOSDISK_SECSIZE);
+		err = geli_read(&dskp, p_off * BD(dev).bd_sectorsize, tmpbuf,
+		    alignblks * BD(dev).bd_sectorsize);
 		if (err)
 			return (err);
 
-		bcopy(tmpbuf + diff, dest, blks * BIOSDISK_SECSIZE);
+		if (tmpbuf != dest) {
+			bcopy(tmpbuf + diff, dest, blks * BD(dev).bd_sectorsize);
+			free(tmpbuf);
+		}
 		return (0);
 	}
 #endif /* LOADER_GELI_SUPPORT */
@@ -898,10 +909,10 @@ bios_read(void *vdev __unused, struct ds
 	dev.d_partition = priv->part;
 	dev.d_offset = priv->start;
 
-	off = off / BIOSDISK_SECSIZE;
+	off = off / BD(&dev).bd_sectorsize;
 	/* GELI gives us the offset relative to the partition start */
 	off += dev.d_offset;
-	bytes = bytes / BIOSDISK_SECSIZE;
+	bytes = bytes / BD(&dev).bd_sectorsize;
 
 	return (bd_io(&dev, off, bytes, buf, 0));
 }

Modified: head/sys/boot/i386/zfsboot/zfsboot.c
==============================================================================
--- head/sys/boot/i386/zfsboot/zfsboot.c	Fri May 20 01:38:31 2016	(r300256)
+++ head/sys/boot/i386/zfsboot/zfsboot.c	Fri May 20 01:41:47 2016	(r300257)
@@ -200,7 +200,7 @@ vdev_read(vdev_t *vdev, void *priv, off_
 {
 	char *p;
 	daddr_t lba, alignlba;
-	off_t alignoff, diff;
+	off_t diff;
 	unsigned int nb, alignnb;
 	struct dsk *dsk = (struct dsk *) priv;
 
@@ -210,10 +210,11 @@ vdev_read(vdev_t *vdev, void *priv, off_
 	p = buf;
 	lba = off / DEV_BSIZE;
 	lba += dsk->start;
-	/* Align reads to 4k else 4k sector GELIs will not decrypt. */
-	alignoff = off & ~ (off_t)(DEV_GELIBOOT_BSIZE - 1);
-	/* Round LBA down to nearest multiple of DEV_GELIBOOT_BSIZE bytes. */
-	alignlba = alignoff / DEV_BSIZE;
+	/*
+	 * Align reads to 4k else 4k sector GELIs will not decrypt.
+	 * Round LBA down to nearest multiple of DEV_GELIBOOT_BSIZE bytes.
+	 */
+	alignlba = rounddown2(off, DEV_GELIBOOT_BSIZE) / DEV_BSIZE;
 	/*
 	 * The read must be aligned to DEV_GELIBOOT_BSIZE bytes relative to the
 	 * start of the GELI partition, not the start of the actual disk.


More information about the svn-src-head mailing list