1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 20:22:30 +01:00

Implement ps3 application root flags detection

This commit is contained in:
Eladash 2019-11-01 21:21:15 +02:00 committed by Ivan
parent 974bce19ed
commit c2eb9a583d
13 changed files with 193 additions and 37 deletions

View File

@ -885,12 +885,17 @@ SELFDecrypter::SELFDecrypter(const fs::file& s)
{
}
bool SELFDecrypter::LoadHeaders(bool isElf32)
bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
{
// Read SCE header.
self_f.seek(0);
sce_hdr.Load(self_f);
if (out_info)
{
out_info->valid = false;
}
// Check SCE magic.
if (!sce_hdr.CheckMagic())
{
@ -905,6 +910,11 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
self_f.seek(self_hdr.se_appinfooff);
app_info.Load(self_f);
if (out_info)
{
out_info->app_info = app_info;
}
// Read ELF header.
self_f.seek(self_hdr.se_elfoff);
@ -967,8 +977,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
ctrlinfo_arr.clear();
self_f.seek(self_hdr.se_controloff);
u32 i = 0;
while(i < self_hdr.se_controlsize)
for (u64 i = 0; i < self_hdr.se_controlsize;)
{
ctrlinfo_arr.emplace_back();
ControlInfo &cinfo = ctrlinfo_arr.back();
@ -976,6 +985,11 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
i += cinfo.size;
}
if (out_info)
{
out_info->ctrl_info = ctrlinfo_arr;
}
// Read ELF section headers.
if (isElf32)
{
@ -1013,6 +1027,11 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
}
}
if (out_info)
{
out_info->valid = true;
}
return true;
}
@ -1374,8 +1393,13 @@ static bool CheckDebugSelf(fs::file& s)
return false;
}
extern fs::file decrypt_self(fs::file elf_or_self, u8* klic_key)
fs::file decrypt_self(fs::file elf_or_self, u8* klic_key, SelfAdditionalInfo* out_info)
{
if (out_info)
{
out_info->valid = false;
}
if (!elf_or_self)
{
return fs::file{};
@ -1393,7 +1417,7 @@ extern fs::file decrypt_self(fs::file elf_or_self, u8* klic_key)
SELFDecrypter self_dec(elf_or_self);
// Load the SELF file headers.
if (!self_dec.LoadHeaders(isElf32))
if (!self_dec.LoadHeaders(isElf32, out_info))
{
LOG_ERROR(LOADER, "SELF: Failed to load SELF file headers!");
return fs::file{};
@ -1420,7 +1444,7 @@ extern fs::file decrypt_self(fs::file elf_or_self, u8* klic_key)
return elf_or_self;
}
extern bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key)
bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key)
{
if (!self)
return false;

View File

@ -343,6 +343,13 @@ struct SelfHeader
void Show(){}
};
struct SelfAdditionalInfo
{
bool valid = false;
std::vector<ControlInfo> ctrl_info;
AppInfo app_info;
};
class SCEDecrypter
{
protected:
@ -413,7 +420,7 @@ class SELFDecrypter
public:
SELFDecrypter(const fs::file& s);
fs::file MakeElf(bool isElf32);
bool LoadHeaders(bool isElf32);
bool LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info = nullptr);
void ShowHeaders(bool isElf32);
bool LoadMetadata(u8* klic_key);
bool DecryptData();
@ -497,6 +504,6 @@ private:
}
};
extern fs::file decrypt_self(fs::file elf_or_self, u8* klic_key = nullptr);
extern bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key = nullptr);
extern std::array<u8, 0x10> get_default_self_klic();
fs::file decrypt_self(fs::file elf_or_self, u8* klic_key = nullptr, SelfAdditionalInfo* additional_info = nullptr);
bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key = nullptr);
std::array<u8, 0x10> get_default_self_klic();

View File

