mitm: fix long-standing C descriptor issue.

This commit is contained in:
Michael Scire 2019-09-24 21:43:18 -07:00 committed by SciresM
parent bb223eb5ae
commit e07011be32
9 changed files with 17 additions and 143 deletions

View file

@ -18,7 +18,6 @@
#include <algorithm>
#include <switch.h>
#include "set_mitm_service.hpp"
#include "set_shim.h"
void SetMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) {
/* No commands need postprocessing. */
@ -104,7 +103,3 @@ Result SetMitmService::GetRegionCode(Out<u32> out_region_code) {
out_region_code.SetValue(this->locale.region_code);
return ResultSuccess;
}
Result SetMitmService::GetAvailableLanguageCodes(OutPointerWithClientSize<u64> out_language_codes, Out<s32> out_count) {
return setGetAvailableLanguageCodesFwd(this->forward_service.get(), out_count.GetPointer(), out_language_codes.pointer, out_language_codes.num_elements);
}

View file

@ -25,10 +25,6 @@ class SetMitmService : public IMitmServiceObject {
enum class CommandId {
GetLanguageCode = 0,
GetRegionCode = 4,
/* Commands for which set:sys *must* act as a passthrough. */
/* TODO: Solve the relevant IPC detection problem. */
GetAvailableLanguageCodes = 1,
};
private:
sts::os::Mutex lock;
@ -55,14 +51,9 @@ class SetMitmService : public IMitmServiceObject {
/* Overridden commands. */
Result GetLanguageCode(Out<u64> out_lang_code);
Result GetRegionCode(Out<u32> out_region_code);
/* Forced passthrough commands. */
Result GetAvailableLanguageCodes(OutPointerWithClientSize<u64> out_language_codes, Out<s32> out_count);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(SetMitmService, GetLanguageCode),
MAKE_SERVICE_COMMAND_META(SetMitmService, GetRegionCode),
MAKE_SERVICE_COMMAND_META(SetMitmService, GetAvailableLanguageCodes),
};
};

View file

@ -1,59 +0,0 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <switch.h>
#include "setsys_shim.h"
/* Command forwarders. */
Result setGetAvailableLanguageCodesFwd(Service* s, s32 *total_entries, u64 *language_codes, size_t max_entries) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvStatic(&c, language_codes, max_entries * sizeof(*language_codes), 0);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 1;
Result rc = serviceIpcDispatch(s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
s32 total_entries;
} *resp;
serviceIpcParse(s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*total_entries = resp->total_entries;
}
}
return rc;
}

View file

@ -1,19 +0,0 @@
/**
* @file set_shim.h
* @brief Settings Services (set) IPC wrapper. To be merged into libnx, eventually.
* @author SciresM
* @copyright libnx Authors
*/
#pragma once
#include <switch.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Command forwarders. */
Result setGetAvailableLanguageCodesFwd(Service* s, s32 *total_entries, u64 *language_codes, size_t max_entries);
#ifdef __cplusplus
}
#endif

View file

@ -98,7 +98,3 @@ Result SetSysMitmService::GetSettingsItemValue(Out<u64> out_size, OutBuffer<u8>
return ResultSuccess;
}
Result SetSysMitmService::GetEdid(OutPointerWithServerSize<SetSysEdid, 0x1> out) {
return setsysGetEdidFwd(this->forward_service.get(), out.pointer);
}

View file

@ -27,10 +27,6 @@ class SetSysMitmService : public IMitmServiceObject {
GetFirmwareVersion2 = 4,
GetSettingsItemValueSize = 37,
GetSettingsItemValue = 38,
/* Commands for which set:sys *must* act as a passthrough. */
/* TODO: Solve the relevant IPC detection problem. */
GetEdid = 41,
};
public:
SetSysMitmService(std::shared_ptr<Service> s, u64 pid, sts::ncm::TitleId tid) : IMitmServiceObject(s, pid, tid) {
@ -50,16 +46,11 @@ class SetSysMitmService : public IMitmServiceObject {
Result GetFirmwareVersion2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out);
Result GetSettingsItemValueSize(Out<u64> out_size, InPointer<char> name, InPointer<char> key);
Result GetSettingsItemValue(Out<u64> out_size, OutBuffer<u8> out_value, InPointer<char> name, InPointer<char> key);
/* Forced passthrough commands. */
Result GetEdid(OutPointerWithServerSize<SetSysEdid, 0x1> out);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(SetSysMitmService, GetFirmwareVersion),
MAKE_SERVICE_COMMAND_META(SetSysMitmService, GetFirmwareVersion2),
MAKE_SERVICE_COMMAND_META(SetSysMitmService, GetSettingsItemValueSize),
MAKE_SERVICE_COMMAND_META(SetSysMitmService, GetSettingsItemValue),
MAKE_SERVICE_COMMAND_META(SetSysMitmService, GetEdid),
};
};

View file

@ -19,39 +19,6 @@
#include "setsys_shim.h"
/* Command forwarders. */
Result setsysGetEdidFwd(Service* s, SetSysEdid* out) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvStatic(&c, out, sizeof(*out), 0);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 41;
Result rc = serviceIpcDispatch(s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result setsysGetSettingsItemValueFwd(Service *s, const char *name, const char *item_key, void *value_out, size_t value_out_size, u64 *size_out) {
char send_name[SET_MAX_NAME_SIZE];
char send_item_key[SET_MAX_NAME_SIZE];

View file

@ -11,12 +11,7 @@
extern "C" {
#endif
typedef struct {
char edid[0x100];
} SetSysEdid;
/* Command forwarders. */
Result setsysGetEdidFwd(Service* s, SetSysEdid* out);
Result setsysGetSettingsItemValueFwd(Service* s, const char *name, const char *item_key, void *value_out, size_t value_out_size, u64 *size_out);
#ifdef __cplusplus

View file

@ -80,6 +80,23 @@ class MitmSession final : public ServiceSession {
}
Result ForwardRequest(IpcResponseContext *ctx) {
/* Mitm forward specific preprocessing. */
if (ctx->request.NumStaticsOut) {
u32 *cmdbuf = (u32 *)armGetTls();
/* Overwrite the number of C descriptors to only use a single buffer. */
cmdbuf[1] = (cmdbuf[1] & (~u32(0xF << 10))) | (0x2 << 10);
IpcStaticRecvDescriptor *c_desc = (IpcStaticRecvDescriptor *)(reinterpret_cast<uintptr_t>(ctx->request.RawWithoutPadding) + ctx->request.RawSize);
/* Don't write out of bounds, though this should never happen. */
if (reinterpret_cast<uintptr_t>(c_desc) + sizeof(*c_desc) <= reinterpret_cast<uintptr_t>(cmdbuf) + 0x100) {
uintptr_t ptr = reinterpret_cast<uintptr_t>(this->pointer_buffer.data());
c_desc->Addr = ptr;
c_desc->Packed = (ptr >> 32) | (this->pointer_buffer.size() << 16);
} else {
std::abort();
}
}
/* Dispatch forwards. */
R_TRY(serviceIpcDispatch(this->forward_service.get()));