Skip to content

Commit

Permalink
OSI_linux initial mips64 support with fixupendian2 helper
Browse files Browse the repository at this point in the history
Also adds some more macro-enabled debug prints
  • Loading branch information
AndrewFasano committed Jul 21, 2023
1 parent c630c80 commit e32183d
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 18 deletions.
13 changes: 8 additions & 5 deletions panda/plugins/osi_linux/default_profile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ target_ptr_t default_get_current_task_struct(CPUState *cpu)
//via the thread_info struct, the default call to struct_get with the per_cpu_offset_0_addr can be incorrect
err = struct_get(cpu, &ts, current_task_addr, 0);
assert(err == struct_get_ret_t::SUCCESS && "failed to get current task struct");
fixupendian(ts);
fixupendian2(ts);
return ts;
} else {
assert(false && "cannot use kernel version older than 3.7");
Expand All @@ -49,7 +49,7 @@ target_ptr_t default_get_current_task_struct(CPUState *cpu)
//via the thread_info struct, the default call to struct_get with the per_cpu_offset_0_addr can be incorrect
err = struct_get(cpu, &ts, current_task_addr, 0);
assert(err == struct_get_ret_t::SUCCESS && "failed to get current task struct");
fixupendian(ts);
fixupendian2(ts);
return ts;

}
Expand All @@ -58,6 +58,7 @@ target_ptr_t default_get_current_task_struct(CPUState *cpu)
// userspace clobbers it but kernel restores (somewhow?)
// First field of struct is task - no offset needed
current_task_addr = get_id(cpu); // HWID returned by hw_proc_id is the cached r28 value
OG_printf("Got current task struct at " TARGET_FMT_lx "\n", current_task_addr);

#else // x86/64
current_task_addr = ki.task.current_task_addr;
Expand All @@ -66,9 +67,10 @@ target_ptr_t default_get_current_task_struct(CPUState *cpu)
//assert(err == struct_get_ret_t::SUCCESS && "failed to get current task struct");
if (err != struct_get_ret_t::SUCCESS) {
// Callers need to check if we return NULL!
OG_printf("Failed to read current task struct from task_addr with offset " TARGET_FMT_lx "\n", ki.task.per_cpu_offset_0_addr);
return 0;
}
fixupendian(ts);
fixupendian2(ts);
return ts;
}

Expand All @@ -80,7 +82,7 @@ target_ptr_t default_get_task_struct_next(CPUState *cpu, target_ptr_t task_struc
struct_get_ret_t err;
target_ptr_t tasks;
err = struct_get(cpu, &tasks, task_struct, ki.task.tasks_offset);
fixupendian(tasks);
fixupendian2(tasks);
assert(err == struct_get_ret_t::SUCCESS && "failed to get next task");
return tasks-ki.task.tasks_offset;
}
Expand All @@ -92,8 +94,9 @@ target_ptr_t default_get_group_leader(CPUState *cpu, target_ptr_t ts)
{
struct_get_ret_t err;
target_ptr_t group_leader;
OG_printf("Getting group leader from task_struct at " TARGET_FMT_lx " with offset %x\n", ts, ki.task.group_leader_offset);
err = struct_get(cpu, &group_leader, ts, ki.task.group_leader_offset);
fixupendian(group_leader);
fixupendian2(group_leader);
assert(err == struct_get_ret_t::SUCCESS && "failed to get group leader for task");
return group_leader;
}
Expand Down
57 changes: 50 additions & 7 deletions panda/plugins/osi_linux/osi_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -721,17 +721,60 @@ void restore_after_snapshot(CPUState* cpu) {
PPP_REG_CB("syscalls2", on_all_sys_enter, on_first_syscall);
}

#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS)

// Keep track of which tasks have entered execve. Note that we simply track
// based on the task struct. This works because the other threads in the thread
// group will be terminated and the current task will be the only task in the
// group once execve completes. Even if execve fails, this should still work
// because the execve call will return to the calling thread.
static std::unordered_set<target_ptr_t> tasks_in_execve;

static void exec_enter(CPUState *cpu)
{
bool **out=0;
if (!osi_guest_is_ready(cpu, (void**)out)) return;
target_ptr_t ts = kernel_profile->get_current_task_struct(cpu);
tasks_in_execve.insert(ts);
}

