Fix: Crash on reading domain header from Control message

The application would crash if there was a control request from a domain message. As it would still try to read the domain header in the message.
This commit is contained in:
◱ PixelyIon
2019-11-15 00:36:38 +05:30
committed by ◱ PixelyIon
parent c005d7df74
commit b3517357e1
5 changed files with 88 additions and 87 deletions

View File

@ -9,20 +9,20 @@ namespace skyline::kernel::ipc {
header = reinterpret_cast<CommandHeader *>(currPtr);
currPtr += sizeof(CommandHeader);
if (header->handle_desc) {
if (header->handleDesc) {
handleDesc = reinterpret_cast<HandleDescriptor *>(currPtr);
currPtr += sizeof(HandleDescriptor) + (handleDesc->send_pid ? sizeof(u64) : 0);
for (uint index = 0; handleDesc->copy_count > index; index++) {
currPtr += sizeof(HandleDescriptor) + (handleDesc->sendPid ? sizeof(u64) : 0);
for (uint index = 0; handleDesc->copyCount > index; index++) {
copyHandles.push_back(*reinterpret_cast<handle_t *>(currPtr));
currPtr += sizeof(handle_t);
}
for (uint index = 0; handleDesc->move_count > index; index++) {
for (uint index = 0; handleDesc->moveCount > index; index++) {
moveHandles.push_back(*reinterpret_cast<handle_t *>(currPtr));
currPtr += sizeof(handle_t);
}
}
for (uint index = 0; header->x_no > index; index++) {
for (uint index = 0; header->Xno > index; index++) {
auto bufX = reinterpret_cast<BufferDescriptorX *>(currPtr);
if (bufX->Address()) {
vecBufX.push_back(bufX);
@ -31,7 +31,7 @@ namespace skyline::kernel::ipc {
currPtr += sizeof(BufferDescriptorX);
}
for (uint index = 0; header->a_no > index; index++) {
for (uint index = 0; header->Ano > index; index++) {
auto bufA = reinterpret_cast<BufferDescriptorABW *>(currPtr);
if (bufA->Address()) {
vecBufA.push_back(bufA);
@ -40,7 +40,7 @@ namespace skyline::kernel::ipc {
currPtr += sizeof(BufferDescriptorABW);
}
for (uint index = 0; header->b_no > index; index++) {
for (uint index = 0; header->Bno > index; index++) {
auto bufB = reinterpret_cast<BufferDescriptorABW *>(currPtr);
if (bufB->Address()) {
vecBufB.push_back(bufB);
@ -49,7 +49,7 @@ namespace skyline::kernel::ipc {
currPtr += sizeof(BufferDescriptorABW);
}
for (uint index = 0; header->w_no > index; index++) {
for (uint index = 0; header->Wno > index; index++) {
auto bufW = reinterpret_cast<BufferDescriptorABW *>(currPtr);
if (bufW->Address()) {
vecBufW.push_back(bufW);
@ -61,7 +61,7 @@ namespace skyline::kernel::ipc {
u64 padding = ((((reinterpret_cast<u64>(currPtr) - reinterpret_cast<u64>(tls.data())) - 1U) & ~(constant::IpcPaddingSum - 1U)) + constant::IpcPaddingSum + (reinterpret_cast<u64>(tls.data()) - reinterpret_cast<u64>(currPtr))); // Calculate the amount of padding at the front
currPtr += padding;
if (isDomain) {
if (isDomain && (header->type == CommandType::Request)) {
domain = reinterpret_cast<DomainHeaderRequest *>(currPtr);
currPtr += sizeof(DomainHeaderRequest);
@ -69,10 +69,10 @@ namespace skyline::kernel::ipc {
currPtr += sizeof(PayloadHeader);
cmdArg = currPtr;
cmdArgSz = domain->payload_sz - sizeof(PayloadHeader);
currPtr += domain->payload_sz;
cmdArgSz = domain->payloadSz - sizeof(PayloadHeader);
currPtr += domain->payloadSz;
for (uint index = 0; domain->input_count > index; index++) {
for (uint index = 0; domain->inputCount > index; index++) {
domainObjects.push_back(*reinterpret_cast<handle_t *>(currPtr));
currPtr += sizeof(handle_t);
}
@ -81,21 +81,21 @@ namespace skyline::kernel::ipc {
currPtr += sizeof(PayloadHeader);
cmdArg = currPtr;
cmdArgSz = (header->raw_sz * sizeof(u32)) - (constant::IpcPaddingSum + sizeof(PayloadHeader));
cmdArgSz = (header->rawSize * sizeof(u32)) - (constant::IpcPaddingSum + sizeof(PayloadHeader));
currPtr += cmdArgSz;
}
if (payload->magic != constant::SfciMagic && header->type != static_cast<u16>(CommandType::Control))
if (payload->magic != constant::SfciMagic && header->type != CommandType::Control)
state.logger->Debug("Unexpected Magic in PayloadHeader: 0x{:X}", u32(payload->magic));
currPtr += constant::IpcPaddingSum - padding;
if (header->c_flag == static_cast<u8>(BufferCFlag::SingleDescriptor)) {
if (header->cFlag == BufferCFlag::SingleDescriptor) {
auto bufC = reinterpret_cast<BufferDescriptorC *>(currPtr);
vecBufC.push_back(bufC);
state.logger->Debug("Buf C: AD: 0x{:X} SZ: 0x{:X}", u64(bufC->address), u16(bufC->size));
} else if (header->c_flag > static_cast<u8>(BufferCFlag::SingleDescriptor)) {
for (uint index = 0; (header->c_flag - 2) > index; index++) { // (c_flag - 2) C descriptors are present
} else if (header->cFlag > BufferCFlag::SingleDescriptor) {
for (uint index = 0; (static_cast<u8>(header->cFlag) - 2) > index; index++) { // (cFlag - 2) C descriptors are present
auto bufC = reinterpret_cast<BufferDescriptorC *>(currPtr);
if (bufC->address) {
vecBufC.push_back(bufC);
@ -105,12 +105,14 @@ namespace skyline::kernel::ipc {
}
}
state.logger->Debug("Header: X No: {}, A No: {}, B No: {}, W No: {}, C No: {}, Raw Size: {}", u8(header->x_no), u8(header->a_no), u8(header->b_no), u8(header->w_no), u8(vecBufC.size()), u64(cmdArgSz));
if (header->handle_desc)
state.logger->Debug("Handle Descriptor: Send PID: {}, Copy Count: {}, Move Count: {}", bool(handleDesc->send_pid), u32(handleDesc->copy_count), u32(handleDesc->move_count));
if (isDomain)
state.logger->Debug("Domain Header: Command: {}, Input Object Count: {}, Object ID: 0x{:X}", domain->command, domain->input_count, domain->object_id);
state.logger->Debug("Data Payload: Command ID: 0x{:X}", u32(payload->value));
if (header->type == CommandType::Request) {
state.logger->Debug("Header: X No: {}, A No: {}, B No: {}, W No: {}, C No: {}, Raw Size: {}", u8(header->Xno), u8(header->Ano), u8(header->Bno), u8(header->Wno), u8(vecBufC.size()), u64(cmdArgSz));
if (header->handleDesc)
state.logger->Debug("Handle Descriptor: Send PID: {}, Copy Count: {}, Move Count: {}", bool(handleDesc->sendPid), u32(handleDesc->copyCount), u32(handleDesc->moveCount));
if (isDomain)
state.logger->Debug("Domain Header: Command: {}, Input Object Count: {}, Object ID: 0x{:X}", domain->command, domain->inputCount, domain->objectId);
state.logger->Debug("Command ID: 0x{:X}", u32(payload->value));
}
}
IpcResponse::IpcResponse(bool isDomain, const DeviceState &state) : isDomain(isDomain), state(state) {}
@ -119,14 +121,14 @@ namespace skyline::kernel::ipc {
std::array<u8, constant::TlsIpcSize> tls{};
u8 *currPtr = tls.data();
auto header = reinterpret_cast<CommandHeader *>(currPtr);
header->raw_sz = static_cast<u32>((sizeof(PayloadHeader) + argVec.size() + (domainObjects.size() * sizeof(handle_t)) + constant::IpcPaddingSum + (isDomain ? sizeof(DomainHeaderRequest) : 0)) / sizeof(u32)); // Size is in 32-bit units because Nintendo
header->handle_desc = (!copyHandles.empty() || !moveHandles.empty());
header->rawSize = static_cast<u32>((sizeof(PayloadHeader) + argVec.size() + (domainObjects.size() * sizeof(handle_t)) + constant::IpcPaddingSum + (isDomain ? sizeof(DomainHeaderRequest) : 0)) / sizeof(u32)); // Size is in 32-bit units because Nintendo
header->handleDesc = (!copyHandles.empty() || !moveHandles.empty());
currPtr += sizeof(CommandHeader);
if (header->handle_desc) {
if (header->handleDesc) {
auto handleDesc = reinterpret_cast<HandleDescriptor *>(currPtr);
handleDesc->copy_count = static_cast<u8>(copyHandles.size());
handleDesc->move_count = static_cast<u8>(moveHandles.size());
handleDesc->copyCount = static_cast<u8>(copyHandles.size());
handleDesc->moveCount = static_cast<u8>(moveHandles.size());
currPtr += sizeof(HandleDescriptor);
for (unsigned int copyHandle : copyHandles) {
@ -145,7 +147,7 @@ namespace skyline::kernel::ipc {
if (isDomain) {
auto domain = reinterpret_cast<DomainHeaderResponse *>(currPtr);
domain->output_count = static_cast<u32>(domainObjects.size());
domain->outputCount = static_cast<u32>(domainObjects.size());
currPtr += sizeof(DomainHeaderResponse);
}
@ -165,7 +167,7 @@ namespace skyline::kernel::ipc {
}
}
state.logger->Debug("Output: Raw Size: {}, Command ID: 0x{:X}, Copy Handles: {}, Move Handles: {}", u32(header->raw_sz), u32(payload->value), copyHandles.size(), moveHandles.size());
state.logger->Debug("Output: Raw Size: {}, Command ID: 0x{:X}, Copy Handles: {}, Move Handles: {}", u32(header->rawSize), u32(payload->value), copyHandles.size(), moveHandles.size());
state.thisProcess->WriteMemory(tls.data(), state.thisThread->tls, constant::TlsIpcSize);
}