Fix several potential buffer overrun conditions. These changes have been

tested both in the kernel and in userland.  Also, fix a couple of printf
warnings that show up when CAMDEBUG is defined.

Reviewed by:		imp
Partially submitted by:	imp
This commit is contained in:
ken 1998-10-15 19:08:58 +00:00
parent 999b2a26da
commit 3263ebd2ec
3 changed files with 116 additions and 29 deletions

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: cam_xpt.c,v 1.22 1998/10/14 22:51:51 ken Exp $ * $Id: cam_xpt.c,v 1.23 1998/10/15 17:46:18 ken Exp $
*/ */
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -2596,7 +2596,7 @@ xpt_action(union ccb *start_ccb)
scsi_op_desc(start_ccb->csio.cdb_io.cdb_bytes[0], scsi_op_desc(start_ccb->csio.cdb_io.cdb_bytes[0],
&path->device->inq_data), &path->device->inq_data),
scsi_cdb_string(start_ccb->csio.cdb_io.cdb_bytes, scsi_cdb_string(start_ccb->csio.cdb_io.cdb_bytes,
cdb_str))); cdb_str, sizeof(cdb_str))));
/* FALLTRHOUGH */ /* FALLTRHOUGH */
} }
case XPT_TARGET_IO: case XPT_TARGET_IO:
@ -3256,7 +3256,7 @@ xpt_run_dev_allocq(struct cam_eb *bus)
device = qinfo->device; device = qinfo->device;
CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE, CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
("running device 0x%x\n", device)); ("running device %p\n", device));
drvq = &device->drvq; drvq = &device->drvq;
@ -3350,7 +3350,7 @@ xpt_run_dev_sendq(struct cam_eb *bus)
} }
CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE, CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
("running device 0x%x\n", device)); ("running device %p\n", device));
work_ccb = cam_ccbq_peek_ccb(&device->ccbq, 0); work_ccb = cam_ccbq_peek_ccb(&device->ccbq, 0);
if (work_ccb == NULL) { if (work_ccb == NULL) {

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: scsi_all.c,v 1.4 1998/09/29 22:11:30 ken Exp $ * $Id: scsi_all.c,v 1.5 1998/10/02 21:00:54 ken Exp $
*/ */
#include <sys/param.h> #include <sys/param.h>
@ -1560,7 +1560,7 @@ scsi_error_action(int asc, int ascq, struct scsi_inquiry_data *inq_data)
} }
char * char *
scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string) scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string, size_t len)
{ {
u_int8_t cdb_len; u_int8_t cdb_len;
char holdstr[8]; char holdstr[8];
@ -1610,6 +1610,13 @@ scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string)
*cdb_string = '\0'; *cdb_string = '\0';
for (i = 0; i < cdb_len; i++) { for (i = 0; i < cdb_len; i++) {
sprintf(holdstr, "%x ", cdb_ptr[i]); sprintf(holdstr, "%x ", cdb_ptr[i]);
/*
* If we're about to exceed the length of the string,
* just return what we've already printed.
*/
if (strlen(holdstr) + strlen(cdb_string) > len)
break;
strcat(cdb_string, holdstr); strcat(cdb_string, holdstr);
} }
@ -1672,12 +1679,14 @@ scsi_sense_print(struct ccb_scsiio *csio)
printf("%s. CDB: %s\n", printf("%s. CDB: %s\n",
scsi_op_desc(csio->cdb_io.cdb_ptr[0], scsi_op_desc(csio->cdb_io.cdb_ptr[0],
&cgd.inq_data), &cgd.inq_data),
scsi_cdb_string(csio->cdb_io.cdb_ptr, cdb_str)); scsi_cdb_string(csio->cdb_io.cdb_ptr, cdb_str,
sizeof(cdb_str)));
} else { } else {
printf("%s. CDB: %s\n", printf("%s. CDB: %s\n",
scsi_op_desc(csio->cdb_io.cdb_bytes[0], scsi_op_desc(csio->cdb_io.cdb_bytes[0],
&cgd.inq_data), scsi_cdb_string( &cgd.inq_data), scsi_cdb_string(
csio->cdb_io.cdb_bytes, cdb_str)); csio->cdb_io.cdb_bytes, cdb_str,
sizeof(cdb_str)));
} }
} }
@ -1809,7 +1818,7 @@ scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
char path_str[64]; char path_str[64];
char tmpstr[2048]; char tmpstr[2048];
int tmpstrlen = 2048; int tmpstrlen = 2048;
int cur_len = 0, retlen; int cur_len = 0, tmplen = 0, retlen;
if ((device == NULL) || (csio == NULL) || (str == NULL)) if ((device == NULL) || (csio == NULL) || (str == NULL))
return(NULL); return(NULL);
@ -1836,23 +1845,34 @@ scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
retlen = snprintf(tmpstr, tmpstrlen, "%s", path_str); retlen = snprintf(tmpstr, tmpstrlen, "%s", path_str);
strncat(str, tmpstr, str_len - cur_len - 1); if ((tmplen = str_len - cur_len - 1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
cur_len += retlen; cur_len += retlen;
str[str_len - 1] = '\0';
if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) { if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) {
retlen = snprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n", retlen = snprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n",
scsi_op_desc(csio->cdb_io.cdb_ptr[0], scsi_op_desc(csio->cdb_io.cdb_ptr[0],
&device->inq_data), &device->inq_data),
scsi_cdb_string(csio->cdb_io.cdb_ptr, scsi_cdb_string(csio->cdb_io.cdb_ptr,
cdb_str)); cdb_str,
sizeof(cdb_str)));
} else { } else {
retlen = snprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n", retlen = snprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n",
scsi_op_desc(csio->cdb_io.cdb_bytes[0], scsi_op_desc(csio->cdb_io.cdb_bytes[0],
&device->inq_data), scsi_cdb_string( &device->inq_data), scsi_cdb_string(
(u_int8_t *)&csio->cdb_io.cdb_bytes, cdb_str)); csio->cdb_io.cdb_bytes, cdb_str,
sizeof(cdb_str)));
} }
strncat(str, tmpstr, str_len - cur_len - 1);
if ((tmplen = str_len - cur_len - 1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
cur_len += retlen; cur_len += retlen;
str[str_len - 1] = '\0';
} }
/* /*
@ -1886,8 +1906,13 @@ scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
retlen = snprintf(tmpstr, tmpstrlen, "%s", path_str); retlen = snprintf(tmpstr, tmpstrlen, "%s", path_str);
strncat(str, tmpstr, str_len - cur_len - 1);
if ((tmplen = str_len - cur_len - 1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
cur_len += retlen; cur_len += retlen;
str[str_len - 1] = '\0';
error_code = sense->error_code & SSD_ERRCODE; error_code = sense->error_code & SSD_ERRCODE;
sense_key = sense->flags & SSD_KEY; sense_key = sense->flags & SSD_KEY;
@ -1895,15 +1920,25 @@ scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
switch (error_code) { switch (error_code) {
case SSD_DEFERRED_ERROR: case SSD_DEFERRED_ERROR:
retlen = snprintf(tmpstr, tmpstrlen, "Deferred Error: "); retlen = snprintf(tmpstr, tmpstrlen, "Deferred Error: ");
strncat(str, tmpstr, str_len - cur_len - 1);
if ((tmplen = str_len - cur_len - 1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
cur_len += retlen; cur_len += retlen;
str[str_len - 1] = '\0';
/* FALLTHROUGH */ /* FALLTHROUGH */
case SSD_CURRENT_ERROR: case SSD_CURRENT_ERROR:
retlen = snprintf(tmpstr, tmpstrlen, "%s", retlen = snprintf(tmpstr, tmpstrlen, "%s",
scsi_sense_key_text[sense_key]); scsi_sense_key_text[sense_key]);
strncat(str, tmpstr, str_len - cur_len - 1);
if ((tmplen = str_len - cur_len - 1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
cur_len += retlen; cur_len += retlen;
str[str_len - 1] = '\0';
info = scsi_4btoul(sense->info); info = scsi_4btoul(sense->info);
@ -1919,8 +1954,13 @@ scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
retlen = snprintf(tmpstr, tmpstrlen, retlen = snprintf(tmpstr, tmpstrlen,
" req sz: %d (decimal)", " req sz: %d (decimal)",
info); info);
strncat(str, tmpstr, str_len - cur_len - 1);
if ((tmplen = str_len - cur_len - 1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
cur_len += retlen; cur_len += retlen;
str[str_len - 1] = '\0';
break; break;
default: default:
if (info) { if (info) {
@ -1936,15 +1976,24 @@ scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
" info:%x", " info:%x",
info); info);
} }
strncat(str, tmpstr,
str_len - cur_len - 1); if ((tmplen = str_len - cur_len -1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
cur_len += retlen; cur_len += retlen;
str[str_len - 1] = '\0';
} }
} }
} else if (info) { } else if (info) {
retlen = snprintf(tmpstr, tmpstrlen," info?:%x", info); retlen = snprintf(tmpstr, tmpstrlen," info?:%x", info);
strncat(str, tmpstr, str_len - cur_len - 1);
if ((tmplen = str_len - cur_len -1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
cur_len += retlen; cur_len += retlen;
str[str_len - 1] = '\0';
} }
if (sense->extra_len >= 4) { if (sense->extra_len >= 4) {
@ -1955,8 +2004,13 @@ scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
sense->cmd_spec_info[1], sense->cmd_spec_info[1],
sense->cmd_spec_info[2], sense->cmd_spec_info[2],
sense->cmd_spec_info[3]); sense->cmd_spec_info[3]);
strncat(str, tmpstr, str_len - cur_len - 1);
if ((tmplen = str_len - cur_len -1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
cur_len += retlen; cur_len += retlen;
str[str_len - 1] = '\0';
} }
} }
@ -1969,15 +2023,25 @@ scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
retlen = snprintf(tmpstr, tmpstrlen, retlen = snprintf(tmpstr, tmpstrlen,
" asc:%x,%x\n%s%s", asc, ascq, " asc:%x,%x\n%s%s", asc, ascq,
path_str, desc); path_str, desc);
strncat(str, tmpstr, str_len - cur_len - 1);
if ((tmplen = str_len - cur_len -1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
cur_len += retlen; cur_len += retlen;
str[str_len - 1] = '\0';
} }
if (sense->extra_len >= 7 && sense->fru) { if (sense->extra_len >= 7 && sense->fru) {
retlen = snprintf(tmpstr, tmpstrlen, retlen = snprintf(tmpstr, tmpstrlen,
" field replaceable unit: %x", " field replaceable unit: %x",
sense->fru); sense->fru);
strncat(str, tmpstr, str_len - cur_len - 1);
if ((tmplen = str_len - cur_len -1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
str[str_len - 1] = '\0';
cur_len += retlen; cur_len += retlen;
} }
@ -1986,7 +2050,12 @@ scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
retlen = snprintf(tmpstr, tmpstrlen, " sks:%x,%x", retlen = snprintf(tmpstr, tmpstrlen, " sks:%x,%x",
sense->sense_key_spec[0], sense->sense_key_spec[0],
scsi_2btoul(&sense->sense_key_spec[1])); scsi_2btoul(&sense->sense_key_spec[1]));
strncat(str, tmpstr, str_len - cur_len - 1);
if ((tmplen = str_len - cur_len -1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
str[str_len - 1] = '\0';
cur_len += retlen; cur_len += retlen;
} }
break; break;
@ -1994,21 +2063,38 @@ scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
default: default:
retlen = snprintf(tmpstr, tmpstrlen, "error code %d", retlen = snprintf(tmpstr, tmpstrlen, "error code %d",
sense->error_code & SSD_ERRCODE); sense->error_code & SSD_ERRCODE);
strncat(str, tmpstr, str_len - cur_len - 1);
if ((tmplen = str_len - cur_len -1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
cur_len += retlen; cur_len += retlen;
str[str_len - 1] = '\0';
if (sense->error_code & SSD_ERRCODE_VALID) { if (sense->error_code & SSD_ERRCODE_VALID) {
retlen = snprintf(tmpstr, tmpstrlen, retlen = snprintf(tmpstr, tmpstrlen,
" at block no. %d (decimal)", " at block no. %d (decimal)",
info = scsi_4btoul(sense->info)); info = scsi_4btoul(sense->info));
strncat(str, tmpstr, str_len - cur_len - 1);
if ((tmplen = str_len - cur_len -1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
cur_len += retlen; cur_len += retlen;
str[str_len - 1] = '\0';
} }
} }
retlen = snprintf(tmpstr, tmpstrlen, "\n"); retlen = snprintf(tmpstr, tmpstrlen, "\n");
strncat(str, tmpstr, str_len - cur_len - 1);
if ((tmplen = str_len - cur_len -1) < 0)
goto sst_bailout;
strncat(str, tmpstr, tmplen);
cur_len += retlen; cur_len += retlen;
str[str_len - 1] = '\0';
sst_bailout:
return(str); return(str);
} }

View File

@ -14,7 +14,7 @@
* *
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
* *
* $Id: scsi_all.h,v 1.3 1998/09/29 22:11:30 ken Exp $ * $Id: scsi_all.h,v 1.4 1998/10/02 05:25:49 ken Exp $
*/ */
/* /*
@ -709,7 +709,8 @@ int scsi_interpret_sense(struct cam_device *device,
const char * scsi_op_desc(u_int16_t opcode, const char * scsi_op_desc(u_int16_t opcode,
struct scsi_inquiry_data *inq_data); struct scsi_inquiry_data *inq_data);
char * scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string); char * scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string,
size_t len);
void scsi_print_inquiry(struct scsi_inquiry_data *inq_data); void scsi_print_inquiry(struct scsi_inquiry_data *inq_data);