MODE SENSE: Fixed wrong ALLOCATION LENGTH handling (#617)

* Log PCF

* Code cleanup

* Logging update

* Updated error handling

* Updated setting of MODE SENSE return data size

* Added comments

* Removed useless assertions

* Updated logging

* Comment update

* Updated logging

* Formatting update

* Comment update
This commit is contained in:
Uwe Seimet 2022-01-20 16:04:59 +01:00 committed by GitHub
parent b7db82ab71
commit 7f362c9308
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -461,8 +461,6 @@ void Disk::ModeSense6(SASIDEV *controller)
{ {
ctrl->length = ModeSense6(ctrl->cmd, ctrl->buffer); ctrl->length = ModeSense6(ctrl->cmd, ctrl->buffer);
if (ctrl->length <= 0) { if (ctrl->length <= 0) {
LOGTRACE("%s Unsupported mode page $%02X",__PRETTY_FUNCTION__, (unsigned int)ctrl->cmd[2]);
controller->Error(); controller->Error();
return; return;
} }
@ -474,8 +472,6 @@ void Disk::ModeSense10(SASIDEV *controller)
{ {
ctrl->length = ModeSense10(ctrl->cmd, ctrl->buffer); ctrl->length = ModeSense10(ctrl->cmd, ctrl->buffer);
if (ctrl->length <= 0) { if (ctrl->length <= 0) {
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, (unsigned int)ctrl->cmd[2]);
controller->Error(); controller->Error();
return; return;
} }
@ -681,7 +677,6 @@ int Disk::ModeSense6(const DWORD *cdb, BYTE *buf)
{ {
// Get length, clear buffer // Get length, clear buffer
int length = (int)cdb[4]; int length = (int)cdb[4];
ASSERT((length >= 0) && (length < 0x100));
memset(buf, 0, length); memset(buf, 0, length);
// Get changeable flag // Get changeable flag
@ -691,12 +686,15 @@ int Disk::ModeSense6(const DWORD *cdb, BYTE *buf)
int page = cdb[2] & 0x3f; int page = cdb[2] & 0x3f;
bool valid = page == 0x00; bool valid = page == 0x00;
LOGTRACE("%s Requesting mode page $%02X", __PRETTY_FUNCTION__, page);
// Basic information // Basic information
int size = 4; int size = 4;
// MEDIUM TYPE // MEDIUM TYPE
if (IsMo()) { if (IsMo()) {
buf[1] = 0x03; // optical reversible or erasable // Optical reversible or erasable
buf[1] = 0x03;
} }
// DEVICE SPECIFIC PARAMETER // DEVICE SPECIFIC PARAMETER
@ -704,7 +702,7 @@ int Disk::ModeSense6(const DWORD *cdb, BYTE *buf)
buf[2] = 0x80; buf[2] = 0x80;
} }
// add block descriptor if DBD is 0 // Add block descriptor if DBD is 0
if ((cdb[1] & 0x08) == 0) { if ((cdb[1] & 0x08) == 0) {
// Mode parameter header, block descriptor length // Mode parameter header, block descriptor length
buf[3] = 0x08; buf[3] = 0x08;
@ -726,53 +724,52 @@ int Disk::ModeSense6(const DWORD *cdb, BYTE *buf)
buf[11] = disk_size; buf[11] = disk_size;
} }
// size
size = 12; size = 12;
} }
// Page code 1(read-write error recovery) // Page code 1 (read-write error recovery)
if ((page == 0x01) || (page == 0x3f)) { if (page == 0x01 || page == 0x3f) {
size += AddErrorPage(change, &buf[size]); size += AddErrorPage(change, &buf[size]);
valid = true; valid = true;
} }
// Page code 3(format device) // Page code 3 (format device)
if ((page == 0x03) || (page == 0x3f)) { if (page == 0x03 || page == 0x3f) {
size += AddFormatPage(change, &buf[size]); size += AddFormatPage(change, &buf[size]);
valid = true; valid = true;
} }
// Page code 4(drive parameter) // Page code 4 (drive parameter)
if ((page == 0x04) || (page == 0x3f)) { if (page == 0x04 || page == 0x3f) {
size += AddDrivePage(change, &buf[size]); size += AddDrivePage(change, &buf[size]);
valid = true; valid = true;
} }
// Page code 6(optical) // Page code 6 (optical)
if (IsMo()) { if (IsMo()) {
if ((page == 0x06) || (page == 0x3f)) { if (page == 0x06 || page == 0x3f) {
size += AddOptionPage(change, &buf[size]); size += AddOptionPage(change, &buf[size]);
valid = true; valid = true;
} }
} }
// Page code 8(caching) // Page code 8 (caching)
if ((page == 0x08) || (page == 0x3f)) { if (page == 0x08 || page == 0x3f) {
size += AddCachePage(change, &buf[size]); size += AddCachePage(change, &buf[size]);
valid = true; valid = true;
} }
// Page code 13(CD-ROM) // Page code 13 (CD-ROM)
if (IsCdRom()) { if (IsCdRom()) {
if ((page == 0x0d) || (page == 0x3f)) { if (page == 0x0d || page == 0x3f) {
size += AddCDROMPage(change, &buf[size]); size += AddCDROMPage(change, &buf[size]);
valid = true; valid = true;
} }
} }
// Page code 14(CD-DA) // Page code 14 (CD-DA)
if (IsCdRom()) { if (IsCdRom()) {
if ((page == 0x0e) || (page == 0x3f)) { if (page == 0x0e || page == 0x3f) {
size += AddCDDAPage(change, &buf[size]); size += AddCDDAPage(change, &buf[size]);
valid = true; valid = true;
} }
@ -785,23 +782,22 @@ int Disk::ModeSense6(const DWORD *cdb, BYTE *buf)
valid = true; valid = true;
} }
// final setting of mode data length
buf[0] = size - 1;
// Unsupported page
if (!valid) { if (!valid) {
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, page);
SetStatusCode(STATUS_INVALIDCDB); SetStatusCode(STATUS_INVALIDCDB);
return 0; return 0;
} }
//check if size of data is more than size requested.
if (size > length) {
SetStatusCode(STATUS_INVALIDCDB);
return 0;
}
//Set length returned to actual size of data
length = size;
return length; // Do not return more than ALLOCATION LENGTH bytes
if (size > length) {
LOGTRACE("%s %d bytes available, %d bytes requested", __PRETTY_FUNCTION__, size, length);
size = length;
}
// Final setting of mode data length
buf[0] = size;
return size;
} }
int Disk::ModeSense10(const DWORD *cdb, BYTE *buf) int Disk::ModeSense10(const DWORD *cdb, BYTE *buf)
@ -813,7 +809,6 @@ int Disk::ModeSense10(const DWORD *cdb, BYTE *buf)
if (length > 0x800) { if (length > 0x800) {
length = 0x800; length = 0x800;
} }
ASSERT((length >= 0) && (length < 0x800));
memset(buf, 0, length); memset(buf, 0, length);
// Get changeable flag // Get changeable flag
@ -823,12 +818,15 @@ int Disk::ModeSense10(const DWORD *cdb, BYTE *buf)
int page = cdb[2] & 0x3f; int page = cdb[2] & 0x3f;
bool valid = page == 0x00; bool valid = page == 0x00;
LOGTRACE("%s Requesting mode page $%02X", __PRETTY_FUNCTION__, page);
// Basic Information // Basic Information
int size = 8; int size = 8;
// MEDIUM TYPE // MEDIUM TYPE
if (IsMo()) { if (IsMo()) {
buf[2] = 0x03; // optical reversible or erasable // Optical reversible or erasable
buf[2] = 0x03;
} }
// DEVICE SPECIFIC PARAMETER // DEVICE SPECIFIC PARAMETER
@ -836,7 +834,7 @@ int Disk::ModeSense10(const DWORD *cdb, BYTE *buf)
buf[3] = 0x80; buf[3] = 0x80;
} }
// add block descriptor if DBD is 0 // Add block descriptor if DBD is 0
if ((cdb[1] & 0x08) == 0) { if ((cdb[1] & 0x08) == 0) {
// Only if ready // Only if ready
if (IsReady()) { if (IsReady()) {
@ -889,49 +887,49 @@ int Disk::ModeSense10(const DWORD *cdb, BYTE *buf)
} }
} }
// Page code 1(read-write error recovery) // Page code 1 (read-write error recovery)
if ((page == 0x01) || (page == 0x3f)) { if (page == 0x01 || page == 0x3f) {
size += AddErrorPage(change, &buf[size]); size += AddErrorPage(change, &buf[size]);
valid = true; valid = true;
} }
// Page code 3(format device) // Page code 3 (format device)
if ((page == 0x03) || (page == 0x3f)) { if (page == 0x03 || page == 0x3f) {
size += AddFormatPage(change, &buf[size]); size += AddFormatPage(change, &buf[size]);
valid = true; valid = true;
} }
// Page code 4(drive parameter) // Page code 4 (drive parameter)
if ((page == 0x04) || (page == 0x3f)) { if (page == 0x04 || page == 0x3f) {
size += AddDrivePage(change, &buf[size]); size += AddDrivePage(change, &buf[size]);
valid = true; valid = true;
} }
// Page code 6(optical) // Page code 6 (optical)
if (IsMo()) { if (IsMo()) {
if ((page == 0x06) || (page == 0x3f)) { if (page == 0x06 || page == 0x3f) {
size += AddOptionPage(change, &buf[size]); size += AddOptionPage(change, &buf[size]);
valid = true; valid = true;
} }
} }
// Page code 8(caching) // Page code 8 (caching)
if ((page == 0x08) || (page == 0x3f)) { if (page == 0x08 || page == 0x3f) {
size += AddCachePage(change, &buf[size]); size += AddCachePage(change, &buf[size]);
valid = true; valid = true;
} }
// Page code 13(CD-ROM) // Page code 13 (CD-ROM)
if (IsCdRom()) { if (IsCdRom()) {
if ((page == 0x0d) || (page == 0x3f)) { if (page == 0x0d || page == 0x3f) {
size += AddCDROMPage(change, &buf[size]); size += AddCDROMPage(change, &buf[size]);
valid = true; valid = true;
} }
} }
// Page code 14(CD-DA) // Page code 14 (CD-DA)
if (IsCdRom()) { if (IsCdRom()) {
if ((page == 0x0e) || (page == 0x3f)) { if (page == 0x0e || page == 0x3f) {
size += AddCDDAPage(change, &buf[size]); size += AddCDDAPage(change, &buf[size]);
valid = true; valid = true;
} }
@ -944,24 +942,23 @@ int Disk::ModeSense10(const DWORD *cdb, BYTE *buf)
valid = true; valid = true;
} }
// final setting of mode data length
buf[0] = (size - 2) >> 8;
buf[1] = size - 2;
// Unsupported page
if (!valid) { if (!valid) {
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, page);
SetStatusCode(STATUS_INVALIDCDB); SetStatusCode(STATUS_INVALIDCDB);
return 0; return 0;
} }
//check if size of data is more than size requested.
if (size > length) {
SetStatusCode(STATUS_INVALIDCDB);
return 0;
}
//Set length returned to actual size of data
length = size;
return length; // Do not return more than ALLOCATION LENGTH bytes
if (size > length) {
LOGTRACE("%s %d bytes available, %d bytes requested", __PRETTY_FUNCTION__, size, length);
size = length;
}
// Final setting of mode data length
buf[0] = size >> 8;
buf[1] = size;
return size;
} }
int Disk::AddErrorPage(bool change, BYTE *buf) int Disk::AddErrorPage(bool change, BYTE *buf)