Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fw agnostic save mounting #155

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions include/dir.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef DIR_H
#define DIR_H

#ifdef __cplusplus
extern "C" {
#endif

#define MAX_PATH_LEN 1024

int copyfile(const char *src, const char *dst);
int copydir(const char *src, const char *dst);

#ifdef __cplusplus
}
#endif

#endif // DIR_H
16 changes: 16 additions & 0 deletions include/init.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef INIT_H
#define INIT_H

#ifdef __cplusplus
extern "C" {
#endif

int init_cred(void);
int setup_cred(void);
int init_devices(void);

#ifdef __cplusplus
}
#endif

#endif // INIT_H
17 changes: 17 additions & 0 deletions include/scall.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef SCALL_H
#define SCALL_H

#include <orbis/libkernel.h>

#ifdef __cplusplus
extern "C" {
#endif

int sys_open(const char *path, int flags, int mode);
int sys_mknod(const char *path, mode_t mode, dev_t dev);

#ifdef __cplusplus
}
#endif

#endif // SCALL_H
43 changes: 43 additions & 0 deletions include/sd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef SD_H
#define SD_H

#include <stdint.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

#define ENC_SEALEDKEY_LEN 0x60
#define DEC_SEALEDKEY_LEN 0x20

#define UNUSED(x) (void)(x)

typedef struct {
int blockSize;
uint8_t idk[2];
} CreatePfsSaveDataOpt;

typedef struct {
bool readOnly;
char *budgetid;
} MountSaveDataOpt;

typedef struct {
bool dummy;
} UmountSaveDataOpt;

int loadPrivLibs(void);
int generateSealedKey(uint8_t data[ENC_SEALEDKEY_LEN]);
int decryptSealedKey(uint8_t enc_key[ENC_SEALEDKEY_LEN], uint8_t dec_key[DEC_SEALEDKEY_LEN]);
int decryptSealedKeyAtPath(const char *keyPath, uint8_t decryptedSealedKey[DEC_SEALEDKEY_LEN]);
int createSave(const char *folder, const char *saveName, int blocks);
int mountSave(const char *folder, const char *saveName, const char *mountPath);
int umountSave(const char *mountPath, int handle, bool ignoreErrors);
uint16_t getMaxKeySet(void);

#ifdef __cplusplus
}
#endif

#endif // SD_H
114 changes: 114 additions & 0 deletions source/dir.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <orbis/libkernel.h>
#include <stdint.h>

#include "dir.h"
#include "scall.h"

int copyfile(const char *src, const char *dst) {
int fd_src = -1;
int fd_dst = -1;
int ret = 0;
uint8_t buf[65536]; // 64KB chunk size
ssize_t bytesRead, bytesWritten;

// open source file
fd_src = open(src, O_RDONLY, 0);
if (fd_src == -1) {
ret = -1;
goto clean;
}

// open destination file
fd_dst = open(dst, O_CREAT | O_WRONLY | O_TRUNC, 0777);
if (fd_dst == -1) {
ret = -2;
goto clean;
}

// write to other file in chunks until end
while ((bytesRead = read(fd_src, buf, sizeof(buf))) > 0) {
bytesWritten = write(fd_dst, buf, bytesRead);
if (bytesWritten != bytesRead) {
ret = -3;
goto clean;
}
}

if (bytesRead == -1) {
ret = -4;
}

clean:
if (fd_src != -1) {
close(fd_src);
}
if (fd_dst != -1) {
close(fd_dst);
}
return ret;
}

int copydir(const char *src, const char *dst) {
DIR *dir;
struct dirent *entry = NULL;
char new_dst[MAX_PATH_LEN];

mkdir(dst, 0777);

dir = opendir(src);
if (!dir) {
return -1;
}

while ((entry = readdir(dir))) {
// skip "." and ".." to avoid infinite loops
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}

struct stat s;
char path[MAX_PATH_LEN];

memset(&s, 0, sizeof(struct stat));
snprintf(path, sizeof(path), "%s/%s", src, entry->d_name);

// check if dir
if (entry->d_type == DT_DIR) {
// check if exists in src
if (stat(path, &s) == -1) {
continue;
}
snprintf(new_dst, sizeof(new_dst), "%s/%s", dst, entry->d_name);

int ret = copydir(path, new_dst);
if (ret != 0) {
return ret;
}
}
// check if file
else if (entry->d_type == DT_REG) {
// check if exists in src
if (stat(path, &s) == -1) {
continue;
}

// treat files specially
setuid(s.st_uid);

snprintf(new_dst, sizeof(new_dst), "%s/%s", dst, entry->d_name);
if (copyfile(path, new_dst) != 0) {
return -2;
}
}
}

