arch/addrenv: Change text write enable/disable to generic mprot

Implement a generic access rights modification procedure instead
of the procedures that only do one thing (enable/disable write)
to one section (text).
This commit is contained in:
Ville Juven
2022-05-12 11:55:50 +03:00
committed by Xiang Xiao
parent 072c28fe8e
commit 47e85b68fe
4 changed files with 71 additions and 88 deletions
+14 -25
View File
@@ -25,51 +25,40 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/compiler.h>
#include <sys/mman.h>
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: up_addrenv_text_enable_write * Name: up_addrenv_mprot
* *
* Description: * Description:
* Temporarily enable write access to the .text section. This must be * Modify access rights to an address range.
* called prior to loading the process code into memory.
* *
* Input Parameters: * Input Parameters:
* addrenv - The address environment to be modified. * addrenv - The address environment to be modified.
* addr - Base address of the region.
* len - Size of the region.
* prot - Access right flags.
* *
* Returned Value: * Returned Value:
* Zero (OK) on success; a negated errno value on failure. * Zero (OK) on success; a negated errno value on failure.
* *
****************************************************************************/ ****************************************************************************/
int up_addrenv_text_enable_write(group_addrenv_t *addrenv) int up_addrenv_mprot(group_addrenv_t *addrenv, uintptr_t addr, size_t len,
int prot)
{ {
/* Nothing needs to be done */ /* Nothing needs to be done */
return OK; UNUSED(addrenv);
} UNUSED(addr);
UNUSED(len);
/**************************************************************************** UNUSED(prot);
* Name: up_addrenv_text_disable_write
*
* Description:
* Disable write access to the .text section. This must be called after the
* process code is loaded into memory.
*
* Input Parameters:
* addrenv - The address environment to be modified.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int up_addrenv_text_disable_write(group_addrenv_t *addrenv)
{
/* Nothing needs to be done */
return OK; return OK;
} }
+38 -35
View File
@@ -33,15 +33,22 @@
#include <arch/barriers.h> #include <arch/barriers.h>
#include <sys/mman.h>
#include "pgalloc.h" #include "pgalloc.h"
#include "riscv_mmu.h" #include "riscv_mmu.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define CLR_MASK (PTE_R | PTE_W | PTE_X)
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
static int modify_region(uintptr_t vstart, uintptr_t vend, uintptr_t setmask, static int modify_region(uintptr_t vstart, uintptr_t vend, uintptr_t setmask)
uintptr_t clrmask)
{ {
uintptr_t l1vaddr; uintptr_t l1vaddr;
uintptr_t lnvaddr; uintptr_t lnvaddr;
@@ -78,7 +85,7 @@ static int modify_region(uintptr_t vstart, uintptr_t vend, uintptr_t setmask,
/* Get entry and modify the flags */ /* Get entry and modify the flags */
entry = mmu_ln_getentry(ptlevel, lnvaddr, vaddr); entry = mmu_ln_getentry(ptlevel, lnvaddr, vaddr);
entry &= ~clrmask; entry &= ~CLR_MASK;
entry |= setmask; entry |= setmask;
/* Restore the entry */ /* Restore the entry */
@@ -99,53 +106,49 @@ static int modify_region(uintptr_t vstart, uintptr_t vend, uintptr_t setmask,
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: up_addrenv_text_enable_write * Name: up_addrenv_mprot
* *
* Description: * Description:
* Temporarily enable write access to the .text section. This must be * Modify access rights to an address range.
* called prior to loading the process code into memory.
* *
* Input Parameters: * Input Parameters:
* addrenv - The address environment to be modified. * addrenv - The address environment to be modified.
* addr - Base address of the region.
* len - Size of the region.
* prot - Access right flags.
* *
* Returned Value: * Returned Value:
* Zero (OK) on success; a negated errno value on failure. * Zero (OK) on success; a negated errno value on failure.
* *
****************************************************************************/ ****************************************************************************/
int up_addrenv_text_enable_write(group_addrenv_t *addrenv) int up_addrenv_mprot(group_addrenv_t *addrenv, uintptr_t addr, size_t len,
int prot)
{ {
/* Sanity checks */ uintptr_t setmask;
uintptr_t vend;
DEBUGASSERT(addrenv); /* addrenv not needed by this implementation */
DEBUGASSERT(MM_ISALIGNED(addrenv->textvbase));
DEBUGASSERT(MM_ISALIGNED(addrenv->datavbase));
return modify_region(addrenv->textvbase, addrenv->datavbase, PTE_W, 0); UNUSED(addrenv);
setmask = 0;
vend = addr + MM_PGALIGNUP(len);
if (prot & PROT_READ)
{
setmask |= PTE_R;
} }
/**************************************************************************** if (prot & PROT_WRITE)
* Name: up_addrenv_text_disable_write
*
* Description:
* Disable write access to the .text section. This must be called after the
* process code is loaded into memory.
*
* Input Parameters:
* addrenv - The address environment to be modified.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int up_addrenv_text_disable_write(group_addrenv_t *addrenv)
{ {
/* Sanity checks */ setmask |= PTE_W;
}
DEBUGASSERT(addrenv);
DEBUGASSERT(MM_ISALIGNED(addrenv->textvbase)); if (prot & PROT_EXEC)
DEBUGASSERT(MM_ISALIGNED(addrenv->datavbase)); {
setmask |= PTE_X;
return modify_region(addrenv->textvbase, addrenv->datavbase, 0, PTE_W); }
return modify_region(addr, vend, setmask);
} }
+9 -2
View File
@@ -30,12 +30,17 @@
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include <sys/mman.h>
#include "libelf.h" #include "libelf.h"
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
#define ELF_TEXT_WRE (PROT_READ | PROT_WRITE | PROT_EXEC)
#define ELF_TEXT_WRD (PROT_READ | PROT_EXEC)
/**************************************************************************** /****************************************************************************
* Private Constant Data * Private Constant Data
****************************************************************************/ ****************************************************************************/
@@ -175,7 +180,8 @@ int elf_addrenv_select(FAR struct elf_loadinfo_s *loadinfo)
/* Allow write access to .text */ /* Allow write access to .text */
ret = up_addrenv_text_enable_write(&loadinfo->addrenv); ret = up_addrenv_mprot(&loadinfo->addrenv, loadinfo->textalloc,
loadinfo->textsize, ELF_TEXT_WRE);
if (ret < 0) if (ret < 0)
{ {
berr("ERROR: up_addrenv_text_enable_write failed: %d\n", ret); berr("ERROR: up_addrenv_text_enable_write failed: %d\n", ret);
@@ -207,7 +213,8 @@ int elf_addrenv_restore(FAR struct elf_loadinfo_s *loadinfo)
/* Remove write access to .text */ /* Remove write access to .text */
ret = up_addrenv_text_disable_write(&loadinfo->addrenv); ret = up_addrenv_mprot(&loadinfo->addrenv, loadinfo->textalloc,
loadinfo->textsize, ELF_TEXT_WRD);
if (ret < 0) if (ret < 0)
{ {
berr("ERROR: up_addrenv_text_disable_write failed: %d\n", ret); berr("ERROR: up_addrenv_text_disable_write failed: %d\n", ret);
+7 -23
View File
@@ -1186,14 +1186,16 @@ int up_addrenv_detach(FAR struct task_group_s *group, FAR struct tcb_s *tcb);
#endif #endif
/**************************************************************************** /****************************************************************************
* Name: up_addrenv_text_enable_write * Name: up_addrenv_mprot
* *
* Description: * Description:
* Temporarily enable write access to the .text section. This must be * Modify access rights to an address range.
* called prior to loading the process code into memory.
* *
* Input Parameters: * Input Parameters:
* addrenv - The address environment to be modified. * addrenv - The address environment to be modified.
* addr - Base address of the region.
* len - Size of the region.
* prot - Access right flags.
* *
* Returned Value: * Returned Value:
* Zero (OK) on success; a negated errno value on failure. * Zero (OK) on success; a negated errno value on failure.
@@ -1201,26 +1203,8 @@ int up_addrenv_detach(FAR struct task_group_s *group, FAR struct tcb_s *tcb);
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV #ifdef CONFIG_ARCH_ADDRENV
int up_addrenv_text_enable_write(FAR group_addrenv_t *addrenv); int up_addrenv_mprot(group_addrenv_t *addrenv, uintptr_t addr, size_t len,
#endif int prot);
/****************************************************************************
* Name: up_addrenv_text_disable_write
*
* Description:
* Disable write access to the .text section. This must be called after the
* process code is loaded into memory.
*
* Input Parameters:
* addrenv - The address environment to be modified.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
int up_addrenv_text_disable_write(FAR group_addrenv_t *addrenv);
#endif #endif
/**************************************************************************** /****************************************************************************