Skip to content

Commit

Permalink
sys_fs: Limit NPDRM FDs to 16
Browse files Browse the repository at this point in the history
Co-Authored-By: Silent <cookieplmonster@users.noreply.github.com>
  • Loading branch information
elad335 and CookiePLMonster committed Apr 4, 2020
1 parent 63080c2 commit 06e71cc
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 5 deletions.
56 changes: 53 additions & 3 deletions rpcs3/Emu/Cell/lv2/sys_fs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ lv2_fs_mount_point g_mp_sys_app_home{512, 512, lv2_mp_flag::strict_get_block_siz
lv2_fs_mount_point g_mp_sys_host_root{512, 512, lv2_mp_flag::strict_get_block_size + lv2_mp_flag::no_uid_gid};
lv2_fs_mount_point g_mp_sys_dev_flash{512, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid};

DECLARE(lv2_file::npdrm_ctr){0};

bool verify_mself(const fs::file& mself_file)
{
FsMselfHeader mself_header;
Expand Down Expand Up @@ -485,7 +487,40 @@ 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 = NORMAL_FD;

if (size == 8)
{
// see sys_fs_open
switch (vm::read64(arg.addr()))
{
case 0x18000000010:
case 0x2:
{
type = NPDRM_FD;
sys_fs.warning("sys_fs_open(): NPDRM detected");
break;
}
}
}

if (type == NPDRM_FD)
{
if (const u32 id = idm::import<lv2_fs_object, lv2_file>([ppath = std::move(ppath), file = std::move(file), mode, flags]() -> std::shared_ptr<lv2_file>
{
if (!lv2_file::npdrm_ctr.try_inc(16))
{
return nullptr;
}

return std::make_shared<lv2_file>(ppath, std::move(file), mode, flags, NPDRM_FD);
}))
{
*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;
Expand Down Expand Up @@ -594,7 +629,14 @@ 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 == NPDRM_FD)
{
file.npdrm_closed = true;
lv2_file::npdrm_ctr--;
}
});

if (!file)
{
Expand Down Expand Up @@ -1236,7 +1278,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>([file = std::move(*file), stream = std::move(stream), mode = file->mode, flags = file->flags]() -> std::shared_ptr<lv2_file>
{
if (!lv2_file::npdrm_ctr.try_inc(16))
{
return nullptr;
}

return std::make_shared<lv2_file>(file, std::move(stream), mode, flags, NPDRM_FD);
}))
{
arg->out_code = CELL_OK;
arg->out_fd = id;
Expand Down
25 changes: 23 additions & 2 deletions rpcs3/Emu/Cell/lv2/sys_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ enum class lv2_mp_flag
__bitset_enum_max
};

enum lv2_file_type : u32
{
NORMAL_FD,
NPDRM_FD,
};

struct lv2_fs_object
{
using id_type = lv2_fs_object;
Expand Down Expand Up @@ -174,26 +180,41 @@ struct lv2_file final : lv2_fs_object
const fs::file file;
const s32 mode;
const s32 flags;
const lv2_file_type type;
atomic_t<bool> npdrm_closed = false;

static atomic_t<u32> npdrm_ctr;

// 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 = NORMAL_FD)
: 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 = NORMAL_FD)
: lv2_fs_object(host.mp, host.name.data())
, file(std::move(file))
, mode(mode)
, flags(flags)
, type(type)
{
}

~lv2_file()
{
if (type == NPDRM_FD && !npdrm_closed)
{
// Forced alternative cleanup
npdrm_ctr--;
}
}

struct open_result_t
{
CellError error;
Expand Down

0 comments on commit 06e71cc

Please sign in to comment.