The branch main has been updated by trasz:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=13aa56fcd59674cd65afc8e9d6b0c15d32bf9f81

commit 13aa56fcd59674cd65afc8e9d6b0c15d32bf9f81
Author:     Edward Tomasz Napierala <[email protected]>
AuthorDate: 2021-07-06 08:23:25 +0000
Commit:     Edward Tomasz Napierala <[email protected]>
CommitDate: 2021-07-06 08:27:22 +0000

    cam(4): preserve alloc_flags when copying CCBs
    
    Before UMA CCBs, all CCBs were of the same size, and could
    be trivially copied using bcopy(9).  Now we have to preserve
    alloc_flags, otherwise we might end up attempting to free
    stack-allocated CCB to UMA; we also need to take CCB size
    into account.
    
    This fixes kernel panic which would occur when trying to access
    a stopped (as in, SCSI START STOP, also "ctladm stop") SCSI device.
    
    Reported By:    Gary Jennejohn <[email protected]>
    Tested By:      Gary Jennejohn <[email protected]>
    Reviewed By:    imp
    Sponsored by:   NetApp, Inc.
    Sponsored by:   Klara, Inc.
    Differential Revision:  https://reviews.freebsd.org/D31054
---
 sys/cam/cam_periph.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 3e1a19936825..90ddf261cb12 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -1354,6 +1354,7 @@ camperiphdone(struct cam_periph *periph, union ccb 
*done_ccb)
        cam_status      status;
        struct scsi_start_stop_unit *scsi_cmd;
        int             error = 0, error_code, sense_key, asc, ascq;
+       u_int16_t       done_flags;
 
        scsi_cmd = (struct scsi_start_stop_unit *)
            &done_ccb->csio.cdb_io.cdb_bytes;
@@ -1422,8 +1423,21 @@ camperiphdone(struct cam_periph *periph, union ccb 
*done_ccb)
         * blocking by that also any new recovery attempts for this CCB,
         * and the result will be the final one returned to the CCB owher.
         */
+
+       /*
+        * Copy the CCB back, preserving the alloc_flags field.  Things
+        * will crash horribly if the CCBs are not of the same size.
+        */
        saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr;
-       bcopy(saved_ccb, done_ccb, sizeof(*done_ccb));
+       KASSERT(saved_ccb->ccb_h.func_code == XPT_SCSI_IO,
+           ("%s: saved_ccb func_code %#x != XPT_SCSI_IO",
+            __func__, saved_ccb->ccb_h.func_code));
+       KASSERT(done_ccb->ccb_h.func_code == XPT_SCSI_IO,
+           ("%s: done_ccb func_code %#x != XPT_SCSI_IO",
+            __func__, done_ccb->ccb_h.func_code));
+       done_flags = done_ccb->ccb_h.alloc_flags;
+       bcopy(saved_ccb, done_ccb, sizeof(struct ccb_scsiio));
+       done_ccb->ccb_h.alloc_flags = done_flags;
        xpt_free_ccb(saved_ccb);
        if (done_ccb->ccb_h.cbfcnp != camperiphdone)
                periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
@@ -1619,6 +1633,7 @@ camperiphscsisenseerror(union ccb *ccb, union ccb **orig,
        struct cam_periph *periph;
        union ccb *orig_ccb = ccb;
        int error, recoveryccb;
+       u_int16_t flags;
 
 #if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
        if (ccb->ccb_h.func_code == XPT_SCSI_IO && ccb->csio.bio != NULL)
@@ -1713,7 +1728,13 @@ camperiphscsisenseerror(union ccb *ccb, union ccb **orig,
                         * this freeze will be dropped as part of ERESTART.
                         */
                        ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
-                       bcopy(ccb, orig_ccb, sizeof(*orig_ccb));
+
+                       KASSERT(ccb->ccb_h.func_code == XPT_SCSI_IO,
+                           ("%s: ccb func_code %#x != XPT_SCSI_IO",
+                            __func__, ccb->ccb_h.func_code));
+                       flags = orig_ccb->ccb_h.alloc_flags;
+                       bcopy(ccb, orig_ccb, sizeof(struct ccb_scsiio));
+                       orig_ccb->ccb_h.alloc_flags = flags;
                }
 
                switch (err_action & SS_MASK) {
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "[email protected]"

Reply via email to