Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 26 Jun 2017 15:23:12 +0000 (UTC)
From:      "Kenneth D. Merry" <ken@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r320361 - stable/10/sys/cam/scsi
Message-ID:  <201706261523.v5QFNCBZ068093@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ken
Date: Mon Jun 26 15:23:12 2017
New Revision: 320361
URL: https://svnweb.freebsd.org/changeset/base/320361

Log:
  MFC r320123:
  
    Fix a potential sleep while holding a mutex in the sa(4) driver.
  
    If the user issues a MTIOCEXTGET ioctl, and the tape drive in question has
    a serial number that is longer than 80 characters, we malloc a buffer in
    saextget() to hold the output of cam_strvis().
  
    Since a mutex is held in that codepath, doing a M_WAITOK malloc could lead
    to sleeping while holding a mutex.  Change it to a M_NOWAIT malloc and bail
    out if we fail to allocate the memory.  Devices with serial numbers longer
    than 80 bytes are very rare (I don't recall seeing one), so this
    should be a very unusual case to hit.  But it is a bug that should be fixed.
  
    sys/cam/scsi/scsi_sa.c:
    	In saextget(), if we need to malloc a buffer to hold the output of
    	cam_strvis(), don't wait for the memory.  Fail and return an error
    	if we can't allocate the memory immediately.
  
  PR:		kern/220094
  Submitted by:	Jia-Ju Bai <baijiaju1990@163.com>
  Sponsored by:	Spectra Logic

Modified:
  stable/10/sys/cam/scsi/scsi_sa.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/cam/scsi/scsi_sa.c
==============================================================================
--- stable/10/sys/cam/scsi/scsi_sa.c	Mon Jun 26 13:14:41 2017	(r320360)
+++ stable/10/sys/cam/scsi/scsi_sa.c	Mon Jun 26 15:23:12 2017	(r320361)
@@ -4464,7 +4464,18 @@ saextget(struct cdev *dev, struct cam_periph *periph, 
 		if (cgd.serial_num_len > sizeof(tmpstr)) {
 			ts2_len = cgd.serial_num_len + 1;
 			ts2_malloc = 1;
-			tmpstr2 = malloc(ts2_len, M_SCSISA, M_WAITOK | M_ZERO);
+			tmpstr2 = malloc(ts2_len, M_SCSISA, M_NOWAIT | M_ZERO);
+			/*
+			 * The 80 characters allocated on the stack above
+			 * will handle the vast majority of serial numbers.
+			 * If we run into one that is larger than that, and
+			 * we can't malloc the length without blocking,
+			 * bail out with an out of memory error.
+			 */
+			if (tmpstr2 == NULL) {
+				error = ENOMEM;
+				goto extget_bailout;
+			}
 		} else {
 			ts2_len = sizeof(tmpstr);
 			ts2_malloc = 0;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201706261523.v5QFNCBZ068093>