summaryrefslogtreecommitdiffstats
path: root/sbin/camcontrol/fwdownload.c
diff options
context:
space:
mode:
authortruckman <truckman@FreeBSD.org>2016-05-24 00:57:11 +0000
committertruckman <truckman@FreeBSD.org>2016-05-24 00:57:11 +0000
commita4774d8f19b89abf2a239ea88471c6a6fbdfff9b (patch)
tree46aa22f07e1f507182e38a44b6dd148c8cda0479 /sbin/camcontrol/fwdownload.c
parent9ae9e7f9e06dc896592419dd2eb12935a3422395 (diff)
downloadFreeBSD-src-a4774d8f19b89abf2a239ea88471c6a6fbdfff9b.zip
FreeBSD-src-a4774d8f19b89abf2a239ea88471c6a6fbdfff9b.tar.gz
Fix multiple Coverity Out-of-bounds access false postive issues in CAM
The currently used idiom for clearing the part of a ccb after its header generates one or two Coverity errors for each time it is used. All instances generate an Out-of-bounds access (ARRAY_VS_SINGLETON) error because of the treatment of the header as a two element array, with a pointer to the non-existent second element being passed as the starting address to bzero(). Some instances also alsp generate Out-of-bounds access (OVERRUN) errors, probably because the space being cleared is larger than the sizeofstruct ccb_hdr). In addition, this idiom is difficult for humans to understand and it is error prone. The user has to chose the proper struct ccb_* type (which does not appear in the surrounding code) for the sizeof() in the length calculation. I found several instances where the length was incorrect, which could cause either an actual out of bounds write, or incompletely clear the ccb. A better way is to write the code to clear the ccb itself starting at sizeof(ccb_hdr) bytes from the start of the ccb, and calculate the length based on the specific type of struct ccb_* being cleared as specified by the union ccb member being used. The latter can normally be seen in the nearby code. This is friendlier for Coverity and other static analysis tools because they will see that the intent is to clear the trailing part of the ccb. Wrap all of the boilerplate code in a convenient macro that only requires a pointer to the desired union ccb member (or a pointer to the union ccb itself) as an argument. Reported by: Coverity CID: 1007578, 1008684, 1009724, 1009773, 1011304, 1011306 CID: 1011307, 1011308, 1011309, 1011310, 1011311, 1011312 CID: 1011313, 1011314, 1011315, 1011316, 1011317, 1011318 CID: 1011319, 1011320, 1011321, 1011322, 1011324, 1011325 CID: 1011326, 1011327, 1011328, 1011329, 1011330, 1011374 CID: 1011390, 1011391, 1011392, 1011393, 1011394, 1011395 CID: 1011396, 1011397, 1011398, 1011399, 1011400, 1011401 CID: 1011402, 1011403, 1011404, 1011405, 1011406, 1011408 CID: 1011409, 1011410, 1011411, 1011412, 1011413, 1011414 CID: 1017461, 1018387, 1086860, 1086874, 1194257, 1229897 CID: 1229968, 1306229, 1306234, 1331282, 1331283, 1331294 CID: 1331295, 1331535, 1331536, 1331539, 1331540, 1341623 CID: 1341624, 1341637, 1341638, 1355264, 1355324 Reviewed by: scottl, ken, delphij, imp MFH: 1 month Differential Revision: https://reviews.freebsd.org/D6496
Diffstat (limited to 'sbin/camcontrol/fwdownload.c')
-rw-r--r--sbin/camcontrol/fwdownload.c12
1 files changed, 4 insertions, 8 deletions
diff --git a/sbin/camcontrol/fwdownload.c b/sbin/camcontrol/fwdownload.c
index 0a678af..176d8f9 100644
--- a/sbin/camcontrol/fwdownload.c
+++ b/sbin/camcontrol/fwdownload.c
@@ -459,8 +459,7 @@ fw_validate_ibm(struct cam_device *dev, int retry_count, int timeout, int fd,
}
/* cam_getccb cleans up the header, caller has to zero the payload */
- bzero(&(&ccb->ccb_h)[1],
- sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
+ CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
bzero(&vpd_page, sizeof(vpd_page));
@@ -666,8 +665,7 @@ fw_check_device_ready(struct cam_device *dev, camcontrol_devtype devtype,
goto bailout;
}
- bzero(&(&ccb->ccb_h)[1],
- sizeof(union ccb) - sizeof(struct ccb_hdr));
+ CCB_CLEAR_ALL_EXCEPT_HDR(ccb);
if (devtype != CC_DT_SCSI) {
dxfer_len = sizeof(struct ata_params);
@@ -798,8 +796,7 @@ fw_download_img(struct cam_device *cam_dev, struct fw_vendor *vp,
goto bailout;
}
- bzero(&(&ccb->ccb_h)[1],
- sizeof(union ccb) - sizeof(struct ccb_hdr));
+ CCB_CLEAR_ALL_EXCEPT_HDR(ccb);
max_pkt_size = vp->max_pkt_size;
if (max_pkt_size == 0)
@@ -830,8 +827,7 @@ fw_download_img(struct cam_device *cam_dev, struct fw_vendor *vp,
vp->cdb_byte2;
cdb.buffer_id = vp->inc_cdb_buffer_id ? pkt_count : 0;
/* Zero out payload of ccb union after ccb header. */
- bzero(&(&ccb->ccb_h)[1],
- sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
+ CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
/*
* Copy previously constructed cdb into ccb_scsiio
* struct.
OpenPOWER on IntegriCloud