IOS/ES: Implement ES_SetUid

This implements ES_SetUid, which is used by the system menu to change
its own permissions. This is required for implementing permission
checks and proper NAND metadata support in the future.
This commit is contained in:
Léo Lam 2017-04-25 00:07:34 +02:00
parent c01fda6255
commit cc40389f88
3 changed files with 38 additions and 7 deletions

View File

@ -173,14 +173,39 @@ static bool UpdateUIDAndGID(const IOS::ES::TMDReader& tmd)
return true; return true;
} }
static ReturnCode CheckIsAllowedToSetUID(const u32 caller_uid)
{
IOS::ES::UIDSys uid_map{Common::FromWhichRoot::FROM_SESSION_ROOT};
const u32 system_menu_uid = uid_map.GetOrInsertUIDForTitle(TITLEID_SYSMENU);
if (!system_menu_uid)
return ES_SHORT_READ;
return caller_uid == system_menu_uid ? IPC_SUCCESS : ES_EINVAL;
}
IPCCommandResult ES::SetUID(const IOCtlVRequest& request) IPCCommandResult ES::SetUID(const IOCtlVRequest& request)
{ {
if (!request.HasNumberOfValidVectors(1, 0)) if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8)
return GetDefaultReply(ES_EINVAL); return GetDefaultReply(ES_EINVAL);
// TODO: fs permissions based on this const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
INFO_LOG(IOS_ES, "IOCTL_ES_SETUID titleID: %08x/%08x", (u32)(TitleID >> 32), (u32)TitleID); const s32 ret = CheckIsAllowedToSetUID(m_caller_uid);
if (ret < 0)
{
ERROR_LOG(IOS_ES, "SetUID: Permission check failed with error %d", ret);
return GetDefaultReply(ret);
}
const auto tmd = IOS::ES::FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
if (!UpdateUIDAndGID(tmd))
{
ERROR_LOG(IOS_ES, "SetUID: Failed to get UID for title %016" PRIx64, title_id);
return GetDefaultReply(ES_SHORT_READ);
}
return GetDefaultReply(IPC_SUCCESS); return GetDefaultReply(IPC_SUCCESS);
} }
@ -265,6 +290,9 @@ void ES::DoState(PointerWrap& p)
p.Do(m_addtitle_content_id); p.Do(m_addtitle_content_id);
p.Do(m_addtitle_content_buffer); p.Do(m_addtitle_content_buffer);
p.Do(m_caller_uid);
p.Do(m_caller_gid);
p.Do(m_export_title_context.valid); p.Do(m_export_title_context.valid);
m_export_title_context.tmd.DoState(p); m_export_title_context.tmd.DoState(p);
p.Do(m_export_title_context.title_key); p.Do(m_export_title_context.title_key);
@ -296,8 +324,8 @@ void ES::DoState(PointerWrap& p)
ReturnCode ES::Open(const OpenRequest& request) ReturnCode ES::Open(const OpenRequest& request)
{ {
if (m_is_active) m_caller_uid = request.uid;
INFO_LOG(IOS_ES, "Device was re-opened."); m_caller_gid = request.gid;
return Device::Open(request); return Device::Open(request);
} }

View File

@ -246,6 +246,9 @@ private:
u32 m_addtitle_content_id = 0xFFFFFFFF; u32 m_addtitle_content_id = 0xFFFFFFFF;
std::vector<u8> m_addtitle_content_buffer; std::vector<u8> m_addtitle_content_buffer;
u32 m_caller_uid = 0;
u16 m_caller_gid = 0;
struct TitleExportContext struct TitleExportContext
{ {
struct ExportContent struct ExportContent

View File

@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread; static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system // Don't forget to increase this after doing changes on the savestate system
static const u32 STATE_VERSION = 80; // Last changed in PR 5309 static const u32 STATE_VERSION = 81; // Last changed in PR 5317
// Maps savestate versions to Dolphin versions. // Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list, // Versions after 42 don't need to be added to this list,