From 43302cdc3966a335bfc84bcad75a58d4ed0708b8 Mon Sep 17 00:00:00 2001 From: cube0x8 Date: Fri, 26 Apr 2024 16:56:20 +0300 Subject: [PATCH] Fixed qemu usermode snapshot (#66) * Fixed qemu usermode snapshot --------- Co-authored-by: Romain Malmain --- accel/tcg/user-exec.c | 6 ++++++ include/exec/cpu-all.h | 8 ++++++++ include/libafl/user.h | 2 +- linux-user/syscall.c | 24 +++++++++++++++--------- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index 3cac3a78c4..de4007e75f 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -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) { diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 1a6510fd3b..ddc57049e8 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -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 @@ -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 diff --git a/include/libafl/user.h b/include/libafl/user.h index 9d942e759e..fd386511a3 100644 --- a/include/libafl/user.h +++ b/include/libafl/user.h @@ -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); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index fcebfa51b9..6af993f405 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -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; @@ -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); } }