Repository navigation
msc device: check READ10/WRITE10 length against the LUN block size #4399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -174,7 +174,22 @@ static uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) { | |
| TU_LOG_DRV(" Computed block size = 0. SCSI case 7 Hi < Di (READ10) or case 13 Ho < Do (WRIT10)\r\n"); | ||
| status = MSC_CSW_STATUS_PHASE_ERROR; | ||
| } else { | ||
| // nothing to do | ||
| // lba and offset passed to read10/write10 callbacks are in the LUN's block size, the transfer length | ||
| // must be exactly block_count of those blocks or offset runs past the end of the block | ||
| uint32_t lun_block_count = 0; | ||
| uint16_t lun_block_size = 0; | ||
| tud_msc_capacity_cb(cbw->lun, &lun_block_count, &lun_block_size); | ||
| uint32_t const lun_bytes = (uint32_t) block_count * lun_block_size; | ||
|
|
||
| if (cbw->total_bytes > lun_bytes) { | ||
| TU_LOG_DRV(" SCSI case 5 Hi > Di (READ10) or case 11 Ho > Do (WRITE10)\r\n"); | ||
| status = MSC_CSW_STATUS_FAILED; | ||
|
Comment on lines
+184
to
+186
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } else if (cbw->total_bytes < lun_bytes) { | ||
| TU_LOG_DRV(" SCSI case 7 Hi < Di (READ10) or case 13 Ho < Do (WRITE10)\r\n"); | ||
| status = MSC_CSW_STATUS_PHASE_ERROR; | ||
| } else { | ||
| // nothing to do | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -389,6 +389,62 @@ void test_msc_read10_block_size_over_16bit(void) | |
| tud_task(); | ||
| } | ||
|
|
||
| // The transfer length must be block count x the LUN's block size: 1024 bytes for one 512-byte block would reach | ||
| // tud_msc_write10_cb() with offset 512, writing past the last block of the disk | ||
| void test_msc_write10_length_over_lun_block_size(void) | ||
| { | ||
| uint32_t const total_bytes = 2 * DISK_BLOCK_SIZE; | ||
|
Comment on lines
+394
to
+396
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The added test covers only oversized WRITE10. It does not exercise the new shorter-length branch that returns Prompt To Fix With AIThis is a comment left during a code review.
Path: test/unit-test/test/device/msc/test_msc_device.c
Line: 394-396
Comment:
**New rejection paths lack tests**
The added test covers only oversized WRITE10. It does not exercise the new shorter-length branch that returns `MSC_CSW_STATUS_PHASE_ERROR`, or oversized READ10, which must stall the input endpoint and wait for the host to clear it before sending status. Add those cases and check the status, remaining byte count, and recovery. Otherwise the new read and short-transfer paths can regress without failing this test.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly. |
||
|
|
||
| msc_cbw_t cbw_write10 = | ||
| { | ||
| .signature = MSC_CBW_SIGNATURE, | ||
| .tag = 0xCAFECAFE, | ||
| .total_bytes = total_bytes, | ||
| .lun = 0, | ||
| .dir = 0, | ||
| .cmd_len = sizeof(scsi_write10_t) | ||
| }; | ||
|
|
||
| scsi_write10_t cmd_write10 = | ||
| { | ||
| .cmd_code = SCSI_CMD_WRITE_10, | ||
| .lba = tu_htonl(DISK_BLOCK_NUM - 1), | ||
| .block_count = tu_htons(1) | ||
| }; | ||
|
|
||
| memcpy(cbw_write10.command, &cmd_write10, cbw_write10.cmd_len); | ||
|
|
||
| desc_configuration = data_desc_configuration; | ||
| uint8_t const* desc_ep = tu_desc_next(tu_desc_next(desc_configuration)); | ||
|
|
||
| dcd_event_setup_received(rhport, (uint8_t*) &request_set_configuration, false); | ||
|
|
||
| dcd_edpt_open_ExpectAndReturn(rhport, (tusb_desc_endpoint_t const *) desc_ep, true); | ||
| dcd_edpt_open_ExpectAndReturn(rhport, (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep), true); | ||
|
|
||
| dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_OUT, NULL, sizeof(msc_cbw_t), false, true); | ||
| dcd_edpt_xfer_IgnoreArg_buffer(); | ||
| dcd_edpt_xfer_ReturnMemThruPtr_buffer( (uint8_t*) &cbw_write10, sizeof(msc_cbw_t)); | ||
|
|
||
| dcd_event_xfer_complete(rhport, EDPT_MSC_OUT, sizeof(msc_cbw_t), 0, true); | ||
|
|
||
| dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_IN, NULL, 0, false, true); | ||
|
|
||
| // case 11 (Ho > Do): no data, STALL Bulk-Out, then a failed CSW with full residue | ||
| msc_csw_t const csw = | ||
| { | ||
| .signature = MSC_CSW_SIGNATURE, | ||
| .tag = 0xCAFECAFE, | ||
| .data_residue = total_bytes, | ||
| .status = MSC_CSW_STATUS_FAILED | ||
| }; | ||
|
|
||
| dcd_edpt_stall_Expect(rhport, EDPT_MSC_OUT); | ||
| dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, EDPT_MSC_IN, (uint8_t*) &csw, sizeof(msc_csw_t), sizeof(msc_csw_t), false, true); | ||
|
|
||
| tud_task(); | ||
| } | ||
|
|
||
| //--------------------------------------------------------------------+ | ||
| // SystemView spans on the early returns | ||
| //--------------------------------------------------------------------+ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new call runs
tud_msc_capacity_cb()for every nonempty READ10/WRITE10 that passes the earlier checks, but its public comment inmsc_device.hstill lists only the two capacity commands. Update that comment to include READ10/WRITE10. Application authors reading the header would otherwise miss that every storage request now calls it, which matters if the callback does slow or state-changing work.Prompt To Fix With AI
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!