Merge pull request #5309 from leoetlino/ios-uid-gid

IOS: Implement UID/GID changes for the PPC
This commit is contained in:
Léo Lam 2017-04-24 22:50:03 +02:00 committed by GitHub
commit 286e9b74ee
8 changed files with 86 additions and 18 deletions

View File

@ -158,6 +158,21 @@ IPCCommandResult ES::GetTitleID(const IOCtlVRequest& request)
return GetDefaultReply(IPC_SUCCESS);
}
static bool UpdateUIDAndGID(const IOS::ES::TMDReader& tmd)
{
IOS::ES::UIDSys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT};
const u64 title_id = tmd.GetTitleId();
const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id);
if (!uid)
{
ERROR_LOG(IOS_ES, "Failed to get UID for title %016" PRIx64, title_id);
return false;
}
SetUIDForPPC(uid);
SetGIDForPPC(tmd.GetGroupId());
return true;
}
IPCCommandResult ES::SetUID(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0))
@ -226,6 +241,16 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload)
s_title_context.Update(content_loader);
INFO_LOG(IOS_ES, "LaunchPPCTitle: Title context changed: %016" PRIx64,
s_title_context.tmd.GetTitleId());
// Note: the UID/GID is also updated for IOS titles, but since we have no guarantee IOS titles
// are installed, we can only do this for PPC titles.
if (!UpdateUIDAndGID(s_title_context.tmd))
{
s_title_context.Clear();
INFO_LOG(IOS_ES, "LaunchPPCTitle: Title context changed: (none)");
return false;
}
return BootstrapPPC(content_loader);
}
@ -533,6 +558,9 @@ s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& tic
if (tmd.GetTitleId() != ticket.GetTitleId())
return ES_EINVAL;
s_title_context.Update(tmd, ticket);
INFO_LOG(IOS_ES, "ES_DIVerify: Title context changed: %016" PRIx64, tmd.GetTitleId());
std::string tmd_path = Common::GetTMDFileName(tmd.GetTitleId(), Common::FROM_SESSION_ROOT);
File::CreateFullPath(tmd_path);
@ -545,14 +573,15 @@ s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& tic
if (!tmd_file.WriteBytes(tmd_bytes.data(), tmd_bytes.size()))
ERROR_LOG(IOS_ES, "DIVerify failed to write disc TMD to NAND.");
}
IOS::ES::UIDSys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT};
uid_sys.AddTitle(tmd.GetTitleId());
// DI_VERIFY writes to title.tmd, which is read and cached inside the NAND Content Manager.
// clear the cache to avoid content access mismatches.
DiscIO::CNANDContentManager::Access().ClearCache();
s_title_context.Update(tmd, ticket);
INFO_LOG(IOS_ES, "ES_DIVerify: Title context changed: %016" PRIx64, tmd.GetTitleId());
if (!UpdateUIDAndGID(s_title_context.tmd))
{
return ES_SHORT_READ;
}
return IPC_SUCCESS;
}
} // namespace Device

View File

@ -446,11 +446,11 @@ UIDSys::UIDSys(Common::FromWhichRoot root)
if (m_entries.empty())
{
AddTitle(TITLEID_SYSMENU);
GetOrInsertUIDForTitle(TITLEID_SYSMENU);
}
}
u32 UIDSys::GetUIDFromTitle(u64 title_id)
u32 UIDSys::GetUIDFromTitle(u64 title_id) const
{
const auto it = std::find_if(m_entries.begin(), m_entries.end(),
[title_id](const auto& entry) { return entry.second == title_id; });
@ -464,26 +464,33 @@ u32 UIDSys::GetNextUID() const
return m_entries.rbegin()->first + 1;
}
void UIDSys::AddTitle(u64 title_id)
u32 UIDSys::GetOrInsertUIDForTitle(const u64 title_id)
{
if (GetUIDFromTitle(title_id))
const u32 current_uid = GetUIDFromTitle(title_id);
if (current_uid)
{
INFO_LOG(IOS_ES, "Title %016" PRIx64 " already exists in uid.sys", title_id);
return;
return current_uid;
}
u32 uid = GetNextUID();
const u32 uid = GetNextUID();
m_entries.insert({uid, title_id});
// Byte swap before writing.
title_id = Common::swap64(title_id);
uid = Common::swap32(uid);
const u64 swapped_title_id = Common::swap64(title_id);
const u32 swapped_uid = Common::swap32(uid);
File::CreateFullPath(m_file_path);
File::IOFile file(m_file_path, "ab");
if (!file.WriteBytes(&title_id, sizeof(title_id)) || !file.WriteBytes(&uid, sizeof(uid)))
if (!file.WriteBytes(&swapped_title_id, sizeof(title_id)) ||
!file.WriteBytes(&swapped_uid, sizeof(uid)))
{
ERROR_LOG(IOS_ES, "Failed to write to /sys/uid.sys");
return 0;
}
return uid;
}
} // namespace ES
} // namespace IOS

View File

@ -219,8 +219,8 @@ class UIDSys final
public:
explicit UIDSys(Common::FromWhichRoot root);
u32 GetUIDFromTitle(u64 title_id);
void AddTitle(u64 title_id);
u32 GetUIDFromTitle(u64 title_id) const;
u32 GetOrInsertUIDForTitle(u64 title_id);
u32 GetNextUID() const;
private:

View File

@ -194,7 +194,7 @@ bool InitImport(u64 title_id)
}
UIDSys uid_sys{Common::FROM_CONFIGURED_ROOT};
uid_sys.AddTitle(title_id);
uid_sys.GetOrInsertUIDForTitle(title_id);
// IOS moves the title content directory to /import if the TMD exists during an import.
if (File::Exists(Common::GetTMDFileName(title_id, Common::FROM_SESSION_ROOT)))

View File

@ -91,6 +91,9 @@ static u64 s_last_reply_time;
static u64 s_active_title_id;
static u32 s_ppc_uid;
static u16 s_ppc_gid;
static constexpr u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL;
static constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL;
@ -702,6 +705,28 @@ bool Reload(const u64 ios_title_id)
return true;
}
// Since we don't have actual processes, we keep track of only the PPC's UID/GID.
// These functions roughly correspond to syscalls 0x2b, 0x2c, 0x2d, 0x2e (though only for the PPC).
void SetUIDForPPC(u32 uid)
{
s_ppc_uid = uid;
}
u32 GetUIDForPPC()
{
return s_ppc_uid;
}
void SetGIDForPPC(u16 gid)
{
s_ppc_gid = gid;
}
u16 GetGIDForPPC()
{
return s_ppc_gid;
}
// This corresponds to syscall 0x41, which loads a binary from the NAND and bootstraps the PPC.
// Unlike 0x42, IOS will set up some constants in memory before booting the PPC.
bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader)
@ -783,6 +808,8 @@ void DoState(PointerWrap& p)
p.Do(s_reply_queue);
p.Do(s_last_reply_time);
p.Do(s_active_title_id);
p.Do(s_ppc_uid);
p.Do(s_ppc_gid);
if (s_active_title_id == MIOS_TITLE_ID)
return;

View File

@ -59,6 +59,11 @@ void Shutdown();
bool Reload(u64 ios_title_id);
u32 GetVersion();
void SetUIDForPPC(u32 uid);
u32 GetUIDForPPC();
void SetGIDForPPC(u16 gid);
u16 GetGIDForPPC();
bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader);
// Do State

View File

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

View File

@ -336,7 +336,7 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
}
IOS::ES::UIDSys uid_sys{Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
uid_sys.AddTitle(title_id);
uid_sys.GetOrInsertUIDForTitle(title_id);
ClearCache();