Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157633578
D5820.id14851.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D5820.id14851.diff
View Options
Index: sys/boot/geli/geliboot.h
===================================================================
--- sys/boot/geli/geliboot.h
+++ sys/boot/geli/geliboot.h
@@ -55,6 +55,9 @@
#ifndef DEV_BSIZE
#define DEV_BSIZE 512
#endif
+#ifndef DEV_4KSEC
+#define DEV_4KSEC 4096
+#endif
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
Index: sys/boot/geli/geliboot.c
===================================================================
--- sys/boot/geli/geliboot.c
+++ sys/boot/geli/geliboot.c
@@ -73,14 +73,18 @@
size_t bytes), struct dsk *dskp, daddr_t lastsector)
{
struct g_eli_metadata md;
- u_char buf[DEV_BSIZE];
+ u_char buf[DEV_BSIZE], rawbuf[DEV_4KSEC];
int error;
+ off_t alignbyte;
- error = read_func(NULL, dskp, (off_t) lastsector * DEV_BSIZE, &buf,
- (size_t) DEV_BSIZE);
+ alignbyte = (off_t)(lastsector * DEV_BSIZE) & ~ (off_t)(DEV_4KSEC - 1);
+ error = read_func(NULL, dskp, alignbyte, &rawbuf, (size_t) DEV_4KSEC);
if (error != 0) {
return (error);
}
+ /* Extract the last 512 bytes from the 4k sector */
+ memcpy(&buf, rawbuf + (DEV_4KSEC - DEV_BSIZE), DEV_BSIZE);
+
error = eli_metadata_decode(buf, &md);
if (error != 0) {
return (error);
@@ -229,35 +233,47 @@
u_char iv[G_ELI_IVKEYLEN];
u_char *pbuf;
int error;
- off_t os;
+ off_t dstoff;
uint64_t keyno;
- size_t n, nb;
+ size_t n, nsec, secsize;
struct g_eli_key gkey;
+ pbuf = buf;
SLIST_FOREACH_SAFE(geli_e, &geli_head, entries, geli_e_tmp) {
if (geli_same_device(geli_e, dskp) != 0) {
continue;
}
- nb = bytes / DEV_BSIZE;
- for (n = 0; n < nb; n++) {
- os = offset + (n * DEV_BSIZE);
- pbuf = buf + (n * DEV_BSIZE);
+ secsize = geli_e->sc.sc_sectorsize;
+ nsec = bytes / secsize;
+ if (nsec == 0) {
+ /* A read of less than the sector size has been
+ * requested. The caller provided destination buffer may
+ * not be big enough to boost the read to a full sector,
+ * so just attempt to decrypt the truncated sector
+ */
+ secsize = bytes;
+ nsec = 1;
+ }
+
+ for (n = 0, dstoff = offset; n < nsec; n++, dstoff += secsize) {
- g_eli_crypto_ivgen(&geli_e->sc, os, iv, G_ELI_IVKEYLEN);
+ g_eli_crypto_ivgen(&geli_e->sc, dstoff, iv, G_ELI_IVKEYLEN);
/* Get the key that corresponds to this offset */
- keyno = (os >> G_ELI_KEY_SHIFT) / DEV_BSIZE;
+ keyno = (dstoff >> G_ELI_KEY_SHIFT) / secsize;
g_eli_key_fill(&geli_e->sc, &gkey, keyno);
error = geliboot_crypt(geli_e->sc.sc_ealgo, 0, pbuf,
- DEV_BSIZE, gkey.gek_key, geli_e->sc.sc_ekeylen, iv);
+ secsize, gkey.gek_key,
+ geli_e->sc.sc_ekeylen, iv);
if (error != 0) {
bzero(&gkey, sizeof(gkey));
printf("Failed to decrypt in geli_read()!");
return (error);
}
+ pbuf += secsize;
}
bzero(&gkey, sizeof(gkey));
return (0);
Index: sys/boot/i386/libi386/biosdisk.c
===================================================================
--- sys/boot/i386/libi386/biosdisk.c
+++ sys/boot/i386/libi386/biosdisk.c
@@ -706,15 +706,29 @@
{
#ifdef LOADER_GELI_SUPPORT
struct dsk dskp;
- off_t p_off;
- int err, n;
+ off_t p_off, diff;
+ daddr_t alignlba;
+ int err, n, alignblks;
+ char *tmpbuf;
/* if we already know there is no GELI, skip the rest */
if (geli_status[dev->d_unit][dev->d_slice] != ISGELI_YES)
return (bd_io(dev, dblk, blks, dest, 0));
if (geli_status[dev->d_unit][dev->d_slice] == ISGELI_YES) {
- err = bd_io(dev, dblk, blks, dest, 0);
+ /* Align reads to 4k else 4k sector GELIs will not decrypt */
+ /* Round LBA down to nearest multiple of 4096 bytes */
+ alignlba = dblk & ~ (daddr_t)(8 - 1);
+ /* Round number of blocks up to nearest multiple of 4096 */
+ alignblks = blks + (dblk - alignlba) + (8 - 1) & ~ (int)(8 - 1);
+ diff = (dblk - alignlba) * BIOSDISK_SECSIZE;
+ /*
+ * Use a temporary buffer here because the buffer provided by
+ * the caller may be too small, and we don't want to overflow it
+ */
+ tmpbuf = alloca(alignblks * BIOSDISK_SECSIZE);
+
+ err = bd_io(dev, alignlba, alignblks, tmpbuf, 0);
if (err)
return (err);
@@ -726,13 +740,14 @@
dskp.start = dev->d_offset;
/* GELI needs the offset relative to the partition start */
- p_off = dblk - dskp.start;
+ p_off = alignlba - dskp.start;
- err = geli_read(&dskp, p_off * BIOSDISK_SECSIZE, dest,
- blks * BIOSDISK_SECSIZE);
+ err = geli_read(&dskp, p_off * BIOSDISK_SECSIZE, tmpbuf,
+ alignblks * BIOSDISK_SECSIZE);
if (err)
return (err);
+ bcopy(tmpbuf + diff, dest, blks * BIOSDISK_SECSIZE);
return (0);
}
#endif /* LOADER_GELI_SUPPORT */
Index: sys/boot/i386/zfsboot/zfsboot.c
===================================================================
--- sys/boot/i386/zfsboot/zfsboot.c
+++ sys/boot/i386/zfsboot/zfsboot.c
@@ -59,6 +59,8 @@
#define TYPE_MAXHARD TYPE_DA
#define TYPE_FD 2
+#define DEV_4KSEC 4096
+
extern uint32_t _end;
#ifdef GPT
@@ -198,8 +200,9 @@
vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
{
char *p;
- daddr_t lba;
- unsigned int nb;
+ daddr_t lba, alignlba;
+ off_t alignoff, diff;
+ unsigned int nb, alignnb;
struct dsk *dsk = (struct dsk *) priv;
if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1)))
@@ -208,24 +211,42 @@
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_4KSEC - 1);
+ /* Round LBA down to nearest multiple of 4096 bytes */
+ alignlba = alignoff / DEV_BSIZE;
+ /* The read must be 4k aligned to the GELI partition, not the disk */
+ alignlba += dsk->start;
+ diff = (lba - alignlba) * DEV_BSIZE;
+
while (bytes > 0) {
nb = bytes / DEV_BSIZE;
if (nb > READ_BUF_SIZE / DEV_BSIZE)
nb = READ_BUF_SIZE / DEV_BSIZE;
- if (drvread(dsk, dmadat->rdbuf, lba, nb))
+ /* Don't overflow the read buffer */
+ if (nb * DEV_BSIZE + diff > READ_BUF_SIZE)
+ nb -= diff / DEV_BSIZE;
+ /* Round number of blocks up to nearest multiple of 4096 */
+ alignnb = nb + (diff / DEV_BSIZE) + (DEV_4KSEC / DEV_BSIZE - 1)
+ & ~ (unsigned int)(DEV_4KSEC / DEV_BSIZE - 1);
+
+ if (drvread(dsk, dmadat->rdbuf, alignlba, alignnb))
return -1;
#ifdef LOADER_GELI_SUPPORT
/* decrypt */
if (is_geli(dsk) == 0) {
- if (geli_read(dsk, ((lba - dsk->start) * DEV_BSIZE),
- dmadat->rdbuf, nb * DEV_BSIZE))
- return (-1);
+ if (geli_read(dsk, ((alignlba - dsk->start) * DEV_BSIZE),
+ dmadat->rdbuf, alignnb * DEV_BSIZE))
+ return (-1);
}
#endif
- memcpy(p, dmadat->rdbuf, nb * DEV_BSIZE);
+ memcpy(p, dmadat->rdbuf + diff, nb * DEV_BSIZE);
p += nb * DEV_BSIZE;
lba += nb;
+ alignlba += alignnb;
bytes -= nb * DEV_BSIZE;
+ /* Don't need the leadingg offset after the first block */
+ diff = 0;
}
return 0;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, May 24, 2:37 PM (3 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33474626
Default Alt Text
D5820.id14851.diff (6 KB)
Attached To
Mode
D5820: Fix GELIBoot support if GELI sector size is > 512
Attached
Detach File
Event Timeline
Log In to Comment