sys_fs: Limit NPDRM FDs to 16

Co-Authored-By: Silent <cookieplmonster@users.noreply.github.com>
This commit is contained in:
Eladash 2020-04-04 17:11:21 +03:00 committed by Ani
parent dd8a3eaac5
commit a178374052
3 changed files with 64 additions and 5 deletions

View File

@ -18,6 +18,7 @@ struct loaded_npdrm_keys
{
std::array<u8, 0x10> devKlic{};
std::array<u8, 0x10> rifKey{};
atomic_t<u32> npdrm_fds{0};
};
struct NPD_HEADER

View File

@ -485,7 +485,42 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
return {error, path};
}
if (const u32 id = idm::make<lv2_fs_object, lv2_file>(ppath, std::move(file), mode, flags))
lv2_file_type type = lv2_file_type::regular;
if (size == 8)
{
// see lv2_file::open
switch (vm::read64(arg.addr()))
{
case 0x18000000010:
case 0x2:
{
type = lv2_file_type::npdrm;
sys_fs.warning("sys_fs_open(): NPDRM detected");
break;
}
default:
break;
}
}
if (type == lv2_file_type::npdrm)
{
if (const u32 id = idm::import<lv2_fs_object, lv2_file>([&ppath = ppath, &file = file, mode, flags]() -> std::shared_ptr<lv2_file>
{
if (!g_fxo->get<loaded_npdrm_keys>()->npdrm_fds.try_inc(16))
{
return nullptr;
}
return std::make_shared<lv2_file>(ppath, std::move(file), mode, flags, lv2_file_type::npdrm);
}))
{
*fd = id;
return CELL_OK;
}
}
else if (const u32 id = idm::make<lv2_fs_object, lv2_file>(ppath, std::move(file), mode, flags))
{
*fd = id;
return CELL_OK;
@ -594,7 +629,13 @@ error_code sys_fs_close(ppu_thread& ppu, u32 fd)
sys_fs.trace("sys_fs_close(fd=%d)", fd);
const auto file = idm::withdraw<lv2_fs_object, lv2_file>(fd);
const auto file = idm::withdraw<lv2_fs_object, lv2_file>(fd, [](lv2_file& file)
{
if (file.type == lv2_file_type::npdrm)
{
g_fxo->get<loaded_npdrm_keys>()->npdrm_fds--;
}
});
if (!file)
{
@ -1236,7 +1277,15 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
fs::file stream;
stream.reset(std::move(sdata_file));
if (const u32 id = idm::make<lv2_fs_object, lv2_file>(*file, std::move(stream), file->mode, file->flags))
if (const u32 id = idm::import<lv2_fs_object, lv2_file>([&]() -> std::shared_ptr<lv2_file>
{
if (!g_fxo->get<loaded_npdrm_keys>()->npdrm_fds.try_inc(16))
{
return nullptr;
}
return std::make_shared<lv2_file>(*file, std::move(stream), file->mode, file->flags, lv2_file_type::npdrm);
}))
{
arg->out_code = CELL_OK;
arg->out_fd = id;

View File

@ -132,6 +132,12 @@ enum class lv2_mp_flag
__bitset_enum_max
};
enum class lv2_file_type
{
regular = 0,
npdrm,
};
struct lv2_fs_object
{
using id_type = lv2_fs_object;
@ -174,23 +180,26 @@ struct lv2_file final : lv2_fs_object
const fs::file file;
const s32 mode;
const s32 flags;
const lv2_file_type type;
// Stream lock
atomic_t<u32> lock{0};
lv2_file(std::string_view filename, fs::file&& file, s32 mode, s32 flags)
lv2_file(std::string_view filename, fs::file&& file, s32 mode, s32 flags, lv2_file_type type = {})
: lv2_fs_object(lv2_fs_object::get_mp(filename), filename)
, file(std::move(file))
, mode(mode)
, flags(flags)
, type(type)
{
}
lv2_file(const lv2_file& host, fs::file&& file, s32 mode, s32 flags)
lv2_file(const lv2_file& host, fs::file&& file, s32 mode, s32 flags, lv2_file_type type = {})
: lv2_fs_object(host.mp, host.name.data())
, file(std::move(file))
, mode(mode)
, flags(flags)
, type(type)
{
}