changeset 21426:1ac65b648ab2

10939 libdiskstatus trusts disk mode sense data to its death Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Rob Johnston <rob.johnston@joyent.com> Reviewed by: Toomas Soome <tsoome@me.com> Reviewed by: Gergő Doma <domag02@gmail.com> Reviewed by: Andy Fiddaman <andy@omniosce.org> Approved by: Dan McDonald <danmcd@joyent.com>
author Robert Mustacchi <rm@joyent.com>
date Tue, 29 Jan 2019 23:21:24 +0000
parents 2520e61c1c15
children dfcb8f75275b
files usr/src/lib/fm/libdiskstatus/common/ds_scsi_uscsi.c
diffstat 1 files changed, 22 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/fm/libdiskstatus/common/ds_scsi_uscsi.c	Mon Jun 03 20:16:08 2019 -0700
+++ b/usr/src/lib/fm/libdiskstatus/common/ds_scsi_uscsi.c	Tue Jan 29 23:21:24 2019 +0000
@@ -22,10 +22,9 @@
 /*
  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright (c) 2019, Joyent, Inc.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * This file contains routines for sending and receiving SCSI commands.  The
  * higher level logic is contained in ds_scsi.c.
@@ -99,7 +98,7 @@
 };
 
 static slist_t sensekey_strings[] = {
-	{ "No sense error", 	KEY_NO_SENSE		},
+	{ "No sense error",	KEY_NO_SENSE		},
 	{ "Recoverable error",	KEY_RECOVERABLE_ERROR	},
 	{ "Not ready error",	KEY_NOT_READY		},
 	{ "Medium error",	KEY_MEDIUM_ERROR	},
@@ -1244,6 +1243,19 @@
 	 */
 	hdr = (struct mode_header *)mode_sense_buf;
 	(void) memset((caddr_t)header, 0, sizeof (struct scsi_ms_header));
+
+	/*
+	 * Check to see if we have a valid header length. We've occasionally
+	 * seen hardware return zero here, even though they filled in the media
+	 * type.
+	 */
+	if (hdr->length == 0) {
+		dprintf("\nMode sense page 0x%x: has header length for zero\n",
+		    page_code);
+		ddump("Mode sense:", mode_sense_buf, nbytes);
+		return (-1);
+	}
+
 	if (hdr->bdesc_length != sizeof (struct block_descriptor) &&
 	    hdr->bdesc_length != 0) {
 		dprintf("\nMode sense page 0x%x: block descriptor "
@@ -1259,6 +1271,13 @@
 	if (page_code == MODEPAGE_ALLPAGES) {
 		/* special case */
 
+		if ((hdr->length + sizeof (header->ms_header.length)) <
+		    (MODE_HEADER_LENGTH + hdr->bdesc_length)) {
+			dprintf("\nHeader length would spiral into a "
+			    "negative bcopy\n");
+			return (-1);
+		}
+
 		(void) memcpy(page_data, (caddr_t)pg,
 		    (hdr->length + sizeof (header->ms_header.length)) -
 		    (MODE_HEADER_LENGTH + hdr->bdesc_length));