[VFS] Fix some security issues in StfsContainerDevice code
This commit is contained in:
parent
1005651855
commit
e07b0ed2ad
|
@ -62,14 +62,13 @@ StfsContainerDevice::~StfsContainerDevice() = default;
|
||||||
bool StfsContainerDevice::Initialize() {
|
bool StfsContainerDevice::Initialize() {
|
||||||
// Resolve a valid STFS file if a directory is given.
|
// Resolve a valid STFS file if a directory is given.
|
||||||
if (filesystem::IsFolder(local_path_) && !ResolveFromFolder(local_path_)) {
|
if (filesystem::IsFolder(local_path_) && !ResolveFromFolder(local_path_)) {
|
||||||
XELOGE("Could not resolve an STFS container given path %s",
|
XELOGE("Could not resolve an STFS container given path %ls",
|
||||||
xe::to_string(local_path_).c_str());
|
local_path_.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!filesystem::PathExists(local_path_)) {
|
if (!filesystem::PathExists(local_path_)) {
|
||||||
XELOGE("Path to STFS container does not exist: %s",
|
XELOGE("Path to STFS container does not exist: %ls", local_path_.c_str());
|
||||||
xe::to_string(local_path_).c_str());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,10 +93,15 @@ bool StfsContainerDevice::Initialize() {
|
||||||
|
|
||||||
StfsContainerDevice::Error StfsContainerDevice::MapFiles() {
|
StfsContainerDevice::Error StfsContainerDevice::MapFiles() {
|
||||||
// Map the file containing the STFS Header and read it.
|
// Map the file containing the STFS Header and read it.
|
||||||
XELOGI("Mapping STFS Header File: %s", xe::to_string(local_path_).c_str());
|
XELOGI("Mapping STFS Header file: %ls", local_path_.c_str());
|
||||||
auto header_map = MappedMemory::Open(local_path_, MappedMemory::Mode::kRead);
|
auto header_map = MappedMemory::Open(local_path_, MappedMemory::Mode::kRead);
|
||||||
|
if (!header_map) {
|
||||||
|
XELOGE("Error mapping STFS Header file.");
|
||||||
|
return Error::kErrorReadError;
|
||||||
|
}
|
||||||
|
|
||||||
auto header_result = ReadHeaderAndVerify(header_map->data());
|
auto header_result =
|
||||||
|
ReadHeaderAndVerify(header_map->data(), header_map->size());
|
||||||
if (header_result != Error::kSuccess) {
|
if (header_result != Error::kSuccess) {
|
||||||
XELOGE("Error reading STFS Header: %d", header_result);
|
XELOGE("Error reading STFS Header: %d", header_result);
|
||||||
return header_result;
|
return header_result;
|
||||||
|
@ -116,7 +120,7 @@ StfsContainerDevice::Error StfsContainerDevice::MapFiles() {
|
||||||
// the files in the .data folder and can discard the header.
|
// the files in the .data folder and can discard the header.
|
||||||
auto data_fragment_path = local_path_ + L".data";
|
auto data_fragment_path = local_path_ + L".data";
|
||||||
if (!filesystem::PathExists(data_fragment_path)) {
|
if (!filesystem::PathExists(data_fragment_path)) {
|
||||||
XELOGE("STFS container is multi-file, but path %s does not exist.",
|
XELOGE("STFS container is multi-file, but path %ls does not exist.",
|
||||||
xe::to_string(data_fragment_path).c_str());
|
xe::to_string(data_fragment_path).c_str());
|
||||||
return Error::kErrorFileMismatch;
|
return Error::kErrorFileMismatch;
|
||||||
}
|
}
|
||||||
|
@ -138,6 +142,11 @@ StfsContainerDevice::Error StfsContainerDevice::MapFiles() {
|
||||||
auto file = fragment_files.at(i);
|
auto file = fragment_files.at(i);
|
||||||
auto path = xe::join_paths(file.path, file.name);
|
auto path = xe::join_paths(file.path, file.name);
|
||||||
auto data = MappedMemory::Open(path, MappedMemory::Mode::kRead);
|
auto data = MappedMemory::Open(path, MappedMemory::Mode::kRead);
|
||||||
|
if (!data) {
|
||||||
|
XELOGI("Failed to map SVOD file %ls.", path.c_str());
|
||||||
|
mmap_.clear();
|
||||||
|
return Error::kErrorReadError;
|
||||||
|
}
|
||||||
mmap_.emplace(std::make_pair(i, std::move(data)));
|
mmap_.emplace(std::make_pair(i, std::move(data)));
|
||||||
}
|
}
|
||||||
XELOGI("SVOD successfully mapped %d files.", fragment_files.size());
|
XELOGI("SVOD successfully mapped %d files.", fragment_files.size());
|
||||||
|
@ -170,18 +179,40 @@ Entry* StfsContainerDevice::ResolvePath(const std::string& path) {
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
StfsContainerDevice::Error StfsContainerDevice::ReadHeaderAndVerify(
|
StfsContainerDevice::Error StfsContainerDevice::ReadPackageType(
|
||||||
const uint8_t* map_ptr) {
|
const uint8_t* map_ptr, size_t map_size,
|
||||||
// Check signature.
|
StfsPackageType* package_type_out) {
|
||||||
|
if (map_size < 4) {
|
||||||
|
return Error::kErrorFileMismatch;
|
||||||
|
}
|
||||||
if (memcmp(map_ptr, "LIVE", 4) == 0) {
|
if (memcmp(map_ptr, "LIVE", 4) == 0) {
|
||||||
package_type_ = StfsPackageType::kLive;
|
if (package_type_out) {
|
||||||
} else if (memcmp(map_ptr, "PIRS", 4) == 0) {
|
*package_type_out = StfsPackageType::kLive;
|
||||||
package_type_ = StfsPackageType::kPirs;
|
}
|
||||||
} else if (memcmp(map_ptr, "CON ", 4) == 0) {
|
return Error::kSuccess;
|
||||||
package_type_ = StfsPackageType::kCon;
|
}
|
||||||
} else {
|
if (memcmp(map_ptr, "PIRS", 4) == 0) {
|
||||||
|
if (package_type_out) {
|
||||||
|
*package_type_out = StfsPackageType::kPirs;
|
||||||
|
}
|
||||||
|
return Error::kSuccess;
|
||||||
|
}
|
||||||
|
if (memcmp(map_ptr, "CON ", 4) == 0) {
|
||||||
|
if (package_type_out) {
|
||||||
|
*package_type_out = StfsPackageType::kCon;
|
||||||
|
}
|
||||||
|
return Error::kSuccess;
|
||||||
|
}
|
||||||
// Unexpected format.
|
// Unexpected format.
|
||||||
return Error::kErrorFileMismatch;
|
return Error::kErrorFileMismatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
StfsContainerDevice::Error StfsContainerDevice::ReadHeaderAndVerify(
|
||||||
|
const uint8_t* map_ptr, size_t map_size) {
|
||||||
|
// Check signature.
|
||||||
|
auto type_result = ReadPackageType(map_ptr, map_size, &package_type_);
|
||||||
|
if (type_result != Error::kSuccess) {
|
||||||
|
return type_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read header.
|
// Read header.
|
||||||
|
@ -708,13 +739,6 @@ bool StfsHeader::Read(const uint8_t* p) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* StfsContainerDevice::ReadMagic(const std::wstring& path) {
|
|
||||||
auto map = MappedMemory::Open(path, MappedMemory::Mode::kRead, 0, 4);
|
|
||||||
auto magic_data = xe::load<uint32_t>(map->data());
|
|
||||||
auto magic_bytes = static_cast<char*>(static_cast<void*>(&magic_data));
|
|
||||||
return std::move(magic_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StfsContainerDevice::ResolveFromFolder(const std::wstring& path) {
|
bool StfsContainerDevice::ResolveFromFolder(const std::wstring& path) {
|
||||||
// Scan through folders until a file with magic is found
|
// Scan through folders until a file with magic is found
|
||||||
std::queue<filesystem::FileInfo> queue;
|
std::queue<filesystem::FileInfo> queue;
|
||||||
|
@ -736,12 +760,11 @@ bool StfsContainerDevice::ResolveFromFolder(const std::wstring& path) {
|
||||||
} else {
|
} else {
|
||||||
// Try to read the file's magic
|
// Try to read the file's magic
|
||||||
auto path = xe::join_paths(current_file.path, current_file.name);
|
auto path = xe::join_paths(current_file.path, current_file.name);
|
||||||
auto magic = ReadMagic(path);
|
auto map = MappedMemory::Open(path, MappedMemory::Mode::kRead, 0, 4);
|
||||||
|
if (map && ReadPackageType(map->data(), map->size(), nullptr) ==
|
||||||
if (memcmp(magic, "LIVE", 4) == 0 || memcmp(magic, "PIRS", 4) == 0 ||
|
Error::kSuccess) {
|
||||||
memcmp(magic, "CON ", 4) == 0) {
|
|
||||||
local_path_ = xe::join_paths(current_file.path, current_file.name);
|
local_path_ = xe::join_paths(current_file.path, current_file.name);
|
||||||
XELOGI("STFS Package found: %s", xe::to_string(local_path_).c_str());
|
XELOGI("STFS Package found: %ls", local_path_.c_str());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,11 +197,12 @@ class StfsContainerDevice : public Device {
|
||||||
|
|
||||||
const uint32_t kSTFSHashSpacing = 170;
|
const uint32_t kSTFSHashSpacing = 170;
|
||||||
|
|
||||||
const char* ReadMagic(const std::wstring& path);
|
|
||||||
bool ResolveFromFolder(const std::wstring& path);
|
bool ResolveFromFolder(const std::wstring& path);
|
||||||
|
|
||||||
Error MapFiles();
|
Error MapFiles();
|
||||||
Error ReadHeaderAndVerify(const uint8_t* map_ptr);
|
static Error ReadPackageType(const uint8_t* map_ptr, size_t map_size,
|
||||||
|
StfsPackageType* package_type_out);
|
||||||
|
Error ReadHeaderAndVerify(const uint8_t* map_ptr, size_t map_size);
|
||||||
|
|
||||||
Error ReadSVOD();
|
Error ReadSVOD();
|
||||||
Error ReadEntrySVOD(uint32_t sector, uint32_t ordinal,
|
Error ReadEntrySVOD(uint32_t sector, uint32_t ordinal,
|
||||||
|
|
Loading…
Reference in New Issue