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
This commit is contained in:
parent
71957470d5
commit
02fd555670
@ -749,21 +749,29 @@ bd_read(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest)
|
|||||||
* sectors cannot be decrypted. Round the requested LBA down to
|
* sectors cannot be decrypted. Round the requested LBA down to
|
||||||
* nearest multiple of DEV_GELIBOOT_BSIZE bytes.
|
* nearest multiple of DEV_GELIBOOT_BSIZE bytes.
|
||||||
*/
|
*/
|
||||||
alignlba = dblk &
|
alignlba = rounddown2(dblk * BD(dev).bd_sectorsize,
|
||||||
~(daddr_t)((DEV_GELIBOOT_BSIZE / BIOSDISK_SECSIZE) - 1);
|
DEV_GELIBOOT_BSIZE) / BD(dev).bd_sectorsize;
|
||||||
/*
|
/*
|
||||||
* Round number of blocks to read up to nearest multiple of
|
* Round number of blocks to read up to nearest multiple of
|
||||||
* DEV_GELIBOOT_BSIZE
|
* DEV_GELIBOOT_BSIZE
|
||||||
*/
|
*/
|
||||||
alignblks = blks + (dblk - alignlba) +
|
diff = (dblk - alignlba) * BD(dev).bd_sectorsize;
|
||||||
((DEV_GELIBOOT_BSIZE / BIOSDISK_SECSIZE) - 1) &
|
alignblks = roundup2(blks * BD(dev).bd_sectorsize + diff,
|
||||||
~(int)((DEV_GELIBOOT_BSIZE / BIOSDISK_SECSIZE) - 1);
|
DEV_GELIBOOT_BSIZE) / BD(dev).bd_sectorsize;
|
||||||
diff = (dblk - alignlba) * BIOSDISK_SECSIZE;
|
|
||||||
/*
|
/*
|
||||||
* Use a temporary buffer here because the buffer provided by
|
* If the read is rounded up to a larger size, use a temporary
|
||||||
* the caller may be too small.
|
* 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);
|
err = bd_io(dev, alignlba, alignblks, tmpbuf, 0);
|
||||||
if (err)
|
if (err)
|
||||||
@ -779,12 +787,15 @@ bd_read(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest)
|
|||||||
/* GELI needs the offset relative to the partition start */
|
/* GELI needs the offset relative to the partition start */
|
||||||
p_off = alignlba - dskp.start;
|
p_off = alignlba - dskp.start;
|
||||||
|
|
||||||
err = geli_read(&dskp, p_off * BIOSDISK_SECSIZE, tmpbuf,
|
err = geli_read(&dskp, p_off * BD(dev).bd_sectorsize, tmpbuf,
|
||||||
alignblks * BIOSDISK_SECSIZE);
|
alignblks * BD(dev).bd_sectorsize);
|
||||||
if (err)
|
if (err)
|
||||||
return (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);
|
return (0);
|
||||||
}
|
}
|
||||||
#endif /* LOADER_GELI_SUPPORT */
|
#endif /* LOADER_GELI_SUPPORT */
|
||||||
@ -898,10 +909,10 @@ bios_read(void *vdev __unused, struct dsk *priv, off_t off, char *buf, size_t by
|
|||||||
dev.d_partition = priv->part;
|
dev.d_partition = priv->part;
|
||||||
dev.d_offset = priv->start;
|
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 */
|
/* GELI gives us the offset relative to the partition start */
|
||||||
off += dev.d_offset;
|
off += dev.d_offset;
|
||||||
bytes = bytes / BIOSDISK_SECSIZE;
|
bytes = bytes / BD(&dev).bd_sectorsize;
|
||||||
|
|
||||||
return (bd_io(&dev, off, bytes, buf, 0));
|
return (bd_io(&dev, off, bytes, buf, 0));
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
|
|||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
daddr_t lba, alignlba;
|
daddr_t lba, alignlba;
|
||||||
off_t alignoff, diff;
|
off_t diff;
|
||||||
unsigned int nb, alignnb;
|
unsigned int nb, alignnb;
|
||||||
struct dsk *dsk = (struct dsk *) priv;
|
struct dsk *dsk = (struct dsk *) priv;
|
||||||
|
|
||||||
@ -210,10 +210,11 @@ vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
|
|||||||
p = buf;
|
p = buf;
|
||||||
lba = off / DEV_BSIZE;
|
lba = off / DEV_BSIZE;
|
||||||
lba += dsk->start;
|
lba += dsk->start;
|
||||||
/* Align reads to 4k else 4k sector GELIs will not decrypt. */
|
/*
|
||||||
alignoff = off & ~ (off_t)(DEV_GELIBOOT_BSIZE - 1);
|
* Align reads to 4k else 4k sector GELIs will not decrypt.
|
||||||
/* Round LBA down to nearest multiple of DEV_GELIBOOT_BSIZE bytes. */
|
* Round LBA down to nearest multiple of DEV_GELIBOOT_BSIZE bytes.
|
||||||
alignlba = alignoff / DEV_BSIZE;
|
*/
|
||||||
|
alignlba = rounddown2(off, DEV_GELIBOOT_BSIZE) / DEV_BSIZE;
|
||||||
/*
|
/*
|
||||||
* The read must be aligned to DEV_GELIBOOT_BSIZE bytes relative to the
|
* 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.
|
* start of the GELI partition, not the start of the actual disk.
|
||||||
|
Loading…
Reference in New Issue
Block a user