Skip to content

Commit c52d447

Browse files
elad335Nekotekina
authored andcommitted
sys_fs: Place all path-format checks upfront, implement more checks
1 parent 524b065 commit c52d447

File tree

1 file changed

+98
-46
lines changed

1 file changed

+98
-46
lines changed

rpcs3/Emu/Cell/lv2/sys_fs.cpp

+98-46
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,43 @@ fs::file lv2_file::make_view(const std::shared_ptr<lv2_file>& _file, u64 offset)
311311
return result;
312312
}
313313

314+
std::pair<CellError, std::string_view> translate_to_sv(vm::cptr<char> ptr)
315+
{
316+
const u32 addr = ptr.addr();
317+
318+
if (!vm::check_addr(addr, vm::page_readable))
319+
{
320+
return {CELL_EFAULT, {}};
321+
}
322+
323+
const usz remained_page_memory = (~addr % 4096) + 1;
324+
325+
constexpr usz max_length = CELL_FS_MAX_FS_PATH_LENGTH + 1;
326+
327+
const usz target_memory_span_size = std::min<usz>(max_length, vm::check_addr(addr + 4096, vm::page_readable) ? max_length : remained_page_memory);
328+
329+
std::string_view path{ptr.get_ptr(), target_memory_span_size};
330+
path = path.substr(0, path.find_first_of('\0'));
331+
332+
if (path.size() == max_length)
333+
{
334+
return {CELL_ENAMETOOLONG, {}};
335+
}
336+
337+
if (path.size() == target_memory_span_size)
338+
{
339+
// Null character lookup has ended whilst pointing at invalid memory
340+
return {CELL_EFAULT, path};
341+
}
342+
343+
if (!path.starts_with("/"sv))
344+
{
345+
return {CELL_ENOENT, path};
346+
}
347+
348+
return {{}, path};
349+
}
350+
314351
error_code sys_fs_test(ppu_thread&, u32 arg1, u32 arg2, vm::ptr<u32> arg3, u32 arg4, vm::ptr<char> buf, u32 buf_size)
315352
{
316353
sys_fs.trace("sys_fs_test(arg1=0x%x, arg2=0x%x, arg3=*0x%x, arg4=0x%x, buf=*0x%x, buf_size=0x%x)", arg1, arg2, arg3, arg4, buf, buf_size);
@@ -600,10 +637,14 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
600637

601638
sys_fs.warning("sys_fs_open(path=%s, flags=%#o, fd=*0x%x, mode=%#o, arg=*0x%x, size=0x%llx)", path, flags, fd, mode, arg, size);
602639

603-
if (!path)
604-
return CELL_EFAULT;
640+
const auto [path_error, vpath] = translate_to_sv(path);
605641

606-
auto [error, ppath, real, file, type] = lv2_file::open(path.get_ptr(), flags, mode, arg.get_ptr(), size);
642+
if (path_error)
643+
{
644+
return {path_error, vpath};
645+
}
646+
647+
auto [error, ppath, real, file, type] = lv2_file::open(vpath, flags, mode, arg.get_ptr(), size);
607648

608649
if (error)
609650
{
@@ -849,15 +890,15 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u32> fd)
849890

850891
sys_fs.warning("sys_fs_opendir(path=%s, fd=*0x%x)", path, fd);
851892

852-
if (!path)
853-
return CELL_EFAULT;
893+
const auto [path_error, vpath] = translate_to_sv(path);
854894

855-
if (!path[0])
856-
return CELL_ENOENT;
895+
if (path_error)
896+
{
897+
return {path_error, vpath};
898+
}
857899

858900
std::string processed_path;
859901
std::vector<std::string> ext;
860-
const std::string_view vpath = path.get_ptr();
861902
const std::string local_path = vfs::get(vpath, &ext, &processed_path);
862903

863904
processed_path += "/";
@@ -1018,13 +1059,13 @@ error_code sys_fs_stat(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<CellFsStat>
10181059

10191060
sys_fs.warning("sys_fs_stat(path=%s, sb=*0x%x)", path, sb);
10201061

1021-
if (!path)
1022-
return CELL_EFAULT;
1062+
const auto [path_error, vpath] = translate_to_sv(path);
10231063

1024-
if (!path[0])
1025-
return CELL_ENOENT;
1064+
if (path_error)
1065+
{
1066+
return {path_error, vpath};
1067+
}
10261068

1027-
const std::string_view vpath = path.get_ptr();
10281069
const std::string local_path = vfs::get(vpath);
10291070

10301071
const auto mp = lv2_fs_object::get_mp(vpath);
@@ -1168,13 +1209,13 @@ error_code sys_fs_mkdir(ppu_thread& ppu, vm::cptr<char> path, s32 mode)
11681209

11691210
sys_fs.warning("sys_fs_mkdir(path=%s, mode=%#o)", path, mode);
11701211

1171-
if (!path)
1172-
return CELL_EFAULT;
1212+
const auto [path_error, vpath] = translate_to_sv(path);
11731213

1174-
if (!path[0])
1175-
return CELL_ENOENT;
1214+
if (path_error)
1215+
{
1216+
return {path_error, vpath};
1217+
}
11761218

1177-
const std::string_view vpath = path.get_ptr();
11781219
const std::string local_path = vfs::get(vpath);
11791220

11801221
const auto mp = lv2_fs_object::get_mp(vpath);
@@ -1219,10 +1260,21 @@ error_code sys_fs_rename(ppu_thread& ppu, vm::cptr<char> from, vm::cptr<char> to
12191260

12201261
sys_fs.warning("sys_fs_rename(from=%s, to=%s)", from, to);
12211262

1222-
const std::string_view vfrom = from.get_ptr();
1223-
const std::string local_from = vfs::get(vfrom);
1263+
const auto [from_error, vfrom] = translate_to_sv(from);
1264+
1265+
if (from_error)
1266+
{
1267+
return {from_error, vfrom};
1268+
}
12241269

1225-
const std::string_view vto = to.get_ptr();
1270+
const auto [to_error, vto] = translate_to_sv(to);
1271+
1272+
if (to_error)
1273+
{
1274+
return {to_error, vto};
1275+
}
1276+
1277+
const std::string local_from = vfs::get(vfrom);
12261278
const std::string local_to = vfs::get(vto);
12271279

12281280
const auto mp = lv2_fs_object::get_mp(vfrom);
@@ -1274,13 +1326,13 @@ error_code sys_fs_rmdir(ppu_thread& ppu, vm::cptr<char> path)
12741326

12751327
sys_fs.warning("sys_fs_rmdir(path=%s)", path);
12761328

1277-
if (!path)
1278-
return CELL_EFAULT;
1329+
const auto [path_error, vpath] = translate_to_sv(path);
12791330

1280-
if (!path[0])
1281-
return CELL_ENOENT;
1331+
if (path_error)
1332+
{
1333+
return {path_error, vpath};
1334+
}
12821335

1283-
const std::string_view vpath = path.get_ptr();
12841336
const std::string local_path = vfs::get(vpath);
12851337

12861338
const auto mp = lv2_fs_object::get_mp(vpath);
@@ -1325,13 +1377,13 @@ error_code sys_fs_unlink(ppu_thread& ppu, vm::cptr<char> path)
13251377

13261378
sys_fs.warning("sys_fs_unlink(path=%s)", path);
13271379

1328-
if (!path)
1329-
return CELL_EFAULT;
1380+
const auto [path_error, vpath] = translate_to_sv(path);
13301381

1331-
if (!path[0])
1332-
return CELL_ENOENT;
1382+
if (path_error)
1383+
{
1384+
return {path_error, vpath};
1385+
}
13331386

1334-
const std::string_view vpath = path.get_ptr();
13351387
const std::string local_path = vfs::get(vpath);
13361388

13371389
const auto mp = lv2_fs_object::get_mp(vpath);
@@ -2002,13 +2054,13 @@ error_code sys_fs_get_block_size(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u
20022054

20032055
sys_fs.warning("sys_fs_get_block_size(path=%s, sector_size=*0x%x, block_size=*0x%x, arg4=*0x%x)", path, sector_size, block_size, arg4);
20042056

2005-
if (!path)
2006-
return CELL_EFAULT;
2057+
const auto [path_error, vpath] = translate_to_sv(path);
20072058

2008-
if (!path[0])
2009-
return CELL_ENOENT;
2059+
if (path_error)
2060+
{
2061+
return {path_error, vpath};
2062+
}
20102063

2011-
const std::string_view vpath = path.get_ptr();
20122064
const std::string local_path = vfs::get(vpath);
20132065

20142066
if (vpath.find_first_not_of('/') == umax)
@@ -2056,13 +2108,13 @@ error_code sys_fs_truncate(ppu_thread& ppu, vm::cptr<char> path, u64 size)
20562108

20572109
sys_fs.warning("sys_fs_truncate(path=%s, size=0x%llx)", path, size);
20582110

2059-
if (!path)
2060-
return CELL_EFAULT;
2111+
const auto [path_error, vpath] = translate_to_sv(path);
20612112

2062-
if (!path[0])
2063-
return CELL_ENOENT;
2113+
if (path_error)
2114+
{
2115+
return {path_error, vpath};
2116+
}
20642117

2065-
const std::string_view vpath = path.get_ptr();
20662118
const std::string local_path = vfs::get(vpath);
20672119

20682120
const auto mp = lv2_fs_object::get_mp(vpath);
@@ -2249,13 +2301,13 @@ error_code sys_fs_utime(ppu_thread& ppu, vm::cptr<char> path, vm::cptr<CellFsUti
22492301
sys_fs.warning("sys_fs_utime(path=%s, timep=*0x%x)", path, timep);
22502302
sys_fs.warning("** actime=%u, modtime=%u", timep->actime, timep->modtime);
22512303

2252-
if (!path)
2253-
return CELL_EFAULT;
2304+
const auto [path_error, vpath] = translate_to_sv(path);
22542305

2255-
if (!path[0])
2256-
return CELL_ENOENT;
2306+
if (path_error)
2307+
{
2308+
return {path_error, vpath};
2309+
}
22572310

2258-
const std::string_view vpath = path.get_ptr();
22592311
const std::string local_path = vfs::get(vpath);
22602312

22612313
const auto mp = lv2_fs_object::get_mp(vpath);

0 commit comments

Comments
 (0)