Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sys_fs: Limit NPDRM FDs to 16 #7945

Merged
merged 3 commits into from Apr 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions rpcs3/Crypto/unedat.h
Expand Up @@ -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
Expand Down
6 changes: 0 additions & 6 deletions rpcs3/Emu/Cell/Modules/cellFs.cpp
Expand Up @@ -863,12 +863,6 @@ s32 cellFsStReadWaitCallback(u32 fd, u64 size, vm::ptr<void(s32 xfd, u64 xsize)>

using fs_aio_cb_t = vm::ptr<void(vm::ptr<CellFsAio> xaio, s32 error, s32 xid, u64 size)>;

// temporarily
struct lv2_fs_mount_point
{
std::mutex mutex;
};

struct fs_aio_thread : ppu_thread
{
using ppu_thread::ppu_thread;
Expand Down
4 changes: 4 additions & 0 deletions rpcs3/Emu/Cell/Modules/cellSysCache.cpp
Expand Up @@ -28,6 +28,8 @@ void fmt_class_string<CellSysCacheError>::format(std::string& out, u64 arg)
});
}

extern lv2_fs_mount_point g_mp_sys_dev_hdd1;

struct syscache_info
{
const std::string cache_root = Emu.GetHdd1Dir() + "/caches/";
Expand Down Expand Up @@ -77,6 +79,8 @@ struct syscache_info
// Poison opened files in /dev_hdd1 to return CELL_EIO on access
if (remove_root)
{
std::lock_guard lock(g_mp_sys_dev_hdd1.mutex);

idm::select<lv2_fs_object, lv2_file>([](u32 id, lv2_file& file)
{
if (std::memcmp("/dev_hdd1", file.name.data(), 9) == 0)
Expand Down
64 changes: 52 additions & 12 deletions rpcs3/Emu/Cell/lv2/sys_fs.cpp
Expand Up @@ -10,15 +10,6 @@

LOG_CHANNEL(sys_fs);

struct lv2_fs_mount_point
{
const u32 sector_size = 512;
const u32 block_size = 4096;
const bs_t<lv2_mp_flag> flags{};

shared_mutex mutex;
};

lv2_fs_mount_point g_mp_sys_dev_hdd0;
lv2_fs_mount_point g_mp_sys_dev_hdd1{512, 32768, lv2_mp_flag::no_uid_gid};
lv2_fs_mount_point g_mp_sys_dev_usb{512, 4096, lv2_mp_flag::no_uid_gid};
Expand Down Expand Up @@ -485,7 +476,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;
Expand Down Expand Up @@ -594,7 +620,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)
{
Expand Down Expand Up @@ -1236,7 +1268,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 = *file, &stream = stream]() -> 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;
Expand Down
25 changes: 21 additions & 4 deletions rpcs3/Emu/Cell/lv2/sys_fs.h
Expand Up @@ -3,6 +3,7 @@
#include "Emu/Memory/vm_ptr.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Utilities/File.h"
#include "Utilities/mutex.h"

#include <string>

Expand Down Expand Up @@ -121,8 +122,6 @@ struct FsMselfEntry
u8 m_reserve[16];
};

struct lv2_fs_mount_point;

enum class lv2_mp_flag
{
read_only,
Expand All @@ -132,6 +131,21 @@ enum class lv2_mp_flag
__bitset_enum_max
};

enum class lv2_file_type
{
regular = 0,
npdrm,
};

struct lv2_fs_mount_point
{
const u32 sector_size = 512;
const u32 block_size = 4096;
const bs_t<lv2_mp_flag> flags{};

shared_mutex mutex;
};

struct lv2_fs_object
{
using id_type = lv2_fs_object;
Expand Down Expand Up @@ -174,23 +188,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)
{
}

Expand Down