@ -1160,6 +1160,27 @@ void ppu_load_exec(const ppu_exec_object& elf)
}
}
// Read control flags (0 if doesn't exist)
g_ps3_process_info.ctrl_flags1 = 0;
if (bool not_found = true)
{
for (const auto& ctrl : g_ps3_process_info.self_info.ctrl_info)
{
if (ctrl.type == 1)
{
if (!std::exchange(not_found, false))
{
LOG_ERROR(LOADER, "More than one control flags header found! (flags1=0x%x)",
ctrl.control_flags.ctrl_flag1);
break;
}
g_ps3_process_info.ctrl_flags1 |= ctrl.control_flags.ctrl_flag1;
}
}
}
// Load other programs
for (auto& prog : elf.progs)
{
@ -1207,7 +1228,8 @@ void ppu_load_exec(const ppu_exec_object& elf)
{
sdk_version = info.sdk_version;
if (s32 prio = info.primary_prio; prio < 3072 && prio >= 0)
if (s32 prio = info.primary_prio; prio < 3072
&& (prio >= (g_ps3_process_info.debug_or_root() ? 0 : -512)))
{
primary_prio = prio;
}

View File

@ -166,7 +166,7 @@ public:
u64 rtime{0};
u64 rdata{0}; // Reservation data
atomic_t<u32> prio{0}; // Thread priority (0..3071)
atomic_t<s32> prio{0}; // Thread priority (0..3071)
const u32 stack_size; // Stack size
const u32 stack_addr; // Stack address

View File

@ -770,7 +770,7 @@ const std::array<ppu_function_t, 1024> s_ppu_syscall_table
null_func,//BIND_FUNC(sys_ss_individual_info_manager) //868 ROOT / DBG AUTHID
null_func,//BIND_FUNC(sys_ss_factory_data_manager) //869 ROOT
BIND_FUNC(sys_ss_get_console_id), //870 (0x366)
null_func,//BIND_FUNC(sys_ss_access_control_engine), //871 (0x367) DBG
BIND_FUNC(sys_ss_access_control_engine), //871 (0x367) DBG
BIND_FUNC(sys_ss_get_open_psid), //872 (0x368)
null_func,//BIND_FUNC(sys_ss_get_cache_of_product_mode), //873 (0x369)
null_func,//BIND_FUNC(sys_ss_get_cache_of_flash_ext_flag), //874 (0x36A)
@ -1066,20 +1066,24 @@ void lv2_obj::sleep_unlocked(cpu_thread& thread, u64 timeout)
}
}
void lv2_obj::awake_unlocked(cpu_thread* cpu, u32 prio)
void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
{
// Check thread type
AUDIT(!cpu || cpu->id_type() == 1);
if (prio < INT32_MAX)
switch (prio)
{
// Priority set
if (static_cast<ppu_thread*>(cpu)->prio.exchange(prio) == prio || !unqueue(g_ppu, cpu))
{
return;
}
default:
{
// Priority set
if (static_cast<ppu_thread*>(cpu)->prio.exchange(prio) == prio || !unqueue(g_ppu, cpu))
{
return;
}
break;
}
else if (prio == -4)
case yield_cmd:
{
// Yield command
const u64 start_time = get_guest_system_time();
@ -1102,6 +1106,11 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, u32 prio)
static_cast<ppu_thread*>(cpu)->start_time = start_time;
}
case enqueue_cmd:
{
break;
}
}
const auto emplace_thread = [](cpu_thread* const cpu)
{

View File

@ -7,6 +7,7 @@
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/PPUThread.h"
#include "sys_event.h"
#include "sys_process.h"
#include "sys_mmapper.h"
LOG_CHANNEL(sys_ppu_thread);
@ -210,7 +211,7 @@ error_code sys_ppu_thread_set_priority(ppu_thread& ppu, u32 thread_id, s32 prio)
{
sys_ppu_thread.trace("sys_ppu_thread_set_priority(thread_id=0x%x, prio=%d)", thread_id, prio);
if (prio < 0 || prio > 3071)
if (prio < (g_ps3_process_info.debug_or_root() ? -512 : 0) || prio > 3071)
{
return CELL_EINVAL;
}
@ -219,7 +220,7 @@ error_code sys_ppu_thread_set_priority(ppu_thread& ppu, u32 thread_id, s32 prio)
{
if (thread.prio != prio)
{
lv2_obj::awake(&thread, prio);
lv2_obj::set_priority(thread, prio);
}
});
@ -299,7 +300,7 @@ error_code _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_par
return CELL_EFAULT;
}
if (prio < 0 || prio > 3071)
if (prio < (g_ps3_process_info.debug_or_root() ? -512 : 0) || prio > 3071)
{
return CELL_EINVAL;
}
@ -359,7 +360,7 @@ error_code sys_ppu_thread_start(ppu_thread& ppu, u32 thread_id)
const auto thread = idm::get<named_thread<ppu_thread>>(thread_id, [&](ppu_thread& thread)
{
lv2_obj::awake(&thread, -2);
lv2_obj::awake(&thread);
});
if (!thread)

