Skip to content

fix(libSceUserService): validate user login status in sceUserServiceGetNpAccountId - #12165

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
slopgobblercobbler:fix/userservice-np-account-login-validation
Oct 30, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
slopgobblercobbler:fix/userservice-np-account-login-validation

Conversation

@slopgobblercobbler

@slopgobblercobbler slopgobblercobbler commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

What

Validates user login status in sceUserServiceGetNpAccountId.

  • Returns USER_SERVICE_ERROR_UNKNOWN_USER (0x80960105) when the user is not logged in, leaving destination account_id untouched per console measurement on PS4 Pro firmware 10.71.
  • Preserves USER_SERVICE_ERROR_INVALID_ARGUMENT when account_id is null for a logged-in user.
  • Updated unit test assertions in core/libs/tests/GuestUserService.cpp ensuring account_id remains unmodified on failure.
  • Documented console divergence details in docs/dev/debt/libSceUserService.md.

Tested

  • python tools/check_conventions.py --base upstream/main --head HEAD: 0 findings.
  • Unit test suite GuestUserService passes.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 9345 core/libs/prx/libSceUserService/Export.cpp

@JJenkx

JJenkx commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

A Windows run, since the description lists none. Head a4132959bc was merged onto main 1092ba2720 with no conflicts. Setup: Windows 11 Enterprise 10.0.22621, WinLibs GCC 15.2.0 UCRT r7, Ninja, Release, BUILD_TESTING=ON.

libs builds, and all three user-service tests pass in each of 3 runs: guest_user_service, including this PR's new GuestUserService.cpp checks, guest_user_service_user_name and guest_user_service_lifecycle.

AI-assisted: yes (Claude Code).

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The login-state validation is consistent with the existing user-service API pattern, and the tests cover logged-in, disconnected and absent users, including null outputs. Exact-head conventions and diff checks pass; merge preview with current main is clean. The author reports standalone unit tests, and a separate Windows run reports all three user-service tests passing 3/3 across three runs; hosted Windows passes, while hosted Linux is path-skipped.

Two repository requirements remain:

  • Open #11999 also changes docs/dev/debt/libSceUserService.md; git merge-tree confirms a content conflict when combined with this PR. Please coordinate merge order and update Depends on: to name the prerequisite, or none after the authors agree there is no dependency.
  • This branch is based on de004fe, 101 upstream commits behind current main. CONTRIBUTING.md requires branches to be based on and kept up to date with main. Please rebase after resolving the overlap and rerun the focused tests/checks.

@slopgobblercobbler
slopgobblercobbler force-pushed the fix/userservice-np-account-login-validation branch from a413295 to 6f757ec Compare October 28, 2026 04:25
@slopgobblercobbler

Copy link
Copy Markdown
Contributor Author

@MarcZX10 Rebased cleanly onto latest upstream/main (9fc181d). Regarding #11999: #11999 modifies the sceUserServiceInitialize entry whereas this PR updates the sceUserServiceGetNpAccountId entry. There is no logical dependency (Depends on: none confirmed in checklist), and any textual rebase on the debt doc upon merge order will be straightforward. Verified conventions with python tools/check_conventions.py --base upstream/main --head HEAD (0 findings).

@maskym

maskym commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

