Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
301 lines (285 sloc) 7.5 KB
/*
* map_open_path.h.S -- PS3 Jailbreak payload : function to map the open path
*
* Copyright (C) Youness Alaoui (KaKaRoTo)
*
* This software is distributed under the terms of the GNU General Public
* License ("GPL") version 3, as published by the Free Software Foundation.
*
*/
#ifndef __MAP_OPEN_PATH_H_S__
#define __MAP_OPEN_PATH_H_S__
/**
* map_open_path:
* @old_path: The path to map
* @new_path: The new path to map it to (or NULL to remove the mapping)
*
* This position independent function will redirect all file access from @old_path to
* @new_path or if @new_path is #NULL, it will remove the mapping
*
* pseudo-code :
* map_open_path(old_path, new_path) {
* int old_len, new_len
* struct path_mapping_s *ptr
*
* if (old_path == NULL)
error:
* return -1
* old_len = strlen(old_path)
* if (new_path)
* new_len = strlen(new_path)
* else
unset:
* new_len = 0
* if (open_mapping_table == NULL) {
* open_mapping_table = alloc (MAX_TABLE_ENTRIES * sizeof(struct path_mapping_s))
memset:
* for (int i = MAX_TABLE_ENTRIES * sizeof(struct path_mapping_s) - 8; i >= 0; i -= 8)
* open_mapping_table[i] = 0
* ptr = open_mapping_table
* goto new_entry
* } else {
no_alloc:
* ptr = open_mapping_table
next_table_entry:
* while (ptr != open_mapping_table + MAX_TABLE_ENTRIES * sizeof(...)) {
* if (ptr.old == NULL)
* continue
* if (ptr.old->size != old_size)
* continue
* if (strncmp(ptr.old->path, old_path, old_size) != 0)
* continue
* if (new_path)
* goto set_new_path
* free (ptr.old)
* free (ptr.new)
* ptr.old = ptr.new = 0
* return 0
* }
not_found:
* ptr = open_mapping_table
next_table_entry2:
* while (ptr != open_mapping_table + MAX_TABLE_ENTRIES * sizeof(...)) {
* if (ptr.old != NULL)
* continue
* goto new_entry
* }
full:
* return -2
* }
*
new_entry:
* if (new_path == NULL)
* return 0
* ptr.old = alloc (sizeof(int) + old_size + 1)
* ptr.old->size = old_size
* strcpy (ptr.old->path, old_path)
* ptr.new = alloc (sizeof (int) + MAX_PATH_SIZE + 1)
set_new_path:
* ptr.new->size = new_size
* strcpy(ptr.new->path, new_path)
*
* return 0
* }
*
*/
map_open_path_start:
// prolog
mflr %r0
stdu %r1, -0xc0(%r1)
std %r24, 0x70(%r1)
std %r25, 0x78(%r1)
std %r26, 0x80(%r1)
std %r27, 0x88(%r1)
std %r28, 0x90(%r1)
std %r29, 0x98(%r1)
std %r30, 0xa0(%r1)
std %r31, 0xa8(%r1)
std %r0, 0xd0(%r1)
mr %r24, %r3
mr %r25, %r4
cmpldi %r3, 0
beq l_map_open_error
BRANCH_ABSOLUTE(%r6, strlen)
mr %r29, %r3
mr %r3, %r25
cmpldi %r3, 0
beq l_map_open_unset
BRANCH_ABSOLUTE(%r6, strlen)
l_map_open_unset:
mr %r30, %r3
// check the map table
MEM_BASE (%r31)
LOAD_LABEL2 (%r26, %r31, open_mapping_table)
ld %r3, 0(%r26)
cmpldi %r3, 0
bne l_map_open_no_alloc
li %r3, 0x10*MAX_TABLE_ENTRIES
li %r4, 0x27
BRANCH_ABSOLUTE(%r6, alloc) // allocate the table
std %r3, 0(%r26)
mr %r26, %r3
mr %r28, %r26
li %r4, 0
li %r5, 0x10*MAX_TABLE_ENTRIES
l_map_open_memset: // set all the data to 0
subi %r5, %r5, 8 // set %r5 to read the previous quad
stdx %r4, %r3, %r5 // Store byte %r6 to %r4[%r5]
cmpldi %r5, 0 // if %r5 reaches 0, end it
bne l_map_open_memset
b l_map_open_new_entry // no need to scan it
l_map_open_no_alloc:
// load the mapping_table in %r26
ld %r28, 0(%r26)
mr %r26, %r28
addi %r27, %r28, 0x10*MAX_TABLE_ENTRIES // Set our limit
l_map_open_next_table_entry:
cmpld %r26, %r27
beq l_map_open_not_found // If we reached our limit, we're done
ld %r3, 0(%r26) // Load the old path structure
addi %r26, %r26, 0x10 // skip to the next entry
cmplwi %r3, 0
beq l_map_open_next_table_entry // if empty entry, then try next
addi %r4, %r3, 4 // Load the path
lwz %r5, 0(%r3) // Load the size of this path
cmplw %r5, %r29
bne l_map_open_next_table_entry // if different size, then try next
mr %r3, %r24 // Load the old path to compare in %r3
BRANCH_ABSOLUTE(%r6, strncmp)
cmpldi %r3, 0
bne l_map_open_next_table_entry // If different, then go to next entry
// We found the entry we wanted
addi %r26, %r26, -0x10 // Reset to the correct entry
ld %r3, 0x08(%r26)
cmpwi %r30, 0 // Check if we set or unset the entry
bne l_map_open_set_new_path // Just overwrite the data in the
// already allocated buffer
ld %r3, 0(%r26) // free the entry if new path = NULL
li %r4, 0x27
BRANCH_ABSOLUTE(%r6, free)
ld %r3, 8(%r26)
li %r4, 0x27
BRANCH_ABSOLUTE(%r6, free)
li %r3, 0
std %r3, 0(%r26)
std %r3, 8(%r26)
b l_map_open_return_0
l_map_open_not_found:
mr %r26, %r28
l_map_open_next_table_entry2:
cmpld %r26, %r27
beq l_map_open_full // If we reached our limit, we're done
ld %r3, 0(%r26) // Load the path structure
addi %r26, %r26, 0x10 // skip to the next entry
cmplwi %r3, 0
bne l_map_open_next_table_entry2 // if empty entry, then try next
addi %r26, %r26, -0x10 // reset back to the correct entry
l_map_open_new_entry:
cmpwi %r30, 0
beq l_map_open_return_0 // If there is no new path, return
addi %r3, %r29, 5
li %r4, 0x27
BRANCH_ABSOLUTE(%r6, alloc) // allocate space for the old path
// structure: size(4) + string + \x00
std %r3, 0(%r26)
stw %r29, 0(%r3)
addi %r3, %r3, 4
mr %r4, %r24
BRANCH_ABSOLUTE(%r6, strcpy)
li %r3, 0x805
li %r4, 0x27
BRANCH_ABSOLUTE(%r6, alloc) // allocate space for the new path
// structure: size(4) + 2048 + \x00
std %r3, 0x08(%r26)
l_map_open_set_new_path:
stw %r30, 0(%r3)
addi %r3, %r3, 4
mr %r4, %r25
BRANCH_ABSOLUTE(%r6, strcpy)
b l_map_open_return_0
l_map_open_error:
li %r3, 0
nor %r3, %r3, %r3 // r3 is already 0 here, so make it -1
b l_map_open_return
l_map_open_full:
li %r3, 1
nor %r3, %r3, %r3 // return -2
b l_map_open_return
l_map_open_return_0:
li %r3, 0 // return 0
b l_map_open_return
l_map_open_return:
// epilog
ld %r24, 0x70(%r1)
ld %r25, 0x78(%r1)
ld %r26, 0x80(%r1)
ld %r27, 0x88(%r1)
ld %r28, 0x90(%r1)
ld %r29, 0x98(%r1)
ld %r30, 0xa0(%r1)
ld %r31, 0xa8(%r1)
ld %r0, 0xd0(%r1)
addi %r1, %r1, 0xc0
mtlr %r0
blr
map_open_path_end:
/**
* syscall_map_open:
* @old_path: The path to map
* @new_path: The new path to map it to (or NULL to remove the mapping)
*
* This new syscall will redirect all file access from @old_path to
* @new_path or if @new_path is #NULL, it will remove the mapping
*/
syscall_map_open_start:
// prolog
mflr %r0
stdu %r1, -0xc0(%r1)
std %r26, 0x70(%r1)
std %r0, 0xd0(%r1)
mr %r26, %r4
cmpldi %r3, 0
beq l_syscall_map_open_error
addi %r4, %r1, 0xa0 // old path
BRANCH_ABSOLUTE(%r6, pathdup_from_user) // strdup %r3 from userspace
mr %r29, %r3
mr %r3, %r26
cmpldi %r3, 0
beq l_syscall_map_open_unset
addi %r4, %r1, 0xb0 // new path
BRANCH_ABSOLUTE(%r6, pathdup_from_user) // strdup %r4 from userspace
b l_syscall_map_open_call
l_syscall_map_open_unset:
std %r3, 0xb0(%r1)
l_syscall_map_open_call:
ld %r3, 0xa0(%r1) // old path
ld %r4, 0xb0(%r1) // new path
// Call map_open_path
MEM_BASE (%r6)
LOAD_LABEL2 (%r6, %r6, map_open_path_ptr)
ld %r6, 0(%r6)
mtctr %r6
bctrl
mr %r26, %r3
ld %r3, 0xa0(%r1)
li %r4, 0x27
BRANCH_ABSOLUTE(%r6, free)
ld %r3, 0xb0(%r1)
cmpldi %r3, 0
beq l_syscall_map_open_return
li %r4, 0x27
BRANCH_ABSOLUTE(%r6, free)
l_syscall_map_open_return:
mr %r3, %r26 // return result of add_open_path_map
l_syscall_map_open_return_r3:
// epilog
ld %r26, 0x70(%r1)
ld %r0, 0xd0(%r1)
addi %r1, %r1, 0xc0
mtlr %r0
blr
l_syscall_map_open_error:
nor %r3, %r3, %r3 // r3 is already 0 here, so make it -1
b l_syscall_map_open_return_r3
syscall_map_open_end:
#endif /* __MAP_OPEN_PATH_H_S__ */
Something went wrong with that request. Please try again.