DF-2281 / fix.diff
diff --git a/sys/bus/cam/scsi/scsi_sg.c b/sys/bus/cam/scsi/scsi_sg.c --- a/sys/bus/cam/scsi/scsi_sg.c +++ b/sys/bus/cam/scsi/scsi_sg.c @@ -694,8 +694,21 @@ /* * Now set up the data block. Again, the designers didn't bother * to make this reliable. + * + * buf_len is an int but uio_resid is size_t; reject anything that + * does not fit (or whose residual is otherwise absurd) instead of + * silently truncating into a negative value that kmalloc/M_ZERO + * would sign-extend into an impossible size. */ - buf_len = uio->uio_resid; + if (uio->uio_resid > INT_MAX) { + error = EINVAL; + goto out_ccb; + } + buf_len = (int)uio->uio_resid; + if (buf_len < 0) { + error = EINVAL; + goto out_ccb; + } if (buf_len != 0) { buf = kmalloc(buf_len, M_DEVBUF, M_WAITOK | M_ZERO); error = uiomove(buf, buf_len, uio); @@ -703,6 +716,10 @@ goto out_buf; dir = CAM_DIR_OUT; } else if (hdr->reply_len != 0) { + if (hdr->reply_len < 0 || hdr->reply_len > MAXPHYS) { + error = EINVAL; + goto out_ccb; + } buf = kmalloc(hdr->reply_len, M_DEVBUF, M_WAITOK | M_ZERO); buf_len = hdr->reply_len; dir = CAM_DIR_IN; |