summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShidokht Yadegari <Shidokht.Yadegari@Sun.COM>2010-02-23 11:23:12 -0800
committerShidokht Yadegari <Shidokht.Yadegari@Sun.COM>2010-02-23 11:23:12 -0800
commitc31fac72a0572e58d0f06438a238d835dee8ffa7 (patch)
tree0c870c1ee5febab9dbfef0fa9138fcbf7c291de9
parent8932b28e77f9b7be3f2de9023636091c1fb9c06c (diff)
downloadillumos-joyent-c31fac72a0572e58d0f06438a238d835dee8ffa7.tar.gz
6660997 CMLB_LABEL should use ddi_driver_name(), not devi_binding_name
6768507 Array overrun in cmlb 6430011 division panic on a disk with reported capacity of less than 80k 6920774 issues with CMLB ioctl handling
-rw-r--r--usr/src/cmd/format/auto_sense.c8
-rw-r--r--usr/src/uts/common/io/cmlb.c60
-rw-r--r--usr/src/uts/common/sys/cmlb_impl.h4
3 files changed, 59 insertions, 13 deletions
diff --git a/usr/src/cmd/format/auto_sense.c b/usr/src/cmd/format/auto_sense.c
index 27fb82520d..f96dd6146d 100644
--- a/usr/src/cmd/format/auto_sense.c
+++ b/usr/src/cmd/format/auto_sense.c
@@ -2280,7 +2280,13 @@ compute_chs_values(diskaddr_t total_capacity, diskaddr_t usable_capacity,
{
/* Unlabeled SCSI floppy device */
- if (total_capacity <= 0x1000) {
+ if (total_capacity < 160) {
+ /* Less than 80K */
+ *nheadp = 1;
+ *pcylp = total_capacity;
+ *nsectp = 1;
+ return;
+ } else if (total_capacity <= 0x1000) {
*nheadp = 2;
*pcylp = 80;
*nsectp = total_capacity / (80 * 2);
diff --git a/usr/src/uts/common/io/cmlb.c b/usr/src/uts/common/io/cmlb.c
index 62025c7cdf..54ac010bce 100644
--- a/usr/src/uts/common/io/cmlb.c
+++ b/usr/src/uts/common/io/cmlb.c
@@ -247,6 +247,12 @@ static i_ddi_prop_dyn_t cmlb_prop_dyn[] = {
};
/*
+ * This implies an upper limit of 8192 GPT partitions
+ * in one transfer for GUID Partition Entry Array.
+ */
+len_t cmlb_tg_max_efi_xfer = 1024 * 1024;
+
+/*
* External kernel interfaces
*/
extern struct mod_ops mod_miscops;
@@ -359,9 +365,9 @@ static int cmlb_dkio_extpartinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
#endif
static void cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...);
-static void cmlb_v_log(dev_info_t *dev, char *label, uint_t level,
+static void cmlb_v_log(dev_info_t *dev, const char *label, uint_t level,
const char *fmt, va_list ap);
-static void cmlb_log(dev_info_t *dev, char *label, uint_t level,
+static void cmlb_log(dev_info_t *dev, const char *label, uint_t level,
const char *fmt, ...);
int
@@ -431,7 +437,7 @@ cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...)
* so that this module does not depend on scsi module.
*/
static void
-cmlb_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, ...)
+cmlb_log(dev_info_t *dev, const char *label, uint_t level, const char *fmt, ...)
{
va_list ap;
@@ -441,7 +447,7 @@ cmlb_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, ...)
}
static void
-cmlb_v_log(dev_info_t *dev, char *label, uint_t level, const char *fmt,
+cmlb_v_log(dev_info_t *dev, const char *label, uint_t level, const char *fmt,
va_list ap)
{
static char name[256];
@@ -1067,10 +1073,10 @@ cmlb_partinfo(cmlb_handle_t cmlbhandle, int part, diskaddr_t *nblocksp,
cl->cl_map[part].dkl_nblk;
if (tagp != NULL)
- if (cl->cl_cur_labeltype == CMLB_LABEL_EFI)
- *tagp = V_UNASSIGNED;
- else
- *tagp = cl->cl_vtoc.v_part[part].p_tag;
+ *tagp =
+ ((cl->cl_cur_labeltype == CMLB_LABEL_EFI) ||
+ (part >= NDKMAP)) ? V_UNASSIGNED :
+ cl->cl_vtoc.v_part[part].p_tag;
rval = 0;
}
@@ -1813,7 +1819,13 @@ cmlb_convert_geometry(struct cmlb_lun *cl, diskaddr_t capacity,
ASSERT(mutex_owned(CMLB_MUTEX(cl)));
/* Unlabeled SCSI floppy device */
- if (capacity <= 0x1000) {
+ if (capacity < 160) {
+ /* Less than 80K */
+ cl_g->dkg_nhead = 1;
+ cl_g->dkg_ncyl = capacity;
+ cl_g->dkg_nsect = 1;
+ return;
+ } else if (capacity <= 0x1000) {
cl_g->dkg_nhead = 2;
cl_g->dkg_ncyl = 80;
cl_g->dkg_nsect = capacity / (cl_g->dkg_nhead * cl_g->dkg_ncyl);
@@ -3300,7 +3312,12 @@ cmlb_build_default_label(struct cmlb_lun *cl, void *tg_cookie)
cl->cl_g.dkg_nsect = cl->cl_blockcount;
}
} else {
- if (cl->cl_blockcount <= 0x1000) {
+ if (cl->cl_blockcount < 160) {
+ /* Less than 80K */
+ cl->cl_g.dkg_nhead = 1;
+ cl->cl_g.dkg_ncyl = cl->cl_blockcount;
+ cl->cl_g.dkg_nsect = 1;
+ } else if (cl->cl_blockcount <= 0x1000) {
/* unlabeled SCSI floppy device */
cl->cl_g.dkg_nhead = 2;
cl->cl_g.dkg_ncyl = 80;
@@ -4081,6 +4098,12 @@ cmlb_dkio_get_extvtoc(struct cmlb_lun *cl, caddr_t arg, int flag,
return (rval);
}
+
+/*
+ * This routine implements the DKIOCGETEFI ioctl. This ioctl is currently
+ * used to read the GPT Partition Table Header (primary/backup), the GUID
+ * partition Entry Array (primary/backup), and the MBR.
+ */
static int
cmlb_dkio_get_efi(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie)
{
@@ -4094,6 +4117,9 @@ cmlb_dkio_get_efi(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie)
user_efi.dki_data = (void *)(uintptr_t)user_efi.dki_data_64;
+ if (user_efi.dki_length > cmlb_tg_max_efi_xfer)
+ return (EINVAL);
+
tgt_lba = user_efi.dki_lba;
mutex_enter(CMLB_MUTEX(cl));
@@ -4884,6 +4910,12 @@ exit:
return (rval);
}
+/*
+ * This routine implements the DKIOCSETEFI ioctl. This ioctl is currently
+ * used to write (or clear) the GPT Partition Table header (primary/backup)
+ * and GUID partition Entry Array (primary/backup). It is also used to write
+ * the Protective MBR.
+ */
static int
cmlb_dkio_set_efi(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag,
void *tg_cookie)
@@ -4902,6 +4934,9 @@ cmlb_dkio_set_efi(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag,
user_efi.dki_data = (void *)(uintptr_t)user_efi.dki_data_64;
+ if (user_efi.dki_length > cmlb_tg_max_efi_xfer)
+ return (EINVAL);
+
buffer = kmem_alloc(user_efi.dki_length, KM_SLEEP);
if (ddi_copyin(user_efi.dki_data, buffer, user_efi.dki_length, flag)) {
rval = EFAULT;
@@ -5203,6 +5238,11 @@ cmlb_setup_default_geometry(struct cmlb_lun *cl, void *tg_cookie)
cl->cl_g.dkg_ncyl = 1;
cl->cl_g.dkg_nhead = 1;
cl->cl_g.dkg_nsect = cl->cl_blockcount;
+ } else if (cl->cl_blockcount < 160) {
+ /* Less than 80K */
+ cl->cl_g.dkg_nhead = 1;
+ cl->cl_g.dkg_ncyl = cl->cl_blockcount;
+ cl->cl_g.dkg_nsect = 1;
} else if (cl->cl_blockcount <= 0x1000) {
/* Needed for unlabeled SCSI floppies. */
cl->cl_g.dkg_nhead = 2;
diff --git a/usr/src/uts/common/sys/cmlb_impl.h b/usr/src/uts/common/sys/cmlb_impl.h
index 1927123457..47ee3ab7bd 100644
--- a/usr/src/uts/common/sys/cmlb_impl.h
+++ b/usr/src/uts/common/sys/cmlb_impl.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -75,7 +75,7 @@ extern "C" {
#define CMLB_MUTEX(cl) (&((cl)->cl_mutex))
#define CMLB_DEVINFO(cl) ((cl)->cl_devi)
-#define CMLB_LABEL(cl) (DEVI(((cl)->cl_devi))->devi_binding_name)
+#define CMLB_LABEL(cl) (ddi_driver_name((cl->cl_devi)))
#define ISREMOVABLE(cl) (cl->cl_is_removable)