Skip to content

Commit

Permalink
Fixed qemu usermode snapshot (#66)
Browse files Browse the repository at this point in the history
* Fixed qemu usermode snapshot

---------

Co-authored-by: Romain Malmain <[email protected]>
  • Loading branch information
cube0x8 and rmalmain authored Apr 26, 2024
1 parent 0a3195e commit de5da8e
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 10 deletions.
6 changes: 6 additions & 0 deletions accel/tcg/user-exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ static PageFlagsNode *pageflags_find(target_ulong start, target_ulong last)
return n ? container_of(n, PageFlagsNode, itree) : NULL;
}

//// --- Begin LibAFL code ---
IntervalTreeRoot * pageflags_get_root(void) {
return &pageflags_root;
}
//// --- End LibAFL code ---

static PageFlagsNode *pageflags_next(PageFlagsNode *p, target_ulong start,
target_ulong last)
{
Expand Down
8 changes: 8 additions & 0 deletions include/exec/cpu-all.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
#include "hw/core/cpu.h"
#include "qemu/rcu.h"

//// --- Begin LibAFL code ---
#include "qemu/interval-tree.h"
//// --- End LibAFL code ---

/* some important defines:
*
* HOST_BIG_ENDIAN : whether the host cpu is big endian and
Expand Down Expand Up @@ -192,6 +196,10 @@ int page_get_flags(target_ulong address);
void page_set_flags(target_ulong start, target_ulong last, int flags);
void page_reset_target_data(target_ulong start, target_ulong last);

//// --- Begin LibAFL code ---
IntervalTreeRoot* pageflags_get_root(void);
//// --- End LibAFL code ---

/**
* page_check_range
* @start: first byte of range
Expand Down
2 changes: 1 addition & 1 deletion include/libafl/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ struct libafl_mapinfo {
};

IntervalTreeNode * libafl_maps_first(IntervalTreeRoot * map_info);
IntervalTreeNode * libafl_maps_next(IntervalTreeNode *node, struct libafl_mapinfo* ret);
IntervalTreeNode * libafl_maps_next(IntervalTreeNode *pageflags_maps_node, IntervalTreeRoot *proc_maps_node, struct libafl_mapinfo* ret);
24 changes: 15 additions & 9 deletions linux-user/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -13806,27 +13806,33 @@ IntervalTreeNode * libafl_maps_first(IntervalTreeRoot * map_info) {
return interval_tree_iter_first(map_info, 0, -1);
}

IntervalTreeNode * libafl_maps_next(IntervalTreeNode *node, struct libafl_mapinfo* ret) {
IntervalTreeNode * libafl_maps_next(IntervalTreeNode *pageflags_maps_node, IntervalTreeRoot *proc_maps_root, struct libafl_mapinfo* ret) {
ret->is_valid = false;

if (!node || !ret) {
if (!pageflags_maps_node || !ret) {
return NULL;
}

MapInfo *e = container_of(node, MapInfo, itree);
MapInfo *e;
IntervalTreeNode *proc_map_interval_node;

if (h2g_valid(e->itree.start)) {
unsigned long min = e->itree.start;
unsigned long max = e->itree.last + 1;
if (h2g_valid(pageflags_maps_node->start)) {
unsigned long min = pageflags_maps_node->start;
unsigned long max = pageflags_maps_node->last + 1;
int flags = page_get_flags(h2g(min));

max = h2g_valid(max - 1) ?
max : (uintptr_t) g2h_untagged(GUEST_ADDR_MAX) + 1;

// I guess this is useless? we are walking the entire pageflags_root tree, so we should always have a valid node
if (!page_check_range(h2g(min), max - min, flags)) {
return libafl_maps_next(interval_tree_iter_next(node, 0, -1), ret);
return libafl_maps_next(interval_tree_iter_next(pageflags_maps_node, 0, -1), proc_maps_root, ret);
}

// Should we check for NULL? Not sure, but if an inteval is in pageflags, then it should be in proc_maps too
proc_map_interval_node = interval_tree_iter_first(proc_maps_root, min, min);
e = container_of(proc_map_interval_node, MapInfo, itree);

int libafl_flags = 0;
if (flags & PAGE_READ) libafl_flags |= PROT_READ;
if (flags & PAGE_WRITE_ORG) libafl_flags |= PROT_WRITE;
Expand All @@ -13840,9 +13846,9 @@ IntervalTreeNode * libafl_maps_next(IntervalTreeNode *node, struct libafl_mapinf
ret->flags = libafl_flags;
ret->is_priv = e->is_priv;

return interval_tree_iter_next(node, 0, -1);
return interval_tree_iter_next(pageflags_maps_node, 0, -1);
} else {
return libafl_maps_next(interval_tree_iter_next(node, 0, -1), ret);
return libafl_maps_next(interval_tree_iter_next(pageflags_maps_node, 0, -1), proc_maps_root, ret);
}
}

Expand Down

0 comments on commit de5da8e

Please sign in to comment.