From f00a85530022599f580992d3537dbaaac45d0004 Mon Sep 17 00:00:00 2001 From: fogydes Date: Sun, 1 Nov 2026 21:15:59 +0530 Subject: [PATCH] fix(libSceSysUtil): return EFAULT from sceSysUtilSendSystemNotificationWithText for an unreadable message pointer --- core/libs/prx/libSceSysUtil/Export.cpp | 12 ++++++++++-- core/libs/tests/GuestSysUtilNotification.cpp | 2 ++ docs/dev/debt/libSceSysUtil.md | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/core/libs/prx/libSceSysUtil/Export.cpp b/core/libs/prx/libSceSysUtil/Export.cpp index a053ac386f..8e5a63dafc 100644 --- a/core/libs/prx/libSceSysUtil/Export.cpp +++ b/core/libs/prx/libSceSysUtil/Export.cpp @@ -5,6 +5,7 @@ #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" +#include "prx/libkernel/KernelErrors.hpp" #include "prx/libkernel/include/Api.hpp" namespace { @@ -25,8 +26,15 @@ int APS5_VABI sceSysUtilSendSystemNotificationWithText(int32_t type, const char* std::memcpy(request.data() + TypeOffset, &type, sizeof(type)); if (message != nullptr) { std::size_t length = 0; - while (length < TextLimit && message[length] != '\0') ++length; - std::memcpy(request.data() + TextOffset, message, length); + char c = 0; + while (length < TextLimit) { + if (!GuestCopyIn_nid_no_patch(&c, message + length, sizeof(c))) { + return SCE_KERNEL_ERROR_EFAULT; + } + if (c == '\0') break; + request[TextOffset + length] = static_cast(c); + ++length; + } } return sceKernelSendNotificationRequest(0, request.data(), request.size(), 0); } diff --git a/core/libs/tests/GuestSysUtilNotification.cpp b/core/libs/tests/GuestSysUtilNotification.cpp index aa60f22ae7..37afa71a77 100644 --- a/core/libs/tests/GuestSysUtilNotification.cpp +++ b/core/libs/tests/GuestSysUtilNotification.cpp @@ -90,6 +90,8 @@ int main() { Require(hello == 0, "a text notification was not sent"); Require(empty == 0, "a null message was not sent as an empty text"); Require(truncated == 0, "a long message was not sent"); + Require(sceSysUtilSendSystemNotificationWithText(0, reinterpret_cast(0x10)) == static_cast(0x8002000Eu), "an unreadable message pointer did not return EFAULT"); + Require(sceSysUtilSendSystemNotificationWithText(0, reinterpret_cast(~std::uintptr_t{0xfff})) == static_cast(0x8002000Eu), "an unreadable message pointer did not return EFAULT"); const std::string expected = "[notification] hello\n[notification] \n[notification] " + longText.substr(0, 179) + "\n"; if (output != expected) { std::fprintf(stderr, "notification output was:\n%s", output.c_str()); diff --git a/docs/dev/debt/libSceSysUtil.md b/docs/dev/debt/libSceSysUtil.md index 614a09c03b..dd8080ae42 100644 --- a/docs/dev/debt/libSceSysUtil.md +++ b/docs/dev/debt/libSceSysUtil.md @@ -9,4 +9,4 @@ ### Functional -- [sceSysUtilSendSystemNotificationWithText](../../../core/libs/prx/libSceSysUtil/Export.cpp) (libSceSysUtil) - follows @BunnyFl's [firmware 13.42 run](https://github.com/boykopovar/AnyPS5/pull/9081#issuecomment-6418015178) of the export, under an emulator with `sceKernelSendNotificationRequest` stubbed, not on a console. `(int32_t type, const char* message)` checks nothing itself: it builds a 0xc30-byte request with kind 5 in the first dword, `type` at +0xc and the message at +0x2d, cut to 179 characters and left empty for a null message, and returns what `sceKernelSendNotificationRequest(0, request, 0xc30, 0)` returns. The run did not report the other bytes of the request; they are zero here. There is no system UI here, so the text goes to the host's standard error; what the console shows for each `type` is decided outside the library and is not known. +- [sceSysUtilSendSystemNotificationWithText](../../../core/libs/prx/libSceSysUtil/Export.cpp) (libSceSysUtil) - follows @BunnyFl's [firmware 13.42 run](https://github.com/boykopovar/AnyPS5/pull/9081#issuecomment-6418015178) under an emulator with `sceKernelSendNotificationRequest` stubbed, not on console. Builds a 0xc30-byte request with kind 5 in the first dword, `type` at +0xc and the message at +0x2d, cut to 179 characters and empty for null, returning what `sceKernelSendNotificationRequest(0, request, 0xc30, 0)` returns. An unreadable message pointer returns `SCE_KERNEL_ERROR_EFAULT` (`0x8002000e`) as a host-safety fallback; console invalid-pointer behaviour was not measured. Other request bytes were not reported and are zero. Lacking system UI, text goes to standard error; console display per `type` is unverified.