setuid(0);
closedir(dir);
return 0;
}
116 changes: 116 additions & 0 deletions source/init.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <libjbc.h>
#include <dbglogger.h>
#define LOG dbglogger_log

#include "init.h"
#include "sd.h"
#include "scall.h"

// cred must be set to invoke mount call, use before anything
int init_cred(void) {
jbc_cred old_cred;
jbc_cred cred;

memset(&old_cred, 0, sizeof(jbc_cred));
memset(&cred, 0, sizeof(jbc_cred));

if (jbc_get_cred(&old_cred) != 0) {
return -1;
}
old_cred.sonyCred = old_cred.sonyCred | 0x4000000000000000ULL;

if (jbc_get_cred(&cred) != 0) {
return -2;
}
cred.sonyCred = cred.sonyCred | 0x4000000000000000ULL;
cred.sceProcType = 0x3801000000000013ULL;

if (jbc_set_cred(&cred) != 0) {
return -3;
}
setuid(0);

return 0;
}

// can use before mount call after initializing everything
int setup_cred(void) {
jbc_cred cred;

memset(&cred, 0, sizeof(jbc_cred));
if (jbc_get_cred(&cred) != 0) {
return -1;
}
cred.sonyCred = cred.sonyCred | 0x4000000000000000ULL;
cred.sceProcType = 0x3801000000000013ULL;

if (jbc_set_cred(&cred) != 0) {
return -2;
}
setuid(0);

return 0;
}

// create devices, do once after setting cred and loading priv libs
int init_devices(void) {
struct stat s;
memset(&s, 0, sizeof(struct stat));

// mount required devices into sandbox
if (jbc_mount_in_sandbox("/dev/", "rootdev") != 0) {
LOG("Failed to mount devices");
return -1;
}

// create devices
if (stat("/rootdev/pfsctldev", &s) == -1) {
LOG("err stat pfsctldev");
return -2;
}
else {
if (sys_mknod("/dev/pfsctldev", S_IFCHR | 0777, s.st_dev) == -1) {
LOG("err mknod pfsctldev");
return -2;
}
}

memset(&s, 0, sizeof(struct stat));

if (stat("/rootdev/lvdctl", &s) == -1) {
LOG("err stat lvdctl");
return -3;
}
else {
if (sys_mknod("/dev/lvdctl", S_IFCHR | 0777, s.st_dev) == -1) {
LOG("err mknod lvdctl");
return -3;
}
}

memset(&s, 0, sizeof(struct stat));

if (stat("/rootdev/sbl_srv", &s) == -1) {
LOG("err stat sbl_srv");
return -4;
}
else {
if (sys_mknod("/dev/sbl_srv", S_IFCHR | 0777, s.st_dev) == -1) {
LOG("err mknod sbl_srv");
return -4;
}
}

// now unmount devices
if (jbc_unmount_in_sandbox("rootdev") != 0) {
LOG("Failed to unmount rootdev");
}

// get max keyset that can be decrypted
getMaxKeySet();

return 0;
}
43 changes: 43 additions & 0 deletions source/scall.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include <orbis/libkernel.h>

#include "scall.h"
#include "sd.h"

int sys_open(const char *path, int flags, int mode) {
int result;
int err;

asm volatile(
".intel_syntax;"
"mov rax, 5;" // System call number for open: 5
"syscall;" // Invoke syscall
: "=a" (result), // Output operand: result
"=@ccc" (err) // Output operand: err (clobbers condition codes)
);

UNUSED(path);
UNUSED(flags);
UNUSED(mode);

return result;
}

int sys_mknod(const char *path, mode_t mode, dev_t dev) {
int result;
int err;

asm volatile(
".intel_syntax;" // Switches the assembly syntax to Intel syntax
"mov rax, 14;" // Moves the value 14 into the RAX register (which typically holds the system call number)
"mov r10, rcx;" // Moves the value of the RCX register into the R10 register
"syscall;" // Executes a system call using the values in the registers
: "=a"(result), // Output constraint: Tells the compiler that the result of the operation will be stored in the RAX register
"=@ccc"(err) // Output constraint: Indicates that error information will be stored in the specified location
);

UNUSED(path);
UNUSED(mode);
UNUSED(dev);

return result;
}
Loading