socsvn commit: r272131 - in soc2014/op/freebsd-base/sys: kern sys
op at FreeBSD.org
op at FreeBSD.org
Sat Aug 9 15:33:13 UTC 2014
Author: op
Date: Sat Aug 9 15:33:11 2014
New Revision: 272131
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=272131
Log:
KSP: check securelevel before do anything
Signed-off-by: Oliver Pinter <oliver.pntr at gmail.com>
git: https://github.com/opntr/opBSD/tree/op/gsoc2014/smap+kpatch
Modified:
soc2014/op/freebsd-base/sys/kern/kern_linker.c
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_linker.c
==============================================================================
--- soc2014/op/freebsd-base/sys/kern/kern_linker.c Sat Aug 9 15:33:02 2014 (r272130)
+++ soc2014/op/freebsd-base/sys/kern/kern_linker.c Sat Aug 9 15:33:11 2014 (r272131)
@@ -421,7 +421,11 @@
return (error);
}
modules = !TAILQ_EMPTY(&lf->modules);
- lf_selfpatch(lf, KSP_MODULE);
+ error = lf_selfpatch(lf, KSP_MODULE);
+ if (error != 0) {
+ linker_file_unload(lf, LINKER_UNLOAD_FORCE);
+ return (error);
+ }
linker_file_register_sysctls(lf);
linker_file_sysinit(lf);
lf->flags |= LINKER_FILE_LINKED;
@@ -1611,7 +1615,12 @@
}
linker_file_register_modules(lf);
/* XXXOP */
- lf_selfpatch(lf, KSP_MODULE);
+ error = lf_selfpatch(lf, KSP_MODULE);
+ if (error != 0) {
+ printf("KLD file %s - could not selfpatching\n",
+ lf->filename);
+ goto fail;
+ }
if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
&si_stop, NULL) == 0)
sysinit_add(si_start, si_stop);
Modified: soc2014/op/freebsd-base/sys/kern/kern_selfpatch.c
==============================================================================
--- soc2014/op/freebsd-base/sys/kern/kern_selfpatch.c Sat Aug 9 15:33:02 2014 (r272130)
+++ soc2014/op/freebsd-base/sys/kern/kern_selfpatch.c Sat Aug 9 15:33:11 2014 (r272131)
@@ -36,6 +36,7 @@
#include <sys/kernel.h>
#include <sys/malloc.h>
+#include <sys/jail.h>
#include <sys/linker.h>
#include <sys/linker_set.h>
#include <sys/selfpatch.h>
@@ -115,7 +116,7 @@
return (false);
}
-void
+int
lf_selfpatch(linker_file_t lf, int mod)
{
struct lf_selfpatch *patch, *start, *stop;
@@ -128,7 +129,7 @@
ret = linker_file_lookup_set(lf, "selfpatch_set", &start, &stop, NULL);
if (ret != 0) {
DBG("failed to locate selfpatch_set\n");
- return;
+ return (0);
}
DBG("start: %p stop: %p\n", start, stop);
} else {
@@ -143,25 +144,36 @@
for (patch = start; patch != stop; patch++) {
DBG("apply: %p\n", patch);
- if (mod == KSP_MODULE)
- lf_selfpatch_apply_module(lf, patch);
- else
- lf_selfpatch_apply(lf, 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);
+ }
}
/*
* when selfpatch does not works, the system should crash
*/
lf_selfpatch_selftest();
+
+ return (0);
}
-void
+int
lf_selfpatch_apply(linker_file_t lf, struct lf_selfpatch *p)
{
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)
+ return (EPERM);
+
DBG("patchable: %p\n", p->patchable);
DBG("patch: %p\n", p->patch);
DBG("feature selector: %d\n", p->feature_selector);
@@ -173,7 +185,7 @@
if (!lf_selfpatch_patch_needed(p)) {
DBG("not needed.\n");
- return;
+ return (0);
}
if (p->patch_size != p->patchable_size)
@@ -212,12 +224,18 @@
pmap_kenter_attr(kva, pages[i], VM_PROT_READ | VM_PROT_EXECUTE);
}
DBG("done.\n");
+
+ return (0);
}
-void
+int
lf_selfpatch_apply_module(linker_file_t lf, struct lf_selfpatch *p)
{
+ /* 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);
@@ -229,7 +247,7 @@
if (!lf_selfpatch_patch_needed(p)) {
DBG("not needed.\n");
- return;
+ return (0);
}
if (p->patch_size != p->patchable_size)
@@ -238,6 +256,8 @@
memcpy(p->patchable, p->patch, p->patchable_size);
DBG("patched.\n");
+
+ return (0);
}
__noinline void
Modified: soc2014/op/freebsd-base/sys/sys/selfpatch.h
==============================================================================
--- soc2014/op/freebsd-base/sys/sys/selfpatch.h Sat Aug 9 15:33:02 2014 (r272130)
+++ soc2014/op/freebsd-base/sys/sys/selfpatch.h Sat Aug 9 15:33:11 2014 (r272131)
@@ -52,8 +52,8 @@
extern char *selfpatch_nop_table[];
-void lf_selfpatch(linker_file_t lf, int mod);
-void lf_selfpatch_apply(linker_file_t lf, struct lf_selfpatch *patch);
-void lf_selfpatch_apply_module(linker_file_t lf, struct lf_selfpatch *patch);
+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);
#endif /* __SELFPATH_H__ */
More information about the svn-soc-all
mailing list