View File

@ -25,7 +25,23 @@
#include "sys_fs.h"
#include "sys_spu.h"
// Check all flags known to be related to extended permissions (TODO)
// I think anything which has root flags implicitly has debug perm as well
// But I havn't confirmed it.
bool ps3_process_info_t::debug_or_root() const
{
return (ctrl_flags1 & (0xe << 28)) != 0;
}
bool ps3_process_info_t::has_root_perm() const
{
return (ctrl_flags1 & (0xc << 28)) != 0;
}
bool ps3_process_info_t::has_debug_perm() const
{
return (ctrl_flags1 & (0xa << 28)) != 0;
}
LOG_CHANNEL(sys_process);

View File

@ -1,5 +1,6 @@
#pragma once
#include "Crypto/unself.h"
#include "Emu/Memory/vm_ptr.h"
// Process Local Object Type
@ -40,6 +41,12 @@ struct ps3_process_info_t
{
u32 sdk_ver;
u32 ppc_seg;
SelfAdditionalInfo self_info;
u32 ctrl_flags1 = 0;
bool has_root_perm() const;
bool has_debug_perm() const;
bool debug_or_root() const;
};
extern ps3_process_info_t g_ps3_process_info;

View File

@ -13,6 +13,7 @@
#include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/RawSPUThread.h"
#include "sys_interrupt.h"
#include "sys_process.h"
#include "sys_mmapper.h"
#include "sys_event.h"
@ -409,7 +410,8 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
// TODO: max num value should be affected by sys_spu_initialize() settings
if (attr->nsize > 0x80 || !num || num > 6 || ((prio < 16 || prio > 255) && (attr->type != SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT && attr->type != SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)))
const s32 min_prio = g_ps3_process_info.has_root_perm() ? 0 : 16;
if (attr->nsize > 0x80 || !num || num > 6 || ((prio < min_prio || prio > 255) && (attr->type != SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT && attr->type != SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)))
{
return CELL_EINVAL;
}
@ -802,11 +804,6 @@ error_code sys_spu_thread_group_set_priority(ppu_thread& ppu, u32 id, s32 priori
sys_spu.trace("sys_spu_thread_group_set_priority(id=0x%x, priority=%d)", id, priority);
if (priority < 16 || priority > 255)
{
return CELL_EINVAL;
}
const auto group = idm::get<lv2_spu_group>(id);
if (!group)
@ -814,6 +811,11 @@ error_code sys_spu_thread_group_set_priority(ppu_thread& ppu, u32 id, s32 priori
return CELL_ESRCH;
}
if (priority < (g_ps3_process_info.has_root_perm() ? 0 : 16) || priority > 255)
{
return CELL_EINVAL;
}
if (group->type == SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT)
{
return CELL_EINVAL;

View File

@ -1,6 +1,7 @@
#include "stdafx.h"
#include "sys_ss.h"
#include "sys_process.h"
#include "Emu/Cell/PPUThread.h"
@ -64,6 +65,52 @@ error_code sys_ss_random_number_generator(u32 arg1, vm::ptr<void> buf, u64 size)
return CELL_OK;
}
error_code sys_ss_access_control_engine(u64 pkg_id, u64 a2, u64 a3)
{
sys_ss.todo("sys_ss_access_control_engine(pkg_id=0x%llx, a2=0x%llx, a3=0x%llx)", pkg_id, a2, a3);
const u64 authid = g_ps3_process_info.self_info.valid ?
g_ps3_process_info.self_info.app_info.authid : 0;
switch (pkg_id)
{
case 0x1:
{
if (!g_ps3_process_info.debug_or_root())
{
return CELL_ENOSYS;
}
if (!a2)
{
return CELL_ESRCH;
}
verify(HERE), a2 == process_getpid();
vm::_ref<u64>(vm::cast(a3)) = authid;
break;
}
case 0x2:
{
vm::_ref<u64>(vm::cast(a2)) = authid;
break;
}
case 0x3:
{
if (!g_ps3_process_info.debug_or_root())
{
return CELL_ENOSYS;
}
break;
}
default:
return 0x8001051du;
}
return CELL_OK;
}
s32 sys_ss_get_console_id(vm::ptr<u8> buf)
{
sys_ss.todo("sys_ss_get_console_id(buf=*0x%x)", buf);

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "Emu/Memory/vm_ptr.h"
#include "Emu/Cell/ErrorCodes.h"
@ -10,5 +10,6 @@ struct CellSsOpenPSID
};
error_code sys_ss_random_number_generator(u32 arg1, vm::ptr<void> buf, u64 size);
error_code sys_ss_access_control_engine(u64 pkg_id, u64 a2, u64 a3);
s32 sys_ss_get_console_id(vm::ptr<u8> buf);
s32 sys_ss_get_open_psid(vm::ptr<CellSsOpenPSID> ptr);

View File

@ -65,6 +65,15 @@ struct lv2_obj
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
private:
enum thread_cmd : s32
{
yield_cmd = INT32_MIN,
enqueue_cmd,
};
public:
// Find and remove the object from the container (deque or vector)
template <typename T, typename E>
static bool unqueue(std::deque<T*>& queue, const E& object)
@ -96,7 +105,7 @@ struct lv2_obj
return res;
}
u32 prio = -1;
s32 prio = 3071;
auto it = queue.cbegin();
for (auto found = it, end = queue.cend(); found != end; found++)
@ -120,7 +129,7 @@ private:
static void sleep_unlocked(cpu_thread&, u64 timeout);
// Schedule the thread
static void awake_unlocked(cpu_thread*, u32 prio = -1);
static void awake_unlocked(cpu_thread*, s32 prio = enqueue_cmd);
public:
static void sleep(cpu_thread& cpu, const u64 timeout = 0)
@ -130,7 +139,7 @@ public:
g_to_awake.clear();
}
static inline void awake(cpu_thread* const thread, const u32 prio = -1)
static inline void awake(cpu_thread* const thread, s32 prio = enqueue_cmd)
{
std::lock_guard lock(g_mutex);
awake_unlocked(thread, prio);
@ -139,7 +148,13 @@ public:
static void yield(cpu_thread& thread)
{
vm::temporary_unlock(thread);
awake(&thread, -4);
awake(&thread, yield_cmd);
}
static void set_priority(cpu_thread& thread, s32 prio)
{
verify(HERE), prio + 512u < 3712;
awake(&thread, prio);
}
static inline void awake_all()

View File

@ -10,6 +10,7 @@
#include "Emu/Cell/PPUAnalyser.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/Cell/RawSPUThread.h"
#include "Emu/Cell/lv2/sys_process.h"
#include "Emu/Cell/lv2/sys_memory.h"
#include "Emu/Cell/lv2/sys_sync.h"
#include "Emu/Cell/lv2/sys_prx.h"
@ -1481,7 +1482,7 @@ void Emulator::Load(const std::string& title_id, bool add_only, bool force_globa
elf_file.open(decrypted_path);
}
// Decrypt SELF
else if ((elf_file = decrypt_self(std::move(elf_file), klic.empty() ? nullptr : klic.data())))
else if ((elf_file = decrypt_self(std::move(elf_file), klic.empty() ? nullptr : klic.data(), &g_ps3_process_info.self_info)))
{
if (true)
{
@ -1498,6 +1499,10 @@ void Emulator::Load(const std::string& title_id, bool add_only, bool force_globa
}
}
}
else
{
g_ps3_process_info.self_info.valid = false;
}
if (!elf_file)
{