static void exec_check(CPUState *cpu)
{
// Fast Path: Nothing is in execve, so there's nothing to do.
if (0 == tasks_in_execve.size()) {
return;
}
bool** out=0;
if (!osi_guest_is_ready(cpu, (void**)out)) return;

// Slow Path: Something is in execve, so we have to check.
target_ptr_t ts = kernel_profile->get_current_task_struct(cpu);
auto it = tasks_in_execve.find(ts);
if (tasks_in_execve.end() != it && !panda_in_kernel(cpu)) {
notify_task_change(cpu);
tasks_in_execve.erase(ts);
}
}

static void before_tcg_codegen_callback(CPUState *cpu, TranslationBlock *tb)
{
TCGOp *op = find_first_guest_insn();
assert(NULL != op);
insert_call(&op, exec_check, cpu);

if (0x0 != ki.task.switch_task_hook_addr && tb->pc == ki.task.switch_task_hook_addr) {
// Instrument the task switch address.
insert_call(&op, notify_task_change, cpu);
}
}
#endif

/**
* @brief Initializes plugin.
*/
bool init_plugin(void *self) {
// Register callbacks to the PANDA core.
#if defined(TARGET_MIPS64)
printf("No OSI for mips64\n");
return false;
#endif

#if defined(TARGET_I386) || defined(TARGET_ARM) || (defined(TARGET_MIPS) && !defined(TARGET_MIPS64))
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS)
{
// Whenever we load a snapshot, we need to find cpu offsets again
// (particularly if KASLR is enabled) and we also may need to re-initialize
Expand All @@ -743,7 +786,7 @@ bool init_plugin(void *self) {
assert(init_osi_api());
}

#if defined(TARGET_MIPS)
#if defined(TARGET_MIPS) // 32 or 64 bit
panda_require("hw_proc_id");
assert(init_hw_proc_id_api());
#endif
Expand Down
13 changes: 7 additions & 6 deletions panda/plugins/osi_linux/osi_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
#include "hw_proc_id/hw_proc_id_ext.h"
#endif

#define OG_printf(...)
//#define OG_printf(...) printf(__VA_ARGS__) // Uncomment for debugging

extern struct kernelinfo ki;
extern struct KernelProfile const *kernel_profile;

Expand Down Expand Up @@ -81,24 +84,24 @@ struct_get_ret_t struct_get(CPUState *cpu, T *v, target_ptr_t ptr, std::initiali
while (true) {
it++;
if (it == offsets.end()) break;
//printf("\tDereferenced 0x%x (offset 0x%lx) to get ", ptr, o);
OG_printf("\tDereferenced 0x" TARGET_FMT_lx" (offset 0x" TARGET_FMT_lx ") to get ", ptr, o);
auto r = struct_get(cpu, &ptr, ptr, o);
if (r != struct_get_ret_t::SUCCESS) {
//printf("ERROR\n");
OG_printf("ERROR\n");
memset((uint8_t *)v, 0, sizeof(T));
return r;
}
o = *it;
// We just read a pointer so we may need to fix its endianness
if (sizeof(T) == 4) fixupendian(ptr); // XXX wrong for 64-bit guests
//printf("0x%x\n", ptr);
OG_printf("0x" TARGET_FMT_lx "\n", ptr);
}

// last item is read using the size of the type of v
// this isn't a pointer so there's no need to fix its endianness
auto ret = struct_get(cpu, v, ptr, o); // deref ptr into v, result in ret
fixupendian(*v);
//printf("Struct_get final 0x%x => 0x%x\n", ptr, *v);
OG_printf("Struct_get final 0x" TARGET_FMT_lx " => 0x " TARGET_FMT_lx "\n", ptr, *v);
return ret;
}
#endif
Expand Down Expand Up @@ -169,8 +172,6 @@ static inline _retType2 _name(CPUState* env, target_ptr_t _paramName) { \
#define OG_SUCCESS 0
#define OG_ERROR_MEMORY -1
#define OG_ERROR_DEREF -2
#define OG_printf(...)
//#define OG_printf(...) printf(__VA_ARGS__)

/**
* @brief IMPLEMENT_OFFSET_GETN is a macro for generating uniform
Expand Down

0 comments on commit e32183d

Please sign in to comment.