Don't ignore an OpenBSD GPT partition just because the GPT says
authorkrw <krw@openbsd.org>
Fri, 2 Sep 2022 14:18:47 +0000 (14:18 +0000)
committerkrw <krw@openbsd.org>
Fri, 2 Sep 2022 14:18:47 +0000 (14:18 +0000)
it extends beyond the edge of the disk the GPT currently
inhabits. We only care if enough of it is addressable that a
disklabel is accessible.

Brings GPT handling of 'OpenBSD partitions extending too far'
into line with the MBR handling of the same situation.

sys/kern/subr_disk.c

index 5f06c01..483cd7c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: subr_disk.c,v 1.257 2022/09/02 12:28:12 krw Exp $     */
+/*     $OpenBSD: subr_disk.c,v 1.258 2022/09/02 14:18:47 krw Exp $     */
 /*     $NetBSD: subr_disk.c,v 1.17 1996/03/16 23:17:08 christos Exp $  */
 
 /*
@@ -590,17 +590,16 @@ int
 spoofgpt(struct buf *bp, void (*strat)(struct buf *), const uint8_t *dosbb,
     struct disklabel *lp, daddr_t *partoffp)
 {
-       static const uint8_t     gpt_uuid_openbsd[] = GPT_UUID_OPENBSD;
        struct dos_partition     dp[NDOSPART];
        struct gpt_header        gh;
-       struct uuid              gptype, uuid_openbsd;
+       struct uuid              gptype;
        struct gpt_partition    *gp;
        struct partition        *pp;
-       uint64_t                 lbaend, lbastart;
+       uint64_t                 lbaend, lbastart, labelsec;
        uint64_t                 gpbytes, end, start;
-       daddr_t                  labeloff, partoff;
+       daddr_t                  partoff;
        unsigned int             i, n;
-       int                      error, obsdfound;
+       int                      error, fstype, obsdfound;
        uint32_t                 partnum;
        uint16_t                 sig;
 
@@ -634,7 +633,6 @@ spoofgpt(struct buf *bp, void (*strat)(struct buf *), const uint8_t *dosbb,
        partnum = letoh32(gh.gh_part_num);
 
        n = 'i' - 'a';  /* Start spoofing at 'i', a.k.a. 8. */
-       uuid_dec_be(gpt_uuid_openbsd, &uuid_openbsd);
 
        DL_SETBSTART(lp, lbastart);
        DL_SETBEND(lp, lbaend + 1);
@@ -642,33 +640,41 @@ spoofgpt(struct buf *bp, void (*strat)(struct buf *), const uint8_t *dosbb,
        obsdfound = 0;
        for (i = 0; i < partnum; i++) {
                start = letoh64(gp[i].gp_lba_start);
-               end = letoh64(gp[i].gp_lba_end) + 1;
-               if (start >= end || start < lbastart || end > lbaend + 1)
+               if (start > lbaend || start < lbastart)
+                       continue;
+
+               end = letoh64(gp[i].gp_lba_end);
+               if (start > end)
+                       continue;
+
+               uuid_dec_le(&gp[i].gp_type, &gptype);
+               fstype = gpt_get_fstype(&gptype);
+               if (obsdfound && fstype == FS_BSDFFS)
                        continue;
-               if (obsdfound == 0) {
-                       labeloff = partoff + DOS_LABELSECTOR;
-                       if (labeloff >= DL_SECTOBLK(lp, start) &&
-                           labeloff < DL_SECTOBLK(lp, end))
+
+               if (fstype == FS_BSDFFS) {
+                       obsdfound = 1;
+                       partoff = DL_SECTOBLK(lp, start);
+                       labelsec = DL_BLKTOSEC(lp, partoff + DOS_LABELSECTOR);
+                       if (labelsec > ((end < lbaend) ? end : lbaend))
                                partoff = -1;
+                       DL_SETBSTART(lp, start);
+                       DL_SETBEND(lp, end + 1);
+                       continue;
                }
 
-               uuid_dec_le(&gp[i].gp_type, &gptype);
-               if (memcmp(&gptype, &uuid_openbsd, sizeof(gptype)) == 0) {
-                       if (obsdfound == 0) {
-                               obsdfound = 1;
-                               partoff = DL_SECTOBLK(lp, start);
-                               labeloff = partoff + DOS_LABELSECTOR;
-                               if (labeloff >= DL_SECTOBLK(lp, end))
-                                       partoff = -1;
-                               DL_SETBSTART(lp, start);
-                               DL_SETBEND(lp, end);
-                       }
-               } else if (n < MAXPARTITIONS) {
+               if (partoff != -1) {
+                       labelsec = DL_BLKTOSEC(lp, partoff + DOS_LABELSECTOR);
+                       if (labelsec >= start && labelsec <= end)
+                               partoff = -1;
+               }
+
+               if (n < MAXPARTITIONS && end <= lbaend) {
                        pp = &lp->d_partitions[n];
                        n++;
-                       pp->p_fstype = gpt_get_fstype(&gptype);
+                       pp->p_fstype = fstype;
                        DL_SETPOFFSET(pp, start);
-                       DL_SETPSIZE(pp, end - start);
+                       DL_SETPSIZE(pp, end - start + 1);
                }
        }