Skip to content

Commit c0fe4f7

Browse files
committed
fs.mitm: Intercept qlaunch sysver request
1 parent 5b219e6 commit c0fe4f7

4 files changed

Lines changed: 194 additions & 6 deletions

File tree

stratosphere/fs_mitm/source/fsmitm_main.cpp

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232

3333
#include "fsmitm_utils.hpp"
3434

35+
#include "setsys_mitm_service.hpp"
36+
3537
extern "C" {
3638
extern u32 __start__;
3739

@@ -86,15 +88,30 @@ void __appExit(void) {
8688
smExit();
8789
}
8890

91+
void CreateSettingsMitMServer(void *arg) {
92+
MultiThreadedWaitableManager *server_manager = (MultiThreadedWaitableManager *)arg;
93+
94+
Result rc;
95+
if (R_FAILED((rc = setsysInitialize()))) {
96+
fatalSimple(rc);
97+
}
98+
99+
ISession<MitMQueryService<SetSysMitMService>> *setsys_query_srv = NULL;
100+
MitMServer<SetSysMitMService> *setsys_srv = new MitMServer<SetSysMitMService>(&setsys_query_srv, "set:sys", 60);
101+
server_manager->add_waitable(setsys_srv);
102+
server_manager->add_waitable(setsys_query_srv);
103+
104+
svcExitThread();
105+
}
106+
89107
int main(int argc, char **argv)
90108
{
91109
Thread worker_thread = {0};
92110
Thread sd_initializer_thread = {0};
93111
Thread hid_initializer_thread = {0};
112+
Thread set_mitm_setup_thread = {0};
94113
consoleDebugInit(debugDevice_SVC);
95-
96-
consoleDebugInit(debugDevice_SVC);
97-
114+
98115
if (R_FAILED(threadCreate(&worker_thread, &FsMitMWorker::Main, NULL, 0x20000, 45, 0))) {
99116
/* TODO: Panic. */
100117
}
@@ -117,17 +134,26 @@ int main(int argc, char **argv)
117134
}
118135

119136
/* TODO: What's a good timeout value to use here? */
120-
auto server_manager = std::make_unique<MultiThreadedWaitableManager>(5, U64_MAX, 0x20000);
121-
//auto server_manager = std::make_unique<WaitableManager>(U64_MAX);
137+
MultiThreadedWaitableManager *server_manager = new MultiThreadedWaitableManager(5, U64_MAX, 0x20000);
122138

123139
/* Create fsp-srv mitm. */
124140
ISession<MitMQueryService<FsMitMService>> *fs_query_srv = NULL;
125141
MitMServer<FsMitMService> *fs_srv = new MitMServer<FsMitMService>(&fs_query_srv, "fsp-srv", 61);
126142
server_manager->add_waitable(fs_srv);
127143
server_manager->add_waitable(fs_query_srv);
144+
145+
/* Create set:sys mitm server, delayed until set:sys is available. */
146+
if (R_FAILED(threadCreate(&set_mitm_setup_thread, &CreateSettingsMitMServer, server_manager, 0x4000, 0x15, 0))) {
147+
/* TODO: Panic. */
148+
}
149+
if (R_FAILED(threadStart(&set_mitm_setup_thread))) {
150+
/* TODO: Panic. */
151+
}
128152

129153
/* Loop forever, servicing our services. */
130154
server_manager->process();
155+
156+
delete server_manager;
131157

132158
return 0;
133159
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright (c) 2018 Atmosphère-NX
3+
*
4+
* This program is free software; you can redistribute it and/or modify it
5+
* under the terms and conditions of the GNU General Public License,
6+
* version 2, as published by the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11+
* more details.
12+
*
13+
* You should have received a copy of the GNU General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
17+
#include <mutex>
18+
#include <switch.h>
19+
#include "setsys_mitm_service.hpp"
20+
21+
#include "mitm_query_service.hpp"
22+
#include "debug.hpp"
23+
24+
static HosMutex g_version_mutex;
25+
static bool g_got_version = false;
26+
static SetSysFirmwareVersion g_fw_version = {0};
27+
28+
static Result _GetFirmwareVersion(SetSysFirmwareVersion *out) {
29+
std::lock_guard<HosMutex> lock(g_version_mutex);
30+
if (!g_got_version) {
31+
Result rc = setsysGetFirmwareVersion(&g_fw_version);
32+
if (R_FAILED(rc)) {
33+
return rc;
34+
}
35+
36+
/* Modify the output firmware version. */
37+
{
38+
u32 major, minor, micro;
39+
char display_version[sizeof(g_fw_version.display_version)] = {0};
40+
41+
GetAtmosphereApiVersion(&major, &minor, &micro, nullptr, nullptr);
42+
snprintf(display_version, sizeof(display_version), "%s (AMS %u.%u.%u)", g_fw_version.display_version, major, minor, micro);
43+
44+
memcpy(g_fw_version.display_version, display_version, sizeof(g_fw_version.display_version));
45+
}
46+
47+
g_got_version = true;
48+
}
49+
50+
*out = g_fw_version;
51+
return 0;
52+
}
53+
54+
Result SetSysMitMService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
55+
Result rc = 0xF601;
56+
57+
switch (static_cast<SetSysCmd>(cmd_id)) {
58+
case SetSysCmd::GetFirmwareVersion:
59+
rc = WrapIpcCommandImpl<&SetSysMitMService::get_firmware_version>(this, r, out_c, pointer_buffer, pointer_buffer_size);
60+
break;
61+
case SetSysCmd::GetFirmwareVersion2:
62+
if (kernelAbove300()) {
63+
rc = WrapIpcCommandImpl<&SetSysMitMService::get_firmware_version2>(this, r, out_c, pointer_buffer, pointer_buffer_size);
64+
}
65+
break;
66+
default:
67+
break;
68+
}
69+
70+
return rc;
71+
}
72+
73+
void SetSysMitMService::postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
74+
/* No commands need postprocessing. */
75+
}
76+
77+
Result SetSysMitMService::handle_deferred() {
78+
/* This service is never deferrable. */
79+
return 0;
80+
}
81+
82+
std::tuple<Result> SetSysMitMService::get_firmware_version(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) {
83+
if (out.num_elements != 1) {
84+
return {0xF601};
85+
}
86+
87+
Result rc = _GetFirmwareVersion(out.pointer);
88+
89+
/* GetFirmwareVersion sanitizes these fields. */
90+
out.pointer->revision_major = 0;
91+
out.pointer->revision_minor = 0;
92+
93+
return {rc};
94+
}
95+
96+
std::tuple<Result> SetSysMitMService::get_firmware_version2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) {
97+
if (out.num_elements != 1) {
98+
return {0xF601};
99+
}
100+
101+
Result rc = _GetFirmwareVersion(out.pointer);
102+
103+
return {rc};
104+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (c) 2018 Atmosphère-NX
3+
*
4+
* This program is free software; you can redistribute it and/or modify it
5+
* under the terms and conditions of the GNU General Public License,
6+
* version 2, as published by the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11+
* more details.
12+
*
13+
* You should have received a copy of the GNU General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
17+
#pragma once
18+
#include <switch.h>
19+
#include <stratosphere/iserviceobject.hpp>
20+
#include "imitmserviceobject.hpp"
21+
#include "fsmitm_utils.hpp"
22+
23+
enum class SetSysCmd {
24+
GetFirmwareVersion = 3,
25+
GetFirmwareVersion2 = 4,
26+
};
27+
28+
class SetSysMitMService : public IMitMServiceObject {
29+
private:
30+
public:
31+
SetSysMitMService(Service *s) : IMitMServiceObject(s) {
32+
/* ... */
33+
}
34+
35+
static bool should_mitm(u64 pid, u64 tid) {
36+
/* Only MitM qlaunch, maintenance. */
37+
return tid == 0x0100000000001000ULL || tid == 0x0100000000001015ULL;
38+
}
39+
40+
SetSysMitMService *clone() override {
41+
auto new_srv = new SetSysMitMService((Service *)&this->forward_service);
42+
this->clone_to(new_srv);
43+
return new_srv;
44+
}
45+
46+
void clone_to(void *o) override {
47+
/* ... */
48+
}
49+
50+
virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size);
51+
virtual void postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size);
52+
virtual Result handle_deferred();
53+
54+
protected:
55+
/* Overridden commands. */
56+
std::tuple<Result> get_firmware_version(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out);
57+
std::tuple<Result> get_firmware_version2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out);
58+
};

stratosphere/libstratosphere/include/stratosphere/isession.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ class ISession : public IWaitable {
196196
/* TODO: Panic? */
197197
}
198198
IpcParsedCommand r;
199-
u64 cmd_id;
199+
u64 cmd_id = 0;
200200

201201

202202
Result retval = ipcParse(&r);

0 commit comments

Comments
 (0)