tech-toolchain archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

PR toolchain/42357 disklabel endian issues



Hi all,
I have submitted the above PR with a bunch of patches for fixing this problem. 
Some review would be nice. 

This adds a function called bswap_label() that byte swaps a label. The dkcksum 
function has been changed to take the number of partitions in the label as a 
parameter because it sometimes needs to checksum a byte swapped label. I could 
have changed dkcksum to check the label magic numbers and byte swap the 
npartitions field if necessary, but that would have introduced a lot of new 
dependencies to dkcksum, so I opted for the extra parameter.

I also replaced a couple of u_short with uint16_t because we are dealing with 
data types whose size is fixed externally. (u_short may be defined to have a 
fixed size, but there's no harm in saying what you mean.)

The patch defines a macro called BSWAP_LABEL that is overkill for this. I 
expect that whoever commits a fix leaves this bit out. I only saw it after I 
had filed the PR.

Cheers,
Lloyd

Index: sbin/apmlabel/apmlabel.c
===================================================================
RCS file: /vol/src/rsync-src/src/sbin/apmlabel/apmlabel.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 apmlabel.c
--- sbin/apmlabel/apmlabel.c    5 Mar 2007 23:06:53 -0000       1.1.1.1
+++ sbin/apmlabel/apmlabel.c    16 Jul 2009 22:34:15 -0000
@@ -87,7 +87,7 @@
        int one = 1;
 
        label.d_checksum = 0;
-       label.d_checksum = dkcksum(&label);
+       label.d_checksum = dkcksum(&label, label.d_npartitions);
        if (ioctl(sd, doraw ? DIOCWDINFO : DIOCSDINFO, &label) < 0) {
                perror("set label");
                exit(1);
Index: sbin/disklabel/Makefile
===================================================================
RCS file: /vol/src/rsync-src/src/sbin/disklabel/Makefile,v
retrieving revision 1.62
diff -u -r1.62 Makefile
--- sbin/disklabel/Makefile     14 Feb 2009 13:52:51 -0000      1.62
+++ sbin/disklabel/Makefile     9 Jul 2009 04:13:49 -0000
@@ -1,9 +1,12 @@
 #      $NetBSD: Makefile,v 1.62 2009/02/14 13:52:51 abs Exp $
 #      @(#)Makefile    8.2 (Berkeley) 3/17/94
 
+.include <bsd.endian.mk>
+
 PROG=  disklabel
 SRCS=  main.c dkcksum.c interact.c printlabel.c
 MAN=   disklabel.5 disklabel.8
+CPPFLAGS+= -DTARGET_ENDIANNESS=${TARGET_ENDIANNESS}
 .if (${HOSTPROG:U} == "")
 DPADD+= ${LIBUTIL}
 LDADD+= -lutil
Index: sbin/disklabel/dkcksum.c
===================================================================
RCS file: /vol/src/rsync-src/src/sbin/disklabel/dkcksum.c,v
retrieving revision 1.11
diff -u -r1.11 dkcksum.c
--- sbin/disklabel/dkcksum.c    12 Jun 2005 19:18:34 -0000      1.11
+++ sbin/disklabel/dkcksum.c    14 Jul 2009 21:42:21 -0000
@@ -50,15 +50,15 @@
 #endif /* HAVE_NBTOOL_CONFIG_H */
 #include "dkcksum.h"
 
-u_short
-dkcksum(struct disklabel *lp)
+uint16_t
+dkcksum(struct disklabel *lp, int npartitions)
 {
-       u_short *start, *end;
-       u_short  sum;
+       uint16_t        *start, *end;
+       uint16_t         sum;
 
        sum = 0;
-       start = (u_short *)lp;
-       end = (u_short *)&lp->d_partitions[lp->d_npartitions];
+       start = (uint16_t *)lp;
+       end = (uint16_t *)&lp->d_partitions[npartitions];
        while (start < end)
                sum ^= *start++;
        return (sum);
Index: sbin/disklabel/dkcksum.h
===================================================================
RCS file: /vol/src/rsync-src/src/sbin/disklabel/dkcksum.h,v
retrieving revision 1.3
diff -u -r1.3 dkcksum.h
--- sbin/disklabel/dkcksum.h    24 Dec 2000 05:59:11 -0000      1.3
+++ sbin/disklabel/dkcksum.h    14 Jul 2009 20:58:42 -0000
@@ -1,3 +1,3 @@
 /*     $NetBSD: dkcksum.h,v 1.3 2000/12/24 05:59:11 lukem Exp $        */
 
-u_short        dkcksum(struct disklabel *);
+uint16_t       dkcksum(struct disklabel *, int);
Index: sbin/disklabel/main.c
===================================================================
RCS file: /vol/src/rsync-src/src/sbin/disklabel/main.c,v
retrieving revision 1.20
diff -u -r1.20 main.c
--- sbin/disklabel/main.c       4 May 2009 18:09:04 -0000       1.20
+++ sbin/disklabel/main.c       17 Jul 2009 00:04:06 -0000
@@ -180,6 +180,13 @@
 #define GETNUM16(a, v) getulong(a, '\0', NULL, v, UINT16_MAX)
 #define GETNUM8(a, v)  getulong(a, '\0', NULL, v, UINT8_MAX)
 
+static void bswap_label (struct disklabel *);
+#if BYTE_ORDER != TARGET_ENDIANNESS
+#define BSWAP_LABEL(l) do { bswap_label(l); } while (0)
+#else
+#define BSWAP_LABEL(l)
+#endif
+
 static int set_writable_fd = -1;
 
 #if HAVE_NBTOOL_CONFIG_H
@@ -486,7 +493,7 @@
        lab.d_magic = DISKMAGIC;
        lab.d_magic2 = DISKMAGIC;
        lab.d_checksum = 0;
-       lab.d_checksum = dkcksum(&lab);
+       lab.d_checksum = dkcksum(&lab, lab.d_npartitions);
 
        if (rflag) {
                /* Write the label directly to the disk */
@@ -933,15 +940,12 @@
                        is_deleted = "deleted ";
                }
                if (lp->d_magic != DISKMAGIC) {
-                       /* XXX: Do something about byte-swapped labels ? */
                        if (lp->d_magic == DISKMAGIC_REV &&
                            lp->d_magic2 == DISKMAGIC_REV)
-                               warnx("ignoring %sbyteswapped label"
-                                   " at offset %u from sector %u",
-                                   is_deleted, offset, sector);
-                       continue;
+                               bswap_label (lp);
                }
-               if (lp->d_npartitions > MAXPARTITIONS || dkcksum(lp) != 0) {
+               if (lp->d_npartitions > MAXPARTITIONS ||
+                   dkcksum(lp, lp->d_npartitions) != 0) {
                        if (verbose > 0)
                                warnx("corrupt label found at offset %u in "
                                    "sector %u", offset, sector);
@@ -1034,6 +1038,7 @@
        }
 
        *disk_lp = lab;
+       BSWAP_LABEL (disk_lp);
        write_bootarea(f, label_sector);
        return 1;
 }
@@ -1895,3 +1900,64 @@
 
        return ret;
 }
+
+static void
+bswap_label (struct disklabel *l)
+{
+       uint16_t npartitions;
+       int i;
+
+       if (l->d_magic == DISKMAGIC && l->d_magic2 == DISKMAGIC)
+               npartitions = l->d_npartitions;
+       else if (l->d_magic == DISKMAGIC_REV && l->d_magic2 == DISKMAGIC_REV)
+               npartitions = bswap16 (l->d_npartitions);
+       else
+               return;
+
+       /* We need to make sure that we don't replace a bad checksum with a 
+        * good one, but we don't need to tell anyone because we are preserving
+        * the bad checksum for others to check.
+        */
+       if (dkcksum(l, npartitions) != 0)
+               return;
+
+       l->d_magic = bswap32 (l->d_magic);
+        l->d_type = bswap16 (l->d_type);
+        l->d_subtype = bswap16 (l->d_subtype);
+
+       l->d_secsize = bswap32 (l->d_secsize);
+        l->d_nsectors = bswap32 (l->d_nsectors);
+        l->d_ntracks = bswap32 (l->d_ntracks);
+        l->d_ncylinders = bswap32 (l->d_ncylinders);
+        l->d_secpercyl = bswap32 (l->d_secpercyl);
+        l->d_secperunit = bswap32 (l->d_secperunit);
+
+        l->d_sparespertrack = bswap16 (l->d_sparespertrack);
+        l->d_sparespercyl = bswap16 (l->d_sparespercyl);
+
+        l->d_acylinders = bswap32 (l->d_acylinders);
+        l->d_rpm = bswap16 (l->d_rpm);
+        l->d_interleave = bswap16 (l->d_interleave);
+        l->d_trackskew = bswap16 (l->d_trackskew);
+        l->d_cylskew = bswap16 (l->d_cylskew);
+        l->d_headswitch = bswap32 (l->d_headswitch);
+        l->d_trkseek = bswap32 (l->d_trkseek);
+        l->d_flags = bswap32 (l->d_flags);
+       for (i = 0; i < NDDATA; i++)
+               l->d_drivedata[i] = bswap32 (l->d_drivedata[i]);
+        l->d_magic2 = bswap32 (l->d_magic2);
+
+        l->d_npartitions = bswap16 (l->d_npartitions);
+        l->d_bbsize = bswap32 (l->d_bbsize);
+        l->d_sbsize = bswap32 (l->d_sbsize);
+       for (i = 0; i < npartitions; i++)
+       {
+               l->d_partitions[i].p_size = bswap32 (l->d_partitions[i].p_size);
+                l->d_partitions[i].p_offset = bswap32 
(l->d_partitions[i].p_offset);
+               l->d_partitions[i].p_fsize = bswap32 
(l->d_partitions[i].p_fsize);
+               l->d_partitions[i].p_cpg = bswap16 (l->d_partitions[i].p_cpg);
+       }
+
+        l->d_checksum = 0;
+       l->d_checksum = dkcksum (l, npartitions);
+}
Index: sbin/mbrlabel/mbrlabel.c
===================================================================
RCS file: /vol/src/rsync-src/src/sbin/mbrlabel/mbrlabel.c,v
retrieving revision 1.26
diff -u -r1.26 mbrlabel.c
--- sbin/mbrlabel/mbrlabel.c    28 Dec 2005 06:03:15 -0000      1.26
+++ sbin/mbrlabel/mbrlabel.c    17 Jul 2009 00:11:04 -0000
@@ -87,7 +87,7 @@
        int one = 1;
 
        label.d_checksum = 0;
-       label.d_checksum = dkcksum(&label);
+       label.d_checksum = dkcksum(&label, label.d_npartitions);
        if (ioctl(sd, doraw ? DIOCWDINFO : DIOCSDINFO, &label) < 0) {
                perror("set label");
                exit(1);
Index: sbin/svhlabel/svhlabel.c
===================================================================
RCS file: /vol/src/rsync-src/src/sbin/svhlabel/svhlabel.c,v
retrieving revision 1.5
diff -u -r1.5 svhlabel.c
--- sbin/svhlabel/svhlabel.c    6 Apr 2009 12:33:11 -0000       1.5
+++ sbin/svhlabel/svhlabel.c    17 Jul 2009 00:28:19 -0000
@@ -91,7 +91,7 @@
        int one = 1;
 
        label.d_checksum = 0;
-       label.d_checksum = dkcksum(&label);
+       label.d_checksum = dkcksum(&label, label.d_npartitions);
        if (ioctl(sd, doraw ? DIOCWDINFO : DIOCSDINFO, &label) < 0) {
                perror("set label");
                exit(1);
Index: usr.sbin/mscdlabel/main.c
===================================================================
RCS file: /vol/src/rsync-src/src/usr.sbin/mscdlabel/main.c,v
retrieving revision 1.4
diff -u -r1.4 main.c
--- usr.sbin/mscdlabel/main.c   25 May 2006 00:42:23 -0000      1.4
+++ usr.sbin/mscdlabel/main.c   17 Jul 2009 00:36:38 -0000
@@ -199,7 +199,7 @@
                        label.d_npartitions = j;
                strncpy(label.d_packname, "mscdlabel's", 16);
                label.d_checksum = 0;
-               label.d_checksum = dkcksum(&label);
+               label.d_checksum = dkcksum(&label, label.d_npartitions);
                res = ioctl(fd, DIOCSDINFO, &label);
                if (res < 0)
                        err(6, "DIOCSDINFO");



Home | Main Index | Thread Index | Old Index