sys_fs: Improved get_device_root() path identifying security

This commit is contained in:
brian218 2024-01-08 07:52:28 +08:00 committed by Megamouse
parent a269ae7e30
commit 6548e3f7d0
2 changed files with 16 additions and 4 deletions

View File

@ -258,13 +258,15 @@ std::string lv2_fs_object::get_normalized_path(std::string_view path)
return normalized_path.empty() ? "/" : normalized_path;
}
std::string_view lv2_fs_object::get_device_root(std::string_view path)
std::string lv2_fs_object::get_device_root(std::string_view filename)
{
std::string path = get_normalized_path(filename); // Prevent getting fooled by ".." trick such as "/dev_usb000/../dev_flash"
if (const auto first = path.find_first_not_of("/"sv); first != umax)
{
if (const auto pos = path.substr(first).find_first_of("/"sv); pos != umax)
path = path.substr(0, first + pos);
path.remove_prefix(std::max<usz>(0, first - 1)); // Remove duplicate leading '/' while keeping only one
path = path.substr(std::max<std::make_signed_t<usz>>(0, first - 1)); // Remove duplicate leading '/' while keeping only one
}
else
{
@ -283,7 +285,7 @@ lv2_fs_mount_point* lv2_fs_object::get_mp(std::string_view filename, std::string
filename.remove_prefix(cell_fs_path.size());
const bool is_path = filename.starts_with("/"sv);
std::string mp_name = std::string(is_path ? get_device_root(filename) : filename);
std::string mp_name = is_path ? get_device_root(filename) : std::string(filename);
const auto check_mp = [&]()
{
@ -2035,6 +2037,16 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
return CELL_OK;
}
case 0xc0000003: // cellFsUtilitySetFakeSize
{
break;
}
case 0xc0000004: // cellFsUtilityGetFakeSize
{
break;
}
case 0xc0000006: // Unknown
{
const auto arg = vm::static_ptr_cast<lv2_file_c0000006>(_arg);

View File

@ -250,7 +250,7 @@ public:
static std::string get_normalized_path(std::string_view path);
// Get the device's root path (e.g. "/dev_hdd0") from a given path
static std::string_view get_device_root(std::string_view path);
static std::string get_device_root(std::string_view filename);
// Filename can be either a path starting with '/' or a CELL_FS device name
// This should be used only when handling devices that are not mounted