Files
AnyPS5/core/libs/tests/GuestCredentials.cpp
T
Mouad-Scriptz-0 bc5bfd0ed6 feat(libkernel): export setuid, setreuid, setgroups and getgroups
`setuid`, `setreuid` and `setgroups` are absent imports of XPSemu
(PPSA97358) and PS5MC (PPSA99420) on `main`. The guest process is modelled
as root with ids 0, as `seteuid` and `setegid` already assume: `setuid`
accepts 0 and `setreuid` 0 or -1 per id and change nothing, any other id
throws. `setgroups` keeps the supplementary group list as FreeBSD's
`kern_setgroups` does (`NGROUPS_MAX` 1023, an empty list leaves the
effective group as the only entry, a first entry other than 0 throws) and
the new `getgroups` reports it. `guest_credentials` covers the accepted
ids, the default list, a set list, an empty list and the EINVAL/EFAULT
cases.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit d12b062074dcf64bff694800d77f7261adf6f59e)
2026-10-11 18:55:22 +00:00

58 lines
2.3 KiB
C++

#include "prx/libc/include/general/VabiMacros.hpp"
#include <array>
#include <cstdint>
#include <cstdlib>
extern "C" {
int APS5_VABI setuid_nid_postfix(std::uint32_t);
int APS5_VABI setreuid_nid_postfix(std::uint32_t, std::uint32_t);
int APS5_VABI setgroups_nid_postfix(int, const std::uint32_t*);
int APS5_VABI getgroups_nid_postfix(int, std::uint32_t*);
int APS5_VABI getuid_nid_postfix(void);
int APS5_VABI geteuid_nid_postfix(void);
int APS5_VABI getegid_nid_postfix(void);
int* APS5_VABI __error_nid_postfix();
}
static void Require(bool value) { if (!value) std::abort(); }
constexpr int GuestEfault = 14;
constexpr int GuestEinval = 22;
constexpr std::uint32_t Unchanged = 0xffffffffu;
static void RequireFailure(int result, int error) {
Require(result == -1);
Require(*__error_nid_postfix() == error);
}
int main() {
Require(setuid_nid_postfix(0) == 0);
Require(getuid_nid_postfix() == 0 && geteuid_nid_postfix() == 0);
Require(setreuid_nid_postfix(Unchanged, Unchanged) == 0);
Require(setreuid_nid_postfix(0, Unchanged) == 0);
Require(setreuid_nid_postfix(Unchanged, 0) == 0);
Require(setreuid_nid_postfix(0, 0) == 0);
std::array<std::uint32_t, 4> groups{};
Require(getgroups_nid_postfix(0, nullptr) == 1);
Require(getgroups_nid_postfix(static_cast<int>(groups.size()), groups.data()) == 1 && groups[0] == 0);
Require(groups[0] == static_cast<std::uint32_t>(getegid_nid_postfix()));
const std::array<std::uint32_t, 3> wanted{0, 5, 7};
Require(setgroups_nid_postfix(static_cast<int>(wanted.size()), wanted.data()) == 0);
Require(getgroups_nid_postfix(0, nullptr) == 3);
RequireFailure(getgroups_nid_postfix(2, groups.data()), GuestEinval);
RequireFailure(getgroups_nid_postfix(3, nullptr), GuestEfault);
Require(getgroups_nid_postfix(static_cast<int>(groups.size()), groups.data()) == 3);
Require(groups[0] == 0 && groups[1] == 5 && groups[2] == 7);
Require(setgroups_nid_postfix(0, nullptr) == 0);
Require(getgroups_nid_postfix(static_cast<int>(groups.size()), groups.data()) == 1 && groups[0] == 0);
RequireFailure(setgroups_nid_postfix(-1, wanted.data()), GuestEinval);
RequireFailure(setgroups_nid_postfix(1024, wanted.data()), GuestEinval);
RequireFailure(setgroups_nid_postfix(1, nullptr), GuestEfault);
Require(getgroups_nid_postfix(0, nullptr) == 1);
return 0;
}