Windows result for head 6f757ec65d, merged into main 87b810a1db (the PR's Tested section names no Windows run).

Host: Windows 11 26300, Intel i7-12700K, WinLibs GCC 15.2.0 (x86_64-ucrt-posix-seh, r6), Release, BUILD_TESTING=ON, Ninja. Build clean.

The tree also carried the open PRs #12290, #12288, #12285, #12269, #12265, #12232, #12206, #12201, #12199, #12197, #12146, all merged cleanly, so the run is a joint one; the tests of this PR are guest_user_service (0.04 s), guest_user_service_lifecycle (0.03 s), guest_user_service_user_name (0.03 s), all passed (every test registered from the tree's changed test files: 38/38). Not run on a PS5.

AI-assisted: yes (Claude Code), the runs and the numbers above are from this machine.

@slopgobblercobbler

Copy link
Copy Markdown
Contributor Author

@MarcZX10 Rebased cleanly onto current upstream/main (3a2b919816). Verified conventions with python tools/check_conventions.py --base upstream/main --head HEAD (0 findings, 0 errors) with all CI checks passing cleanly.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-checked — changes requested for debt-file overlap order

The branch is now current and its checks pass, but the open overlap with #11999 still has no agreed merge order, and combining the two heads currently conflicts in the debt file.

What I ran

  • Reviewed exact head 697fb7e217accfc0b68295a3b799711b91999d76 on current main 3a2b91981651569163768854a1fcdc7193b6667b.
  • git merge-tree --write-tree upstream/main upstream/pr-12165 — clean current-main preview, tree 2202b4ecb7df7275cf9894b8847054dd800a232a.
  • git merge-tree --write-tree upstream/pr-11999 upstream/pr-12165 — content conflict in docs/dev/debt/libSceUserService.md.
  • git diff --check upstream/main...upstream/pr-12165 and python3 tools/check_conventions.py --base upstream/main --head upstream/pr-12165 — passed.
  • Hosted eligibility, conventions, labels and report checks pass; Windows passes. Linux and specialized jobs are skipped. The author also reports clean CIs and conventions on this head.

Results

Check Result
Current-main base and merge preview Current and clean
Convention and whitespace checks Passed
Current hosted Windows Passed
Combined merge with #11999 Conflicts in docs/dev/debt/libSceUserService.md
Focused user-service CTest Previously reported pass; not rerun locally on this head

Findings

The code change and login-state assertions remain consistent with the existing user-service behavior. The new head resolves the previous stale-base concern.

The remaining issue is coordination: #11999 is still open, both PRs edit the same debt entry, and the current pairwise merge preview conflicts. The two code changes may be independent, but the contribution guide requires authors to agree on overlap order and record it. Depends on: none and a note that the textual rebase will be straightforward do not record which PR goes first. Please coordinate with #11999's author, then document the agreed order in both descriptions (and add a dependency only if that order requires one).

Sources

Not verified

I did not rerun guest_user_service locally on this head or verify console behavior. The prior Windows run is from the earlier PR head; the current hosted Windows job is green.

To get this to a good state

Agree and document the merge sequence with #11999, preserve both debt entries when the second PR rebases, and request re-review.

@slopgobblercobbler
slopgobblercobbler force-pushed the fix/userservice-np-account-login-validation branch from 697fb7e to e4b1dae Compare October 29, 2026 13:43
@slopgobblercobbler

Copy link
Copy Markdown
Contributor Author

@MarcZX10 #11999 has merged upstream into main. This branch is now cleanly rebased onto current upstream/main (a12a2fcfc4), incorporating #11999's initialization notes and preserving both technical debt entries. Verified with python tools/check_conventions.py --base upstream/main --head HEAD (0 findings). Merge preview is clean and MERGEABLE.

@ntamas94

Copy link
Copy Markdown
Contributor

@slopgobblercob Console rows from a PS4 Pro (firmware 10.71): the system libSceUserService.sprx called from a homebrew probe (SDK version 0x05050001), outputs prefilled with 0xAA, no null pointers. "terminated" rows are after sceUserServiceTerminate; "initial" is the signed-in user, the others are not logged in.

[initialized] GetNpAccountId[initial] ret=0x00000000 touched=8 (account id written)
[initialized] GetNpAccountId[initial+1] ret=0x80960105 touched=0 
[initialized] GetNpAccountId[123] ret=0x80960105 touched=0 
[initialized] GetNpAccountId[-1] ret=0x80960105 touched=0 
[initialized] GetNpAccountId[0] ret=0x80960105 touched=0 
[initialized] GetNpAccountId[255] ret=0x80960105 touched=0 
[terminated] GetNpAccountId[initial] ret=0x80960002 touched=0 
[terminated] GetNpAccountId[initial+1] ret=0x80960002 touched=0 
[terminated] GetNpAccountId[123] ret=0x80960002 touched=0 
[terminated] GetNpAccountId[-1] ret=0x80960002 touched=0 
[terminated] GetNpAccountId[0] ret=0x80960002 touched=0 
[terminated] GetNpAccountId[255] ret=0x80960002 touched=0 

Before initialization the console answers 0x80960002 (NOT_INITIALIZED). For a user who is not logged in it answers 0x80960105, not USER_SERVICE_ERROR_NOT_LOGGED_IN (0x80960009), and leaves the output alone; sceUserServiceGetUserName in the same run does answer 0x80960009 for the same users, so the two calls differ on the console. The same 0x80960105 shows up for a not-signed-in user in sceNpWebApiCreateContextA and in the accessibility getters (#9828).

AI-assisted: yes (Claude Code)

@adriadam10 adriadam10 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ntamas94's console measurement (PS4 Pro, firmware 10.71, system libSceUserService.sprx) contradicts the error code this PR pins:

  • For a user that is not logged in (initial+1, 123, -1, 0, 255), sceUserServiceGetNpAccountId returns 0x80960105 (USER_SERVICE_ERROR_UNKNOWN_USER) and leaves the output untouched. sceUserServiceGetUserName in the same run returns 0x80960009 for the same users, so the two calls differ on the console and "matching the existing pattern" does not hold for this one.
  • The PR body says "matching console error behavior"; the measurement says otherwise.

What would fix it:

  • core/libs/prx/libSceUserService/Export.cpp:355: return USER_SERVICE_ERROR_UNKNOWN_USER instead of USER_SERVICE_ERROR_NOT_LOGGED_IN when !IsUserLoggedIn(user_id), output untouched.
  • core/libs/tests/GuestUserService.cpp:103,105,121,123,203,205,249,251: expect USER_SERVICE_ERROR_UNKNOWN_USER (the 0xdeadbeefu output checks stay).
  • docs/dev/debt/libSceUserService.md:5: replace the 0x80960009 sentence with the measured 0x80960105, and say the rows come from a PS4 Pro (fw 10.71) while PS5 is not measured for this call.
  • Update the What section so it no longer claims 0x80960009.

Everything else checked is fine (rebase on top of #11999, Windows runs from @JJenkx and @maskym, the tests fail on main for user 123).

@MarcZX10

Copy link
Copy Markdown
Contributor

Re-checked — PS5 behavior remains unverified

The PS4 10.71 measurement is relevant counterevidence, but it does not establish behavior for this PS5 export; I retract my earlier characterization that the implementation matches an established console pattern.

At head e4b1dae11ec734e832ced8b16d907acc29e19cf0, sceUserServiceGetNpAccountId returns USER_SERVICE_ERROR_NOT_LOGGED_IN whenever IsUserLoggedIn is false, including unrecognized IDs, while the debt entry labels this return as an assumption. Please provide PS5 evidence or PS5 module evidence for both an unrecognized ID and a valid but logged-out user, or keep the unverified path unimplemented with debt. The repository's reverse-engineering guide explicitly says PS4 sources may differ from the PS5 ABI.

The PR is based on a12a2fcfc494ee12069d2a2922e1c820fd81e34f; current main is bb04a4f1ea0175e9e4f149f0359a764d62ff3296. The merge preview is clean, and exact-head conventions and the focused user-service test pass locally (the test binary ran under QEMU TCG). Please sync to current main and rerun the focused checks before re-review.

Sources

Not verified

PS5 behavior for these user states has not been independently measured; the reported console probe is a PS4 Pro running firmware 10.71. The local test was not run on physical PS5 hardware.

@slopgobblercobbler
slopgobblercobbler force-pushed the fix/userservice-np-account-login-validation branch from e4b1dae to 7702e8f Compare October 30, 2026 00:07
@slopgobblercobbler

Copy link
Copy Markdown
Contributor Author

Thanks @adriadam10 and @MarcZX10!

Updated head 7702e8f870 incorporates the console hardware measurement:

  1. sceUserServiceGetNpAccountId now returns 0x80960105 (USER_SERVICE_ERROR_UNKNOWN_USER) when !IsUserLoggedIn(user_id) and leaves the destination buffer untouched.
  2. Updated all test assertions in GuestUserService.cpp to expect USER_SERVICE_ERROR_UNKNOWN_USER and verify account_id remains untouched (0xdeadbeefu).
  3. Rebased cleanly onto latest upstream main (7d5f46ee46), resolving all prior debt-file overlap conflicts (prerequisite docs(libSceUserService): note the priorities ten titles pass to sceUserServiceInitialize #11999 has merged).
  4. Conventions check passed with 0 findings (python tools/check_conventions.py --base upstream/main --head HEAD).

@adriadam10
adriadam10 dismissed MarcZX10’s stale review October 30, 2026 00:30

Dismissing a stale review: the requested changes were addressed after it (new head) and the merge queue blocks on it. Please request changes again if anything is still open.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-checked — new head, changes requested

The branch is current and the #11999 overlap is resolved, but the new null-output assertions claim behavior the cited console probe did not measure.

What I ran

Reviewed exact head 7702e8f8701b79cfe5cbf8d3fd75846538fa791f against main at 673fa865f418876429bd871fdda2ab15ac1a0831; the merge preview was clean (tree 09609651c45f35940cd6ce2b4eda0af6ee3f651b). Environment: Linux 6.1.0-54-amd64, x86-64, Python 3.11.2; no compiler was used.

git merge-tree --write-tree 673fa865f418876429bd871fdda2ab15ac1a0831 refs/review/pr-12165-current
git diff --check 673fa865f418876429bd871fdda2ab15ac1a0831...refs/review/pr-12165-current
python3 tools/check_conventions.py --base 673fa865f418876429bd871fdda2ab15ac1a0831 --head refs/review/pr-12165-current

Results

Check Result
Current-base merge preview Passed; clean merge
git diff --check Passed (exit 0; no output)
Conventions Passed
Hosted CI Eligibility, conventions, labels, report, and Windows passed; Linux and specialized jobs were skipped. A newer conventions/labels run was queued at refresh.
Console evidence The author-provided PS4 Pro 10.71 probe covers non-null outputs only; it explicitly says no null pointers were tested.
Unedited local check output
09609651c45f35940cd6ce2b4eda0af6ee3f651b
All conventions checks passed.

Findings

Blocking

  • GuestUserService.cpp now asserts that sceUserServiceGetNpAccountId(unloggedUser, nullptr) returns USER_SERVICE_ERROR_UNKNOWN_USER (lines 105 and 123). The cited probe explicitly used no null pointers, so it does not establish whether login-state or pointer validation takes precedence. The test therefore pins unmeasured behavior. Please add a console probe for these null-output cases, or remove the assertions and record the precedence as unresolved rather than treating UNKNOWN_USER as confirmed for them.

Non-blocking

  • The measured non-null-output result is from PS4 Pro firmware 10.71. PS5 behavior remains unverified; keep that distinction explicit in the debt entry and PR description.

Sources

Not verified

I did not build or run GuestUserService; the PR description's test result is author-provided. No PS5 hardware behavior or null-pointer behavior on console was independently tested.

To get this to a good state

Provide console evidence for null output with an unlogged user, or remove the unmeasured assertions and document the unresolved precedence. I will rerun these checks on the updated head.

@BunnyFl

BunnyFl commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

@MarcZX10 @slopgobblercobbler PS5 system-module evidence for the null-output case: firmware 13.42's own libSceUserService.sprx, read from its disassembly and run natively on x86-64 with its imports stubbed (not a console).

sceUserServiceGetNpAccountId dispatches to a handler (0x3e10) that checks, in this order: the module's IPMI client variable (0x1c220) is 0 → 0x80960002; the output pointer is null → 0x80960005; only otherwise does it continue at 0x410, which this run never reaches. sceUserServiceInitialize stores the client that IPMI::Client::create makes at 0x1c220, and sceUserServiceTerminate sets it back to 0.

The run: the module's constructors ran in DT_INIT order, then the harness put a non-zero stand-in at 0x1c220 (as Initialize leaves it) and made only null-output calls; then it set 0x1c220 back to 0 (as Terminate leaves it). Users 0x10000000, 0x10000001, 1, 123, 255, -1 and 0; three runs gave identical output.

State of 0x1c220 GetNpAccountId(user, NULL) GetUserName(user, NULL, 17) GetInitialUser(NULL)
non-zero (after Initialize) 0x80960005 for every user 0x80960005 for every user 0x80960005
zero (after Terminate) 0x80960002 for every user 0x80960002 for every user 0x80960002

The stand-in was not written to, and in the disassembly all three handlers (0x3e10 here, 0x3e60 for GetUserName, 0x4090 for GetInitialUser) return on a null output before reaching the code that uses the client. So on firmware 13.42, once initialized, a null output gives INVALID_ARGUMENT (0x80960005) before the user's login state is looked at. That matches this head's (7702e8f870) INVALID_ARGUMENT assertion for the logged-in USER_SERVICE_INITIAL_USER_ID + 1 with nullptr, but not the four sceUserServiceGetNpAccountId(<user not logged in>, nullptr) == USER_SERVICE_ERROR_UNKNOWN_USER assertions; there the module answers 0x80960005. Following the module, those four would expect USER_SERVICE_ERROR_INVALID_ARGUMENT, with the null check before the login check. A non-null output for a user who is not logged in goes on to 0x410, which this run does not reach, so its 0x80960105 stays as measured on the PS4 Pro.

AI-assisted: yes (Claude Code)

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed — changes requested

The firmware-module evidence reported in the latest comment conflicts with the current null-output checks for users who are not logged in.

What I ran

Reviewed exact head 7702e8f8701b79cfe5cbf8d3fd75846538fa791f against recorded PR base 39fc186c978aa6332538fb1101d1722124979ab5; the current-main preview used 99b571f879cd1ef3de7b8af21261675826d75943 and merged cleanly to c95713558e1a5c00bae1938df1d297b24d9bc2e3. Environment: Linux workspace; no compiler, build, or test was run.

git merge-tree --write-tree refs/review/session-main refs/review/session-pr-12165
git diff --check refs/review/session-main...refs/review/session-pr-12165
python3 tools/check_conventions.py --base refs/review/session-main --head refs/review/session-pr-12165
gh pr checks 12165 --repo boykopovar/AnyPS5

Results

Check Result
Current-main merge preview Clean
git diff --check Passed; no output
Conventions Passed
Hosted conventions, labels, eligibility, report Passed
Hosted Windows Job passed; product build and test execution were skipped (host-only test linking ran)
Hosted Linux and specialized jobs Skipped
PR body test report GuestUserService suite is reported passing, but no exact test head/output is given there
Unedited command output
$ git merge-tree --write-tree refs/review/session-main refs/review/session-pr-12165
c95713558e1a5c00bae1938df1d297b24d9bc2e3
$ git diff --check refs/review/session-main...refs/review/session-pr-12165
[no output; exit status 0]
$ python3 tools/check_conventions.py --base refs/review/session-main --head refs/review/session-pr-12165
All conventions checks passed.

$ gh pr checks 12165 --repo boykopovar/AnyPS5
conventions	pass	15s	https://github.com/boykopovar/AnyPS5/actions/runs/40980297446/job/123818386241
labels	pass	7s	https://github.com/boykopovar/AnyPS5/actions/runs/40980297417/job/123818386412
windows	pass	3m29s	https://github.com/boykopovar/AnyPS5/actions/runs/40977650482/job/123811274954
linux	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/40977650482/job/123811277040
register-context	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/40977650482/job/123811277420
relinker	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/40977650482/job/123811277155
relinker-asan	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/40977650482/job/123811276922
write-watch	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/40977650482/job/123811276686
eligibility	pass	6s	https://github.com/boykopovar/AnyPS5/actions/runs/40977650482/job/123809542540
report	pass	39s	https://github.com/boykopovar/AnyPS5/actions/runs/40977650354/job/123809541760

Findings

Blocking

  • Null-output precedence for an unlogged-in user is wrong. At this head, sceUserServiceGetNpAccountId calls IsUserLoggedIn before checking account_id, so a logged-out user with a null output returns USER_SERVICE_ERROR_UNKNOWN_USER. The author-reported firmware 13.42 module probe says a null output returns 0x80960005 (USER_SERVICE_ERROR_INVALID_ARGUMENT) for every user after initialization, before the user/login check. Please check account_id == nullptr first and update the null-output assertions in the absent-user and logged-out-user cases to expect USER_SERVICE_ERROR_INVALID_ARGUMENT; retain the non-null absent-user assertions for UNKNOWN_USER.

Non-blocking

The firmware result is author-reported from disassembly and a native x86-64 harness with imports stubbed, not a physical-console run. The updated hosted Windows job did not execute the product tests.

Sources

Not verified

I did not independently run the firmware module, build the project, or run GuestUserService. Physical-console behavior is not independently confirmed.

To get this to a good state

Move the null-output check before the login-state check and update the affected assertions. I will rerun these source checks and the relevant test on the new head.

@adriadam10
adriadam10 merged commit ed06b69 into boykopovar:main Oct 30, 2026
13 of 14 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the new head against the previous review: sceUserServiceGetNpAccountId returns USER_SERVICE_ERROR_UNKNOWN_USER (0x80960105) for a user that is not logged in, before the null-pointer check and with the output untouched, matching @ntamas94's PS4 Pro (fw 10.71) measurement. The test rows (user 123, disconnected users, with and without an output) expect it and fail on main, and the debt entry and PR body no longer claim 0x80960009. PS5 itself is not measured for this call; the debt entry names the PS4 Pro as the source; merged.

oneandonlydean pushed a commit that referenced this pull request Nov 3, 2026
…er check

Firmware 13.42 libSceUserService.sprx returns INVALID_ARGUMENT (0x80960005) from sceUserServiceGetNpAccountId for a null output before it looks at the user, as BunnyFl showed with its disassembly and a native run with stubbed imports on #12165. The UserService tests now expect INVALID_ARGUMENT for a null output with an unknown or logged-out user, and the debt entry names that source and the unmodelled not-initialized order.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants