Created
December 21, 2025 14:08
-
-
Save john-tornblom/61c4f381c449706243fffaff990d671b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* Copyright (C) 2025 John Törnblom | |
| This program is free software; you can redistribute it and/or modify it | |
| under the terms of the GNU General Public License as published by the | |
| Free Software Foundation; either version 3, or (at your option) any | |
| later version. | |
| This program is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| GNU General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with this program; see the file COPYING. If not, see | |
| <http://www.gnu.org/licenses/>. */ | |
| #include <errno.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <unistd.h> | |
| #include <sys/socket.h> | |
| #include <sys/stat.h> | |
| #include <sys/syscall.h> | |
| #include <sys/un.h> | |
| #include <ps5/kernel.h> | |
| static char* | |
| bin2hex(const uint8_t* bin, char* hex, size_t binsize) { | |
| hex[0] = '0'; | |
| hex[1] = 'x'; | |
| for(size_t i=0; i<binsize; ++i) { | |
| sprintf(&hex[i*2 + 2], "%02x", bin[i]); | |
| } | |
| hex[binsize*2 + 2] = '\0'; | |
| return hex; | |
| } | |
| static void | |
| print_privileges(pid_t pid) { | |
| uint8_t qaflags[16] = {0}; | |
| uint8_t caps[16] = {0}; | |
| char buf[16*3]; | |
| kernel_get_qaflags(qaflags); | |
| kernel_get_ucred_caps(pid, caps); | |
| puts("Console info"); | |
| puts("------------"); | |
| printf("Firmware: %08x\n", kernel_get_fw_version()); | |
| printf("TARGETID: 0x%02x\n", kernel_getchar(KERNEL_ADDRESS_TARGETID)); | |
| printf("SECURITY_FLAGS: 0x%02x\n", kernel_getchar(KERNEL_ADDRESS_SECURITY_FLAGS)); | |
| printf("UTOKEN_FLAGS: 0x%02x\n", kernel_getchar(KERNEL_ADDRESS_UTOKEN_FLAGS)); | |
| printf("QA_FLAGS: %s\n", bin2hex(qaflags, buf, sizeof(qaflags))); | |
| puts(""); | |
| puts("Privileges"); | |
| puts("----------"); | |
| printf("SCE authid: 0x%016lx\n", kernel_get_ucred_authid(pid)); | |
| printf("SCE attrs: 0x%016lx\n", kernel_get_ucred_attrs(pid)); | |
| printf("SCE caps: %s\n", bin2hex(caps, buf, sizeof(caps))); | |
| printf("uid: %d\n", getuid()); | |
| printf("euid: %d\n", geteuid()); | |
| printf("jail vnode: 0x%lx\n", kernel_get_proc_jaildir(pid)); | |
| puts(""); | |
| } | |
| static int | |
| raise_privileges(pid_t pid) { | |
| static const uint8_t caps[16] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, | |
| 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; | |
| kernel_set_ucred_authid(pid, 0x4800000000010003l); | |
| kernel_set_ucred_attrs(pid, -1l); | |
| kernel_set_ucred_uid(pid, 0); | |
| kernel_set_ucred_ruid(pid, 0); | |
| kernel_set_ucred_caps(pid, caps); | |
| return 0; | |
| } | |
| static int | |
| test_symlinks(void) { | |
| int err = 0; | |
| puts(""); | |
| puts("Testing symlinks"); | |
| puts("----------------"); | |
| if(__syscall(SYS_symlink, "/data", "/system_data/temp/symlink_to_data")) { | |
| perror("ufs symlink (/system_data)"); | |
| err = 1; | |
| } else { | |
| puts("ufs symlink (/system_data): OK"); | |
| unlink("/system_data/temp/symlink_to_data"); | |
| } | |
| // | |
| if(__syscall(SYS_symlink, "/data", "/system_tmp/symlink_to_data")) { | |
| perror("nullfs symlink (/system_tmp)"); | |
| err = 1; | |
| } else { | |
| puts("nullfs symlink (/system_tmp): OK"); | |
| unlink("/system_tmp/symlink_to_data"); | |
| } | |
| // | |
| if(__syscall(SYS_symlink, "/data", "/user/temp/symlink_to_data")) { | |
| perror("bfs symlink (/user/temp)"); | |
| err = 1; | |
| } else { | |
| puts("bfs symlink (/user/temp): OK"); | |
| unlink("/user/temp/symlink_to_data"); | |
| } | |
| return err; | |
| } | |
| static int | |
| test_domain_socket(const char* test_name, const char* path) { | |
| int fd = socket(AF_UNIX, SOCK_STREAM, 0); | |
| int err = 0; | |
| struct sockaddr_un addr; | |
| memset(&addr, 0, sizeof(addr)); | |
| addr.sun_family = AF_UNIX; | |
| strcpy(addr.sun_path, path); | |
| if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { | |
| printf("%s: %s\n", test_name, strerror(errno)); | |
| err = -1; | |
| } else { | |
| printf("%s: OK\n", test_name); | |
| } | |
| close(fd); | |
| unlink(addr.sun_path); | |
| return err; | |
| } | |
| static int | |
| test_hardlinks(void) { | |
| int err = 0; | |
| puts(""); | |
| puts("Testing hardlinks"); | |
| puts("-----------------"); | |
| if(__syscall(SYS_mkdir, "/system_data/temp/test")) { | |
| perror("mkdir /system_data/temp/test"); | |
| err = -1; | |
| } else if(__syscall(SYS_link, "/system_data/temp/test", "/system_data/temp/link_to_test")) { | |
| perror("ufs hardlink (/system_data)"); | |
| err = -1; | |
| } else { | |
| puts("ufs hardlink (/system_data): OK"); | |
| } | |
| __syscall(SYS_unlink, "/system_data/temp/link_to_test"); | |
| __syscall(SYS_rmdir, "/system_data/temp/test"); | |
| // | |
| if(__syscall(SYS_mkdir, "/system_tmp/test")) { | |
| perror("mkdir /system_tmp/test"); | |
| err = -1; | |
| } else if(__syscall(SYS_link, "/system_tmp/test", "/system_tmp/link_to_test")) { | |
| perror("nullfs hardlink (/system_tmp)"); | |
| err = -1; | |
| } else { | |
| puts("nullfs hardlink (/system_tmp): OK"); | |
| } | |
| __syscall(SYS_unlink, "/system_tmp/link_to_test"); | |
| __syscall(SYS_rmdir, "/system_tmp/test"); | |
| // | |
| if(__syscall(SYS_mkdir, "/user/temp/test")) { | |
| perror("mkdir /user/temp/test"); | |
| err = -1; | |
| } else if(__syscall(SYS_link, "/user/temp/test", "/user/temp/link_to_test")) { | |
| perror("bfs hardlink (/user/temp)"); | |
| err = -1; | |
| } else { | |
| puts("bfs hardlink (/user/temp): OK"); | |
| } | |
| __syscall(SYS_unlink, "/user/temp/link_to_test"); | |
| __syscall(SYS_rmdir, "/user/temp/test"); | |
| return err; | |
| } | |
| static int | |
| test_mknod_fifo(void) { | |
| int err = 0; | |
| puts(""); | |
| puts("Testing mknod(S_IFIFO)"); | |
| puts("----------------------"); | |
| if(__syscall(SYS_mknod, "/system_data/temp/fifo", S_IFIFO | 0666, 0)) { | |
| perror("ufs mknod S_IFIFO (/system_data)"); | |
| err = 1; | |
| } else { | |
| puts("ufs mknod S_IFIFO (/system_data): OK"); | |
| unlink("/system_data/temp/fifo"); | |
| } | |
| if(__syscall(SYS_mknod, "/system_tmp/fifo", S_IFIFO | 0666, 0)) { | |
| perror("nullfs mknod S_IFIFO (/system_tmp)"); | |
| err = 1; | |
| } else { | |
| puts("nullfs mknod S_IFIFO (/system_tmp): OK"); | |
| unlink("/system_tmp/fifo"); | |
| } | |
| if(__syscall(SYS_mknod, "/user/temp/fifo", S_IFIFO | 0666, 0)) { | |
| perror("bfs mknod S_IFIFO (/user/temp)"); | |
| err = 1; | |
| } else { | |
| puts("bfs mknod S_IFIFO (/user/temp): OK"); | |
| unlink("/user/temp/fifo"); | |
| } | |
| return err; | |
| } | |
| int | |
| main() { | |
| raise_privileges(-1); | |
| print_privileges(-1); | |
| test_symlinks(); | |
| test_hardlinks(); | |
| test_mknod_fifo(); | |
| puts(""); | |
| puts("Testing UNIX domain socket"); | |
| puts("--------------------------"); | |
| test_domain_socket("ufs domain socket", "/system_data/temp/sock"); | |
| test_domain_socket("nullfs domain socket", "/system_tmp/sock"); | |
| test_domain_socket("bfs domain socket", "/user/temp/sock"); | |
| return 0; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment