Module Name:    src
Committed By:   kamil
Date:           Wed Jun 27 01:14:48 UTC 2018

Modified Files:
        src/sbin/disklabel: main.c

Log Message:
Avoid misaligned access in disklabel(8) in find_label()

Introduce a new helper variable tlp and use it for memory access.

Detected with MKSANITIZER/UBSan

A patch by <christos>


To generate a diff of this commit:
cvs rdiff -u -r1.49 -r1.50 src/sbin/disklabel/main.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sbin/disklabel/main.c
diff -u src/sbin/disklabel/main.c:1.49 src/sbin/disklabel/main.c:1.50
--- src/sbin/disklabel/main.c:1.49	Sun Apr  1 04:35:02 2018
+++ src/sbin/disklabel/main.c	Wed Jun 27 01:14:48 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.49 2018/04/01 04:35:02 ryo Exp $	*/
+/*	$NetBSD: main.c,v 1.50 2018/06/27 01:14:48 kamil Exp $	*/
 
 /*
  * Copyright (c) 2006 The NetBSD Foundation, Inc.
@@ -76,7 +76,7 @@ __COPYRIGHT("@(#) Copyright (c) 1987, 19
 static char sccsid[] = "@(#)disklabel.c	8.4 (Berkeley) 5/4/95";
 /* from static char sccsid[] = "@(#)disklabel.c	1.2 (Symmetric) 11/28/85"; */
 #else
-__RCSID("$NetBSD: main.c,v 1.49 2018/04/01 04:35:02 ryo Exp $");
+__RCSID("$NetBSD: main.c,v 1.50 2018/06/27 01:14:48 kamil Exp $");
 #endif
 #endif	/* not lint */
 
@@ -1189,7 +1189,7 @@ readlabel(int f)
 static struct disklabel *
 find_label(int f, u_int sector)
 {
-	struct disklabel *disk_lp, hlp;
+	struct disklabel *disk_lp, hlp, tlp;
 	int i;
 	off_t offset;
 	const char *is_deleted;
@@ -1209,30 +1209,31 @@ find_label(int f, u_int sector)
 	/* Check expected offset first */
 	for (offset = LABEL_OFFSET, i = -4;; offset = i += 4) {
 		is_deleted = "";
-		disk_lp = (void *)(bootarea + offset);
 		if (i == LABEL_OFFSET)
 			continue;
+		disk_lp = (void *)(bootarea + offset);
+		memcpy(&tlp, disk_lp, sizeof(tlp));
 		if ((char *)(disk_lp + 1) > bootarea + bootarea_len)
 			break;
-		if (disk_lp->d_magic2 != disk_lp->d_magic)
+		if (tlp.d_magic2 != tlp.d_magic)
 			continue;
-		if (read_all && (disk_lp->d_magic == DISKMAGIC_DELETED ||
-		    disk_lp->d_magic == DISKMAGIC_DELETED_REV)) {
-			disk_lp->d_magic ^= ~0u;
-			disk_lp->d_magic2 ^= ~0u;
+		if (read_all && (tlp.d_magic == DISKMAGIC_DELETED ||
+		    tlp.d_magic == DISKMAGIC_DELETED_REV)) {
+			tlp.d_magic ^= ~0u;
+			tlp.d_magic2 ^= ~0u;
 			is_deleted = "deleted ";
 		}
-		if (target32toh(disk_lp->d_magic) != DISKMAGIC) {
+		if (target32toh(tlp.d_magic) != DISKMAGIC) {
 			/* XXX: Do something about byte-swapped labels ? */
-			if (target32toh(disk_lp->d_magic) == DISKMAGIC_REV &&
-			    target32toh(disk_lp->d_magic2) == DISKMAGIC_REV)
+			if (target32toh(tlp.d_magic) == DISKMAGIC_REV &&
+			    target32toh(tlp.d_magic2) == DISKMAGIC_REV)
 				warnx("ignoring %sbyteswapped label"
 				    " at offset %jd from sector %u",
 				    is_deleted, (intmax_t)offset, sector);
 			continue;
 		}
-		if (target16toh(disk_lp->d_npartitions) > maxpartitions ||
-		    dkcksum_target(disk_lp) != 0) {
+		if (target16toh(tlp.d_npartitions) > maxpartitions ||
+		    dkcksum_target(&tlp) != 0) {
 			if (verbose > 0)
 				warnx("corrupt label found at offset %jd in "
 				    "sector %u", (intmax_t)offset, sector);
@@ -1246,7 +1247,7 @@ find_label(int f, u_int sector)
 
 		/* To print all the labels we have to do it here */
 		/* XXX: maybe we should compare them? */
-		targettohlabel(&hlp, disk_lp);
+		targettohlabel(&hlp, &tlp);
 		printf("# %ssector %u offset %jd bytes\n",
 		    is_deleted, sector, (intmax_t)offset);
 		if (tflag)
@@ -1256,7 +1257,8 @@ find_label(int f, u_int sector)
 			showpartitions(stdout, &hlp, Cflag);
 		}
 		checklabel(&hlp);
-		htotargetlabel(disk_lp, &hlp);
+		htotargetlabel(&tlp, &hlp);
+		memcpy(disk_lp, &tlp, sizeof(tlp));
 		/* Remember we've found a label */
 		read_all = 2;
 	}

Reply via email to