Date: Tue, 12 Aug 2014 22:38:52 GMT From: op@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r272309 - in soc2014/op/freebsd-base/sys: kern sys Message-ID: <201408122238.s7CMcqno019658@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: op Date: Tue Aug 12 22:38:52 2014 New Revision: 272309 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=272309 Log: KSP: fixed panic on module unload case, and added stubs for protection changes currently protection changes are unneeded, because the whole kernel image mappad with RWX protection... Signed-off-by: Oliver Pinter <oliver.pntr@gmail.com> git: https://github.com/opntr/opBSD/tree/op/gsoc2014/smap+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 Tue Aug 12 21:51:31 2014 (r272308) +++ soc2014/op/freebsd-base/sys/kern/kern_selfpatch.c Tue Aug 12 22:38:52 2014 (r272309) @@ -65,6 +65,11 @@ __noinline void lf_selfpatch_selftest(void); #endif +static void lf_open_kernel_text(struct lf_selfpatch *p); +static void lf_close_kernel_text(struct lf_selfpatch *p); +static void lf_open_module_text(struct lf_selfpatch *p); +static void lf_close_module_text(struct lf_selfpatch *p); + bool lf_selfpatch_patch_needed(struct lf_selfpatch *p) { @@ -127,15 +132,9 @@ for (patch = start; patch != stop; patch++) { DBG("apply: %p\n", patch); - if (mod == KSP_MODULE) { - ret = lf_selfpatch_apply_module(lf, patch); - if (ret != 0) - return (ret); - } else { - ret = lf_selfpatch_apply(lf, patch); - if (ret != 0) - return (ret); - } + ret = lf_selfpatch_apply(lf, patch, mod); + if (ret != 0) + return (ret); } #ifdef KSP_DEBUG @@ -149,11 +148,8 @@ } int -lf_selfpatch_apply(linker_file_t lf, struct lf_selfpatch *p) +lf_selfpatch_apply(linker_file_t lf, struct lf_selfpatch *p, int mod) { - vm_paddr_t pages[4]; - vm_offset_t page_offset; - int i, page_number; /* Refuse to patch if securelevel raised */ if (prison0.pr_securelevel > 0) @@ -176,77 +172,94 @@ if (p->patch_size != p->patchable_size) panic("%s: patch_size != patchable_size", __func__); - 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); - - DBG("page_number: %d\n", page_number); - - KASSERT(page_number < 4, - ("patch size longer than 3 page does not supported yet\n")); - - DBG("change mapping attribute from RX to RWX:\n"); - for (i=0; i<page_number; i++) { - vm_paddr_t kva; + /* + * open the kernel text + * currently this is a dummy function, because the kernel protection + * is RWX now. + */ + if (mod == KSP_MODULE) + lf_open_module_text(p); + else + lf_open_kernel_text(p); - kva = trunc_page(p->patchable) + i * PAGE_SIZE; - pages[i] = pmap_kextract(kva); + /* + * replace the instructions + */ + memcpy(p->patchable, p->patch, p->patchable_size); - DBG("kva: %p page: %p\n", (void *)kva, (void *)pages[i]); -#ifdef NOT_THE_RIGHT_API - pmap_kenter_attr(kva, pages[i], VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); -#endif - } - DBG("done.\n"); + if (mod == KSP_MODULE) + lf_close_module_text(p); + else + lf_close_kernel_text(p); - 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; -#ifdef NOT_THE_RIGHT_API - pmap_kenter_attr(kva, pages[i], VM_PROT_READ | VM_PROT_EXECUTE); -#endif - } - DBG("done.\n"); - return (0); } -int -lf_selfpatch_apply_module(linker_file_t lf, struct lf_selfpatch *p) +static void +lf_open_kernel_text(struct lf_selfpatch *p) { + /* + * dummy function, currently unused becasue the kernel + * protection is RWX + */ +#if 0 + pmap_protect(kernel_pmap, sva, eva, + VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); +#endif +} - /* Refuse to patch if securelevel raised */ - if (prison0.pr_securelevel > 0) - return (EPERM); - - DBG("patchable: %p\n", p->patchable); - DBG("patch: %p\n", p->patch); - DBG("feature selector: %d\n", p->feature_selector); - DBG("feature: %d\n", p->feature); - DBG("patchable size: %d\n", p->patchable_size); - DBG("patch size: %d\n", p->patch_size); - DBG("comment: %s\n", p->comment); - - if (!lf_selfpatch_patch_needed(p)) { - DBG("not needed.\n"); - - return (0); - } +static void +lf_close_kernel_text(struct lf_selfpatch *p) +{ + /* + * dummy function, currently unused becasue the kernel + * protection is RWX + * + * currently flushes the cache after modification + */ +#if 0 + pmap_protect(kernel_pmap, sva, eva, + VM_PROT_READ | VM_PROT_EXECUTE); +#endif - if (p->patch_size != p->patchable_size) - panic("%s: patch_size != patchable_size", __func__); + /* Flushes caches and TLBs. */ + wbinvd(); + invltlb(); +} - memcpy(p->patchable, p->patch, p->patchable_size); +static void +lf_open_module_text(struct lf_selfpatch *p) +{ + /* + * dummy function, currently unused becasue the kernel + * protection is RWX + */ +#if 0 + pmap_protect(module_pmap, sva, eva, + VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); +#endif +} - DBG("patched.\n"); +static void +lf_close_module_text(struct lf_selfpatch *p) +{ + /* + * dummy function, currently unused becasue the kernel + * protection is RWX + * + * currently flushes the cache after modification + */ +#if 0 + pmap_protect(module_pmap, sva, eva, + VM_PROT_READ | VM_PROT_EXECUTE); +#endif - return (0); + /* Flushes caches and TLBs. */ + wbinvd(); + invltlb(); } #ifdef KSP_DEBUG Modified: soc2014/op/freebsd-base/sys/sys/selfpatch.h ============================================================================== --- soc2014/op/freebsd-base/sys/sys/selfpatch.h Tue Aug 12 21:51:31 2014 (r272308) +++ soc2014/op/freebsd-base/sys/sys/selfpatch.h Tue Aug 12 22:38:52 2014 (r272309) @@ -63,7 +63,6 @@ extern char *selfpatch_nop_table[]; int lf_selfpatch(linker_file_t lf, int mod); -int lf_selfpatch_apply(linker_file_t lf, struct lf_selfpatch *patch); -int lf_selfpatch_apply_module(linker_file_t lf, struct lf_selfpatch *patch); +int lf_selfpatch_apply(linker_file_t lf, struct lf_selfpatch *patch, int mod); #endif /* __SELFPATH_H__ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201408122238.s7CMcqno019658>