summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authorken <ken@FreeBSD.org>2017-06-26 15:23:12 +0000
committerken <ken@FreeBSD.org>2017-06-26 15:23:12 +0000
commit224b446d37054a07f45ee4aca27fd67b9f3910a8 (patch)
treea4707eb2d483ebb326151cc2ba1463a763f1adbe /sys/cam
parentcc0ed3af4b7429dde30a2b42632e6f7e260ec0fe (diff)
downloadFreeBSD-src-224b446d37054a07f45ee4aca27fd67b9f3910a8.zip
FreeBSD-src-224b446d37054a07f45ee4aca27fd67b9f3910a8.tar.gz
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
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/scsi/scsi_sa.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/sys/cam/scsi/scsi_sa.c b/sys/cam/scsi/scsi_sa.c
index 354ff13..83c670f 100644
--- a/sys/cam/scsi/scsi_sa.c
+++ b/sys/cam/scsi/scsi_sa.c
@@ -4464,7 +4464,18 @@ saextget(struct cdev *dev, struct cam_periph *periph, struct sbuf *sb,
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;
OpenPOWER on IntegriCloud