Provide KPI for handling of rw/ro kernel text.
This is a pure syntax patch to create an interface to enable and later restore write access to the kernel text and other read-only mapped regions. It is in line with e.g. vm_fault_disable_pagefaults() by allowing the nesting. Discussed with: Peter Lei <peter.lei@ieee.org> Reviewed by: jtl Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D14768
This commit is contained in:
parent
eef279cefd
commit
60e489a73d
@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/pcpu.h>
|
||||
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/specialreg.h>
|
||||
|
||||
#include <ddb/ddb.h>
|
||||
@ -75,19 +76,19 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data)
|
||||
jmp_buf jb;
|
||||
void *prev_jb;
|
||||
char *dst;
|
||||
u_long cr0save;
|
||||
bool old_wp;
|
||||
int ret;
|
||||
|
||||
cr0save = rcr0();
|
||||
old_wp = false;
|
||||
prev_jb = kdb_jmpbuf(jb);
|
||||
ret = setjmp(jb);
|
||||
if (ret == 0) {
|
||||
load_cr0(cr0save & ~CR0_WP);
|
||||
old_wp = disable_wp();
|
||||
dst = (char *)addr;
|
||||
while (size-- > 0)
|
||||
*dst++ = *data++;
|
||||
}
|
||||
load_cr0(cr0save);
|
||||
restore_wp(old_wp);
|
||||
(void)kdb_jmpbuf(prev_jb);
|
||||
return (ret);
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/frame.h>
|
||||
#include <machine/gdb_machdep.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/psl.h>
|
||||
#include <machine/reg.h>
|
||||
@ -127,17 +128,14 @@ gdb_cpu_signal(int type, int code)
|
||||
void *
|
||||
gdb_begin_write(void)
|
||||
{
|
||||
u_long cr0save;
|
||||
|
||||
cr0save = rcr0();
|
||||
load_cr0(cr0save & ~CR0_WP);
|
||||
return ((void *)cr0save);
|
||||
return (disable_wp() ? &gdb_begin_write : NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gdb_end_write(void *arg)
|
||||
{
|
||||
|
||||
load_cr0((u_long)arg);
|
||||
restore_wp(arg != NULL);
|
||||
}
|
||||
|
||||
|
@ -2597,6 +2597,31 @@ clear_pcb_flags(struct pcb *pcb, const u_int flags)
|
||||
: "cc", "memory");
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable and restore kernel text write permissions.
|
||||
* Callers must ensure that disable_wp()/restore_wp() are executed
|
||||
* without rescheduling on the same core.
|
||||
*/
|
||||
bool
|
||||
disable_wp(void)
|
||||
{
|
||||
u_int cr0;
|
||||
|
||||
cr0 = rcr0();
|
||||
if ((cr0 & CR0_WP) == 0)
|
||||
return (false);
|
||||
load_cr0(cr0 & ~CR0_WP);
|
||||
return (true);
|
||||
}
|
||||
|
||||
void
|
||||
restore_wp(bool old_wp)
|
||||
{
|
||||
|
||||
if (old_wp)
|
||||
load_cr0(rcr0() | CR0_WP);
|
||||
}
|
||||
|
||||
#ifdef KDB
|
||||
|
||||
/*
|
||||
|
@ -53,6 +53,8 @@ void amd64_conf_fast_syscall(void);
|
||||
void amd64_db_resume_dbreg(void);
|
||||
void amd64_lower_shared_page(struct sysentvec *);
|
||||
void amd64_syscall(struct thread *td, int traced);
|
||||
bool disable_wp(void);
|
||||
void restore_wp(bool old_wp);
|
||||
void doreti_iret(void) __asm(__STRING(doreti_iret));
|
||||
void doreti_iret_fault(void) __asm(__STRING(doreti_iret_fault));
|
||||
void ld_ds(void) __asm(__STRING(ld_ds));
|
||||
|
Loading…
Reference in New Issue
Block a user