socsvn commit: r271085 - in soc2014/op/freebsd-base/sys: kern sys
op at FreeBSD.org
op at FreeBSD.org
Fri Jul 18 16:08:28 UTC 2014
Author: op
Date: Fri Jul 18 16:08:27 2014
New Revision: 271085
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=271085
Log:
KSP: change destination memory region from RX to RWX, and after patching back to RX
Signed-off-by: Oliver Pinter <oliver.pntr at gmail.com>
git: https://github.com/opntr/opBSD/tree/op/gsoc2014/kpatch
Modified:
soc2014/op/freebsd-base/sys/kern/kern_selfpatch.c
soc2014/op/freebsd-base/sys/sys/selfpatch.h
Modified: soc2014/op/freebsd-base/sys/kern/kern_selfpatch.c
==============================================================================
--- soc2014/op/freebsd-base/sys/kern/kern_selfpatch.c Fri Jul 18 16:07:58 2014 (r271084)
+++ soc2014/op/freebsd-base/sys/kern/kern_selfpatch.c Fri Jul 18 16:08:27 2014 (r271085)
@@ -34,12 +34,16 @@
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/linker.h>
#include <sys/linker_set.h>
#include <sys/selfpatch.h>
#include <sys/sysctl.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
#include <machine/md_var.h>
#include <machine/specialreg.h>
@@ -135,13 +139,49 @@
void
lf_selfpatch_apply(linker_file_t lf, struct lf_selfpatch *p)
{
+ vm_paddr_t *pages;
+ vm_offset_t page_offset;
+ int i, page_number;
+
if (!lf_selfpatch_patch_needed(p))
return;
KASSERT(p->patch_size == p->patchable_size,
("%s: patch_size != patchable_size", __func__));
- DBG("%p\n", p->patch);
+ page_offset = (vm_offset_t)p->patchable & (vm_offset_t)PAGE_MASK;
+ page_number = (p->patchable_size >> PAGE_SHIFT) +
+ ((page_offset + p->patchable_size) > PAGE_SIZE ? 2 : 1);
+
+ pages = malloc(page_number, M_TEMP, M_WAITOK | M_ZERO);
+
+ DBG("change mapping attribute from RX to RWX\n");
+ for (i=0; i<page_number; i++) {
+ vm_paddr_t kva;
+
+ kva = trunc_page(p->patchable) + i * PAGE_SIZE;
+ pages[i] = pmap_kextract(kva);
+ pmap_kenter_attr(kva, pages[i], VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
+ }
+ DBG("done.\n");
+
+ DBG("patchable: %p\n", p->patchable);
+ DBG("patch: %p\n", p->patch);
+ DBG("patch size: %d\n", p->patchable_size);
memcpy(p->patchable, p->patch, p->patchable_size);
+
+ DBG("patched.\n");
+
+ DBG("change mapping attribute from RWX to RX:\n");
+ for (i=0; i<page_number; i++) {
+ vm_paddr_t kva;
+
+ kva = trunc_page(p->patchable) + i * PAGE_SIZE;
+ pmap_kenter_attr(kva, pages[i], VM_PROT_READ | VM_PROT_EXECUTE);
+ }
+ DBG("done.\n");
+
+ free(pages, M_TEMP);
}
+
Modified: soc2014/op/freebsd-base/sys/sys/selfpatch.h
==============================================================================
--- soc2014/op/freebsd-base/sys/sys/selfpatch.h Fri Jul 18 16:07:58 2014 (r271084)
+++ soc2014/op/freebsd-base/sys/sys/selfpatch.h Fri Jul 18 16:08:27 2014 (r271085)
@@ -34,8 +34,8 @@
struct linker_file_t;
typedef struct lf_selfpatch {
- void *patchable;
- void *patch;
+ char *patchable;
+ char *patch;
int patchable_size;
int patch_size;
int feature_selector;
More information about the svn-soc-all
mailing list