summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorHanhui <sylixos@gmail.com>2019-07-25 13:39:55 (GMT)
committer Hanhui <sylixos@gmail.com>2019-07-15 14:38:39 (GMT)
commitad9b3408c4bb6150af4204edec32ebeece8f2ee2 (patch)
treed7fb6e8d89d7af9cf67518ded83aa00d411c2d08
parentfeb2f552df2085a6d8b34a63a0f1ca139966ab40 (diff)
downloadAIC-OS-ad9b3408c4bb6150af4204edec32ebeece8f2ee2.zip
Loader support TEXT segment write protect.
-rw-r--r--SylixOS/arch/mips/common/mipsExc.c22
-rw-r--r--SylixOS/arch/mips/mm/mmu/mipsMmuCommon.c5
-rw-r--r--SylixOS/config/loader/loader_cfg.h1
-rw-r--r--SylixOS/kernel/include/k_const.h16
-rw-r--r--SylixOS/kernel/include/k_kernel.h2
-rw-r--r--SylixOS/kernel/interface/KernelParam.c10
-rw-r--r--SylixOS/kernel/vmm/pageLib.c2
-rw-r--r--SylixOS/kernel/vmm/pageTable.c9
-rw-r--r--SylixOS/kernel/vmm/vmm.h4
-rw-r--r--SylixOS/kernel/vmm/vmmAbort.c32
-rw-r--r--SylixOS/kernel/vmm/vmmMalloc.c49
-rw-r--r--SylixOS/kernel/vmm/vmmSwap.h5
-rw-r--r--SylixOS/loader/elf/elf_loader.c15
-rw-r--r--SylixOS/loader/include/loader_lib.h12
-rw-r--r--SylixOS/loader/src/loader.c92
-rw-r--r--SylixOS/loader/src/loader_malloc.c16
-rw-r--r--SylixOS/loader/src/loader_shell.c10
-rw-r--r--SylixOS/net/lwip/src/api/api_msg.c4
-rw-r--r--SylixOS/shell/ttinyShell/ttinyShellLib.c6
19 files changed, 248 insertions, 64 deletions
diff --git a/SylixOS/arch/mips/common/mipsExc.c b/SylixOS/arch/mips/common/mipsExc.c
index 4c68836..42e070f 100644
--- a/SylixOS/arch/mips/common/mipsExc.c
+++ b/SylixOS/arch/mips/common/mipsExc.c
@@ -708,6 +708,26 @@ static VOID archDefaultExceptHandle (addr_t ulRetAddr, addr_t ulAbortAddr)
API_VmmAbortIsr(ulRetAddr, ulAbortAddr, &abtInfo, ptcbCur);
}
/*********************************************************************************************************
+** 函数名称: archExecInhibitExceptHandle
+** 功能描述: 执行禁止的异常处理
+** 输 入 : ulRetAddr 返回地址
+** ulAbortAddr 终止地址
+** 输 出 : NONE
+** 全局变量:
+** 调用模块:
+*********************************************************************************************************/
+static VOID archExecInhibitExceptHandle (addr_t ulRetAddr, addr_t ulAbortAddr)
+{
+ PLW_CLASS_TCB ptcbCur;
+ LW_VMM_ABORT abtInfo;
+
+ LW_TCB_GET_CUR(ptcbCur);
+
+ abtInfo.VMABT_uiMethod = LW_VMM_ABORT_METHOD_EXEC;
+ abtInfo.VMABT_uiType = LW_VMM_ABORT_TYPE_PERM;
+ API_VmmAbortIsr(ulRetAddr, ulAbortAddr, &abtInfo, ptcbCur);
+}
+/*********************************************************************************************************
** 函数名称: archMachineCheckExceptHandle
** 功能描述: 机器检查异常处理
** 输 入 : ulRetAddr 返回地址
@@ -760,7 +780,7 @@ static MIPS_EXCEPT_HANDLE _G_mipsExceptHandle[32] = {
* 读阻止例外没使能, 执行阻止例外复用 TLBL 例外
*/
[EXCCODE_TLBRI] = (PVOID)archDefaultExceptHandle, /* TLB Read-Inhibit exception */
- [EXCCODE_TLBXI] = (PVOID)archDefaultExceptHandle, /* TLB Exec-Inhibit exception */
+ [EXCCODE_TLBXI] = (PVOID)archExecInhibitExceptHandle, /* TLB Exec-Inhibit exception */
[EXCCODE_MSADIS] = (PVOID)archDefaultExceptHandle, /* MSA disabled exception */
[EXCCODE_MDMX] = (PVOID)archDefaultExceptHandle, /* MDMX unusable exception */
[EXCCODE_WATCH] = (PVOID)archDefaultExceptHandle, /* Watch address reference */
diff --git a/SylixOS/arch/mips/mm/mmu/mipsMmuCommon.c b/SylixOS/arch/mips/mm/mmu/mipsMmuCommon.c
index c78fa5f..977fa72 100644
--- a/SylixOS/arch/mips/mm/mmu/mipsMmuCommon.c
+++ b/SylixOS/arch/mips/mm/mmu/mipsMmuCommon.c
@@ -215,8 +215,9 @@ static INT mipsMmuGlobalInit (CPCHAR pcMachineName)
#if LW_CFG_CPU_WORD_LENGHT == 64
PG_ELPA | /* 支持 48 位物理地址 */
#endif
- PG_XIE); /* 使能 EntryLo 执行阻止位 */
- /* 执行阻止例外复用 TLBL 例外 */
+ PG_XIE | /* 使能 EntryLo 执行阻止位 */
+ PG_IEC); /* 执行阻止例外在 TLBXI 例外 */
+
/*
* 目前为了通用性, 并没有使能个别处理器(GS264, GS464E, 华睿, 君正)才有的读阻止 RI 位,
* 而是使用 ENTRYLO_V 位来判断映射是否有效
diff --git a/SylixOS/config/loader/loader_cfg.h b/SylixOS/config/loader/loader_cfg.h
index 0424370..6c2fada 100644
--- a/SylixOS/config/loader/loader_cfg.h
+++ b/SylixOS/config/loader/loader_cfg.h
@@ -44,6 +44,7 @@
#define LW_CFG_MODULELOADER_GCOV_EN 1 /* 内核模块代码覆盖率分析接口 */
#define LW_CFG_MODULELOADER_ATEXIT_EN 0 /* 是否允许内核模块 atexit() */
#define LW_CFG_MODULELOADER_FPUCHK_EN 0 /* 是否强行检查 FPU 设置兼容性 */
+#define LW_CFG_MODULELOADER_TEXT_RO_EN 0 /* TEXT 段写保护 */
#define LW_CFG_MODULELOADER_RMMOD_ATREBOOT_EN 0 /* 重启时卸载所有模块 */
#define LW_CFG_MODULELOADER_STRONGSYM_FIRST_EN 0 /* 搜索模块符号时是否优先强符号*/
/* 建议为 0 与其他操作系统一致 */
diff --git a/SylixOS/kernel/include/k_const.h b/SylixOS/kernel/include/k_const.h
index e656c4f..25472c3 100644
--- a/SylixOS/kernel/include/k_const.h
+++ b/SylixOS/kernel/include/k_const.h
@@ -76,6 +76,8 @@
#define LW_KERN_FLAG_AUTO_REC_TCB 0x0100 /* 自动回收 TCB 兼容 1.9.7 之前*/
/* 版本, 非 detach 线程删除后 */
/* 立即释放 TCB */
+#define LW_KERN_FLAG_TEXT_RO 0x0200 /* 内核 TEXT 只读 */
+
/*********************************************************************************************************
内核是否支持浮点状态
*********************************************************************************************************/
@@ -205,6 +207,20 @@
#define LW_KERN_AUTO_REC_TCB_GET() (_K_ulKernFlags & LW_KERN_FLAG_AUTO_REC_TCB)
/*********************************************************************************************************
+ 内核代码段只读
+*********************************************************************************************************/
+
+#define LW_KERN_TEXT_RO_SET(en) \
+ do { \
+ if (en) { \
+ _K_ulKernFlags |= LW_KERN_FLAG_TEXT_RO; \
+ } else { \
+ _K_ulKernFlags &= ~LW_KERN_FLAG_TEXT_RO; \
+ } \
+ } while (0)
+#define LW_KERN_TEXT_RO_GET() (_K_ulKernFlags & LW_KERN_FLAG_TEXT_RO)
+
+/*********************************************************************************************************
系统状态
*********************************************************************************************************/
diff --git a/SylixOS/kernel/include/k_kernel.h b/SylixOS/kernel/include/k_kernel.h
index ed44732..d9d0eec 100644
--- a/SylixOS/kernel/include/k_kernel.h
+++ b/SylixOS/kernel/include/k_kernel.h
@@ -51,7 +51,7 @@
#define __SYLIXOS_MAJOR_VER 1
#define __SYLIXOS_MINOR_VER 10
-#define __SYLIXOS_PATCH_VER 2
+#define __SYLIXOS_PATCH_VER 3
#define __SYLIXOS_PATCH_PAD 0
/*********************************************************************************************************
diff --git a/SylixOS/kernel/interface/KernelParam.c b/SylixOS/kernel/interface/KernelParam.c
index dfc67f1..bb60de2 100644
--- a/SylixOS/kernel/interface/KernelParam.c
+++ b/SylixOS/kernel/interface/KernelParam.c
@@ -57,6 +57,7 @@ extern LW_API INT API_RootFsMapInit(CPCHAR pcMap);
建议 Lite 类型处理器可采用 simple 转换法.
netlockfifo=no 网络互斥锁使用 FIFO 顺序等待.
autorectcb=no POSIX 非 detach 线程删除后, 是否不等待 join 或 detach 自动删除 TCB
+ textro=no Kernel TEXT 端只读
rfsmap=/boot:[*],/:[*],... 这是根文件系统映射关系选项, 用逗号隔开,
/boot /etc /tmp /apps ... 为可选映射,
@@ -246,8 +247,15 @@ ULONG API_KernelStartParam (CPCHAR pcParam)
} else {
LW_KERN_AUTO_REC_TCB_SET(LW_TRUE);
}
+
+ } else if (lib_strncmp(pcTok, "textro=", 7) == 0) { /* 自动删除 TCB */
+ if (pcTok[7] == 'n') {
+ LW_KERN_TEXT_RO_SET(LW_FALSE);
+ } else {
+ LW_KERN_TEXT_RO_SET(LW_TRUE);
+ }
}
-
+
#if LW_CFG_DEVICE_EN > 0
else if (lib_strncmp(pcTok, "rfsmap=", 7) == 0) { /* 根文件系统映射 */
API_RootFsMapInit(&pcTok[7]);
diff --git a/SylixOS/kernel/vmm/pageLib.c b/SylixOS/kernel/vmm/pageLib.c
index c4add0b..c1b2f3c 100644
--- a/SylixOS/kernel/vmm/pageLib.c
+++ b/SylixOS/kernel/vmm/pageLib.c
@@ -649,7 +649,7 @@ ULONG __pageExpand (PLW_VMM_PAGE pvmpage,
}
/*********************************************************************************************************
** 函数名称: __pageSplit
-** 功能描述: 将一个虚拟页面控制块分离成两个
+** 功能描述: 将一个连续页面控制块分离成两个
** 输 入 : pvmpage 主页面控制块
** ppvmpageSplit 被分离出的页面控制块
** ulPageNum pvmpage 需要保留的页面个数, 剩余部分将分配给 pvmpageSplit.
diff --git a/SylixOS/kernel/vmm/pageTable.c b/SylixOS/kernel/vmm/pageTable.c
index cbacf74..d5171d5 100644
--- a/SylixOS/kernel/vmm/pageTable.c
+++ b/SylixOS/kernel/vmm/pageTable.c
@@ -230,6 +230,13 @@ static INT __vmmLibGlobalMap (PLW_MMU_CONTEXT pmmuctx, LW_MMU_PHYSICAL_DESC
INT i;
ULONG ulError;
ULONG ulPageNum;
+ ULONG ulTextFlags;
+
+ if (LW_KERN_TEXT_RO_GET()) {
+ ulTextFlags = LW_VMM_FLAG_EXEC | LW_VMM_FLAG_READ;
+ } else {
+ ulTextFlags = LW_VMM_FLAG_EXEC | LW_VMM_FLAG_RDWR;
+ }
for (i = 0; pphydesc[i].PHYD_stSize; i++) {
if ((pphydesc[i].PHYD_uiType == LW_PHYSICAL_MEM_BUSPOOL) ||
@@ -253,7 +260,7 @@ static INT __vmmLibGlobalMap (PLW_MMU_CONTEXT pmmuctx, LW_MMU_PHYSICAL_DESC
case LW_PHYSICAL_MEM_TEXT:
ulError = __vmmLibPageMap(pphydesc[i].PHYD_ulPhyAddr,
pphydesc[i].PHYD_ulVirMap,
- ulPageNum, LW_VMM_FLAG_EXEC | LW_VMM_FLAG_RDWR);
+ ulPageNum, ulTextFlags);
break;
case LW_PHYSICAL_MEM_DATA:
diff --git a/SylixOS/kernel/vmm/vmm.h b/SylixOS/kernel/vmm/vmm.h
index 37f7dc5..2de94c3 100644
--- a/SylixOS/kernel/vmm/vmm.h
+++ b/SylixOS/kernel/vmm/vmm.h
@@ -216,6 +216,10 @@ LW_API ULONG API_VmmSetFiller(PVOID pvVirtualMem, FUNCPTR pfuncFiller,
/* 设置填充函数 */
LW_API ULONG API_VmmSetFindShare(PVOID pvVirtualMem, PVOIDFUNCPTR pfuncFindShare, PVOID pvArg);
/* 设置查询共享函数 */
+#if LW_CFG_MODULELOADER_TEXT_RO_EN > 0
+LW_API ULONG API_VmmSetProtect(PVOID pvVirtualMem, PVOID pvSubMem, size_t stSize);
+#endif /* 设置禁止 copy-on-write 区 */
+
LW_API ULONG API_VmmPreallocArea(PVOID pvVirtualMem,
PVOID pvSubMem,
size_t stSize,
diff --git a/SylixOS/kernel/vmm/vmmAbort.c b/SylixOS/kernel/vmm/vmmAbort.c
index 3781c3d..7d61b2a 100644
--- a/SylixOS/kernel/vmm/vmmAbort.c
+++ b/SylixOS/kernel/vmm/vmmAbort.c
@@ -263,22 +263,42 @@ static INT __vmmAbortCopyOnWrite (PLW_VMM_PAGE pvmpageVirtual, addr_t ulAbort
** 函数名称: __vmmAbortWriteProtect
** 功能描述: 发生写保护中止
** 输 入 : pvmpageVirtual 虚拟空间
-** ulAbortAddrAlign 异常的地址
+** ulAbortAddr 异常的地址
** ulFlag 页面属性
+** ptcbCur 当前任务控制块
** 输 出 : 是否成功
** 全局变量:
** 调用模块:
** 注 意 :
*********************************************************************************************************/
-static INT __vmmAbortWriteProtect (PLW_VMM_PAGE pvmpageVirtual,
- addr_t ulAbortAddrAlign,
- ULONG ulFlag)
+static INT __vmmAbortWriteProtect (PLW_VMM_PAGE pvmpageVirtual,
+ addr_t ulAbortAddr,
+ ULONG ulFlag,
+ PLW_CLASS_TCB ptcbCur)
{
+ addr_t ulAbortAddrAlign = ulAbortAddr & LW_CFG_VMM_PAGE_MASK;
+
+#if LW_CFG_MODULELOADER_TEXT_RO_EN > 0
+ PLW_VMM_PAGE_PRIVATE pvmpagep;
+#endif /* LW_CFG_MODULELOADER_TEXT... */
+
if (ulFlag & LW_VMM_FLAG_WRITABLE) {
return (ERROR_NONE); /* 可能其他任务同时访问此地址 */
}
if (pvmpageVirtual->PAGE_ulFlags & LW_VMM_FLAG_WRITABLE) { /* 虚拟空间允许写操作 */
+#if LW_CFG_MODULELOADER_TEXT_RO_EN > 0
+ pvmpagep = (PLW_VMM_PAGE_PRIVATE)pvmpageVirtual->PAGE_pvAreaCb;
+ if (pvmpagep && pvmpagep->PAGEP_stPtSize) {
+ if ((ulAbortAddr >= pvmpagep->PAGEP_ulPtStart) ||
+ (ulAbortAddr < (pvmpagep->PAGEP_ulPtStart + pvmpagep->PAGEP_stPtSize))) {
+ if (ptcbCur->TCB_pvVProcessContext) { /* 进程内修改保护段 */
+ return (PX_ERROR); /* 杀死任务, 内存不可写 */
+ }
+ }
+ }
+#endif /* LW_CFG_MODULELOADER_TEXT... */
+
return (__vmmAbortCopyOnWrite(pvmpageVirtual,
ulAbortAddrAlign)); /* copy-on-write */
}
@@ -623,8 +643,8 @@ static VOID __vmmAbortShell (PLW_VMM_PAGE_FAIL_CTX pvmpagefailctx)
if (__PAGEFAILCTX_ABORT_METHOD(pvmpagefailctx) ==
LW_VMM_ABORT_METHOD_WRITE) { /* 写入异常 */
if (__vmmAbortWriteProtect(pvmpageVirtual, /* 尝试 copy-on-write 处理 */
- ulVirtualPageAlign,
- ulError) == ERROR_NONE) { /* 进入写保护处理 */
+ ulAbortAddr,
+ ulFlag, ptcbCur) == ERROR_NONE) {/* 进入写保护处理 */
__VMM_UNLOCK();
goto __abort_return;
}
diff --git a/SylixOS/kernel/vmm/vmmMalloc.c b/SylixOS/kernel/vmm/vmmMalloc.c
index 738f48b..ba6e234 100644
--- a/SylixOS/kernel/vmm/vmmMalloc.c
+++ b/SylixOS/kernel/vmm/vmmMalloc.c
@@ -493,6 +493,11 @@ PVOID API_VmmMallocAreaAlign (size_t stSize, size_t stAlign,
return (LW_NULL);
}
+#if LW_CFG_MODULELOADER_TEXT_RO_EN > 0
+ pvmpagep->PAGEP_ulPtStart = 0;
+ pvmpagep->PAGEP_stPtSize = 0;
+#endif /* LW_CFG_MODULELOADER_TEXT... */
+
pvmpagep->PAGEP_pfuncFiller = pfuncFiller;
pvmpagep->PAGEP_pvArg = pvArg;
@@ -925,6 +930,50 @@ ULONG API_VmmSetFindShare (PVOID pvVirtualMem, PVOIDFUNCPTR pfuncFindShare, P
return (ERROR_NONE);
}
/*********************************************************************************************************
+** 函数名称: API_VmmSetProtect
+** 功能描述: 设置虚拟空间受保护区域.
+** 输 入 : pvVirtualMem 连续虚拟地址 (必须为 vmmMallocArea 返回地址)
+** pvSubMem 当出现缺页时, 不允许 copy-on-write 的保护区起始地址
+** stSize 保护区大小.
+** 输 出 : ERROR CODE
+** 全局变量:
+** 调用模块:
+ API 函数
+*********************************************************************************************************/
+#if LW_CFG_MODULELOADER_TEXT_RO_EN > 0
+
+LW_API
+ULONG API_VmmSetProtect (PVOID pvVirtualMem, PVOID pvSubMem, size_t stSize)
+{
+ REGISTER PLW_VMM_PAGE pvmpageVirtual;
+ REGISTER PLW_VMM_PAGE_PRIVATE pvmpagep;
+ addr_t ulAddr = (addr_t)pvVirtualMem;
+
+ __VMM_LOCK();
+ pvmpageVirtual = __areaVirtualSearchPage(ulAddr);
+ if (pvmpageVirtual == LW_NULL) {
+ __VMM_UNLOCK();
+ _ErrorHandle(ERROR_VMM_VIRTUAL_PAGE); /* 无法反向查询虚拟页面控制块 */
+ return (ERROR_VMM_VIRTUAL_PAGE);
+ }
+
+ pvmpagep = (PLW_VMM_PAGE_PRIVATE)pvmpageVirtual->PAGE_pvAreaCb;
+ if (!pvmpagep) {
+ __VMM_UNLOCK();
+ _ErrorHandle(ERROR_VMM_VIRTUAL_PAGE); /* 无法反向查询虚拟页面控制块 */
+ return (ERROR_VMM_VIRTUAL_PAGE);
+ }
+
+ pvmpagep->PAGEP_ulPtStart = (addr_t)pvSubMem;
+ pvmpagep->PAGEP_stPtSize = stSize;
+
+ __VMM_UNLOCK();
+
+ return (ERROR_NONE);
+}
+
+#endif /* LW_CFG_MODULELOADER_TEXT... */
+/*********************************************************************************************************
** 函数名称: API_VmmPCountInArea
** 功能描述: API_VmmMallocAreaEx 分配的连续虚拟内存中包含的物理页面个数 (此物理内存为缺页中断分配)
** 输 入 : pvVirtualMem 连续虚拟地址 (必须为 vmmMallocArea?? 返回地址)
diff --git a/SylixOS/kernel/vmm/vmmSwap.h b/SylixOS/kernel/vmm/vmmSwap.h
index ddf5e85..6ba9788 100644
--- a/SylixOS/kernel/vmm/vmmSwap.h
+++ b/SylixOS/kernel/vmm/vmmSwap.h
@@ -61,6 +61,11 @@ typedef struct {
#define LW_VMM_PHY_PREALLOC 0x4 /* 物理内存预分配 */
INT PAGEP_iFlags; /* like mmap flags */
+#if LW_CFG_MODULELOADER_TEXT_RO_EN > 0
+ addr_t PAGEP_ulPtStart; /* 非缺页中断保护段 */
+ size_t PAGEP_stPtSize;
+#endif /* LW_CFG_MODULELOADER_TEXT... */
+
FUNCPTR PAGEP_pfuncFiller; /* 页面填充器 */
PVOID PAGEP_pvArg; /* 页面填充器参数 */
diff --git a/SylixOS/loader/elf/elf_loader.c b/SylixOS/loader/elf/elf_loader.c
index 582c4f9..883ffea 100644
--- a/SylixOS/loader/elf/elf_loader.c
+++ b/SylixOS/loader/elf/elf_loader.c
@@ -1472,6 +1472,13 @@ static INT elfPhdrRead (LW_LD_EXEC_MODULE *pmodule,
#endif
bCanExec = PF_X & pphdr->p_flags ? LW_TRUE : LW_FALSE; /* 是否可执行 */
+#if LW_CFG_MODULELOADER_TEXT_RO_EN > 0
+ if (!pmodule->EMOD_stCodeLen && bCanExec) { /* 记录代码段位置信息 */
+ pmodule->EMOD_ulCodeOft = dwMapOff;
+ pmodule->EMOD_stCodeLen = pphdr->p_memsz;
+ }
+#endif /* LW_CFG_MODULELOADER_TEXT... */
+
if (LW_LD_VMSAFEMAP_AREA(pmodule->EMOD_pvBaseAddr, dwMapOff, iFd, &stat64Buf,
pphdr->p_offset, pphdr->p_filesz,
bCanShare, bCanExec) != ERROR_NONE) {
@@ -2029,6 +2036,14 @@ INT __elfListLoad (LW_LD_EXEC_MODULE *pmodule, CPCHAR pcPath)
if (elfPhdrBuildInitTable(pmodTemp, (ELF_DYN_DIR *)pmodTemp->EMOD_pvFormatInfo)) {
goto __out;
}
+
+#if LW_CFG_MODULELOADER_TEXT_RO_EN > 0
+ if (pmodTemp->EMOD_stCodeLen) { /* 保护代码段 */
+ LW_LD_VMSAFE_PROTECT(pmodTemp->EMOD_pvBaseAddr,
+ pmodTemp->EMOD_ulCodeOft,
+ pmodTemp->EMOD_stCodeLen);
+ }
+#endif /* LW_CFG_MODULELOADER_TEXT... */
}
#if LW_CFG_CACHE_EN > 0
API_CacheTextUpdate(pmodTemp->EMOD_pvBaseAddr, pmodTemp->EMOD_stLen);
diff --git a/SylixOS/loader/include/loader_lib.h b/SylixOS/loader/include/loader_lib.h
index 422bdfc..06b557b 100644
--- a/SylixOS/loader/include/loader_lib.h
+++ b/SylixOS/loader/include/loader_lib.h
@@ -155,6 +155,14 @@ typedef struct {
BOOL EMOD_bKoUnloadDisallow; /* 不允许卸载内核模块 */
LW_LIST_MONO_HEADER EMOD_pmonoAtexit; /* 内核模块 atexit */
+ dev_t EMOD_dev; /* 模块文件设备标识 */
+ ino_t EMOD_ino; /* 模块文件 inode 标识 */
+
+#if LW_CFG_MODULELOADER_TEXT_RO_EN > 0
+ size_t EMOD_stCodeLen; /* 模块代码段长度 */
+ ULONG EMOD_ulCodeOft; /* 模块代码段偏移 */
+#endif /* LW_CFG_MODULELOADER_TEXT... */
+
#ifdef LW_CFG_CPU_ARCH_ARM
size_t EMOD_stARMExidxCount; /* ARM.exidx 段长度 */
PVOID EMOD_pvARMExidx; /* ARM.exidx 段内存地址 */
@@ -299,10 +307,14 @@ INT __ldMmap(PVOID pvBase, size_t stAddrOft, INT iFd, struct stat64 *psta
VOID __ldShare(PVOID pvBase, size_t stLen, dev_t dev, ino64_t ino64);
VOID __ldShareAbort(dev_t dev, ino64_t ino64);
INT __ldShareConfig(BOOL bShareEn, BOOL *pbPrev);
+VOID __ldProtect(PVOID pvBase, size_t stAddrOft, size_t stLen);
#define LW_LD_VMSAFEMAP_AREA(base, addr_offset, fd, pstat64, file_offset, len, can_share, can_exec) \
__ldMmap(base, addr_offset, fd, pstat64, file_offset, len, can_share, can_exec)
+#define LW_LD_VMSAFE_PROTECT(base, addr_offset, len) \
+ __ldProtect(base, addr_offset, len)
+
#define LW_LD_VMSAFE_SHARE(base, len, dev, ino64) \
__ldShare(base, len, dev, ino64)
diff --git a/SylixOS/loader/src/loader.c b/SylixOS/loader/src/loader.c
index 5bd95ce..5641f6a 100644
--- a/SylixOS/loader/src/loader.c
+++ b/SylixOS/loader/src/loader.c
@@ -92,7 +92,7 @@ extern void __cxa_module_finalize(void *pvBase, size_t stLen, BOOL bCall);
/*********************************************************************************************************
装载器判断文件是否可被装载 (进判断文件权限和类型, 不判断文件格式)
*********************************************************************************************************/
-extern BOOL __ldPathIsFile(CPCHAR pcName);
+extern BOOL __ldPathIsFile(CPCHAR pcName, struct stat *pstatFile);
/*********************************************************************************************************
** 函数名称: moduleCreate
** 功能描述: 创建并初始化模块结构.
@@ -103,19 +103,21 @@ extern BOOL __ldPathIsFile(CPCHAR pcName);
** pcExit 模块退出函数名
** pcEntry 模块入口函数名
** pcSection 仅从指定的 section 中导出符号表
+** pstatFile 文件 stat
** pvVProc 指向的进程主模块
** 输 出 : 创建好的模块指针,如果失败,输出NULL。
** 全局变量:
** 调用模块:
*********************************************************************************************************/
-static LW_LD_EXEC_MODULE *moduleCreate (CPCHAR pcPath,
- BOOL bExportSym,
- BOOL bIsGlobal,
- CPCHAR pcInit,
- CPCHAR pcExit,
- CPCHAR pcEntry,
- CPCHAR pcSection,
- PVOID pvVProc)
+static LW_LD_EXEC_MODULE *moduleCreate (CPCHAR pcPath,
+ BOOL bExportSym,
+ BOOL bIsGlobal,
+ CPCHAR pcInit,
+ CPCHAR pcExit,
+ CPCHAR pcEntry,
+ CPCHAR pcSection,
+ struct stat *pstatFile,
+ PVOID pvVProc)
{
LW_LD_EXEC_MODULE *pmodule = LW_NULL;
size_t stModuleSize = 0; /* 模块大小 */
@@ -179,6 +181,8 @@ static LW_LD_EXEC_MODULE *moduleCreate (CPCHAR pcPath,
pmodule->EMOD_bExportSym = bExportSym;
pmodule->EMOD_bIsGlobal = bIsGlobal;
pmodule->EMOD_pvFormatInfo = LW_NULL;
+ pmodule->EMOD_dev = pstatFile->st_dev;
+ pmodule->EMOD_ino = pstatFile->st_ino;
pmodule->EMOD_pvproc = (LW_LD_VPROC *)pvVProc;
if (pcInit) {
@@ -314,11 +318,13 @@ static INT moduleDelAndDestory (LW_LD_EXEC_MODULE *pmodule)
** pcPathBuffer 查找到的文件路径缓冲
** stMaxLen 缓冲区大小
** pcEnv 环境变量名
+** pstatFile 获取文件 stat
** 输 出 : 0
** 全局变量:
** 调用模块:
*********************************************************************************************************/
-static INT moduleGetLibPath (CPCHAR pcFileName, PCHAR pcPathBuffer, size_t stMaxLen, CPCHAR pcEnv)
+static INT moduleGetLibPath (CPCHAR pcFileName, PCHAR pcPathBuffer,
+ size_t stMaxLen, CPCHAR pcEnv, struct stat *pstatFile)
{
CHAR cBuffer[MAX_FILENAME_LENGTH];
@@ -330,7 +336,7 @@ static INT moduleGetLibPath (CPCHAR pcFileName, PCHAR pcPathBuffer, size_t st
return (PX_ERROR);
}
- if (__ldPathIsFile(pcFileName)) { /* 在当前目录下 */
+ if (__ldPathIsFile(pcFileName, pstatFile)) { /* 在当前目录下 */
_PathGetFull(pcPathBuffer, stMaxLen, pcFileName); /* 保存绝对路径 */
return (ERROR_NONE);
@@ -351,10 +357,9 @@ static INT moduleGetLibPath (CPCHAR pcFileName, PCHAR pcPathBuffer, size_t st
*pcDiv = PX_EOS;
pcDiv++;
}
-
- snprintf(pcPathBuffer, stMaxLen, "%s/%s", pcStart, pcFileName);
/* 合并为完整的目录 */
- if (__ldPathIsFile(pcPathBuffer)) { /* 此文件可以被访问 */
+ snprintf(pcPathBuffer, stMaxLen, "%s/%s", pcStart, pcFileName);
+ if (__ldPathIsFile(pcPathBuffer, pstatFile)) { /* 此文件可以被访问 */
return (ERROR_NONE);
}
} while (pcDiv);
@@ -375,11 +380,11 @@ static INT moduleGetLibPath (CPCHAR pcFileName, PCHAR pcPathBuffer, size_t st
*********************************************************************************************************/
LW_LD_EXEC_MODULE *moduleLoadSub (LW_LD_EXEC_MODULE *pmodule, CPCHAR pcLibName, BOOL bCreate)
{
+ struct stat statFile;
LW_LD_EXEC_MODULE *pmoduleNeed = LW_NULL;
CHAR cLibPath[MAX_FILENAME_LENGTH];
LW_LIST_RING *pringTemp;
CHAR *pcEntry;
- CHAR *pcFileName;
if (LW_NULL == pcLibName) {
_DebugHandle(__ERRORMESSAGE_LEVEL, "invalid parameter\r\n");
@@ -390,6 +395,18 @@ LW_LD_EXEC_MODULE *moduleLoadSub (LW_LD_EXEC_MODULE *pmodule, CPCHAR pcLibName,
if (LW_NULL == pmodule) {
return (LW_NULL);
}
+
+ /*
+ * 获取动态链接库位置
+ */
+ if (ERROR_NONE != moduleGetLibPath(pcLibName, cLibPath, MAX_FILENAME_LENGTH, "LD_LIBRARY_PATH", &statFile)) {
+ if (ERROR_NONE != moduleGetLibPath(pcLibName, cLibPath, MAX_FILENAME_LENGTH, "PATH", &statFile)) {
+ fprintf(stderr, "[ld]Can not find dependent library: %s\n", pcLibName);
+ _ErrorHandle(ERROR_LOADER_NO_MODULE);
+ return (LW_NULL);
+ }
+ }
+
/*
* 查找依赖链表中已经加载的库
*/
@@ -397,11 +414,10 @@ LW_LD_EXEC_MODULE *moduleLoadSub (LW_LD_EXEC_MODULE *pmodule, CPCHAR pcLibName,
pringTemp = &pmodule->EMOD_ringModules;
do {
pmoduleNeed = _LIST_ENTRY(pringTemp, LW_LD_EXEC_MODULE, EMOD_ringModules);
-
- _PathLastName(pmoduleNeed->EMOD_pcModulePath, &pcFileName); /* 取出文件名 */
- if (pcFileName && (lib_strcmp(pcFileName, pcLibName) == 0)) {
+ if (pmoduleNeed->EMOD_dev == statFile.st_dev &&
+ pmoduleNeed->EMOD_ino == statFile.st_ino) { /* 如果已加载该模块,直接返回 */
LW_VP_UNLOCK(pmodule->EMOD_pvproc);
- return (pmoduleNeed); /* 如果已加载该模块,直接返回 */
+ return (pmoduleNeed);
}
pringTemp = _list_ring_get_next(pringTemp);
@@ -411,17 +427,6 @@ LW_LD_EXEC_MODULE *moduleLoadSub (LW_LD_EXEC_MODULE *pmodule, CPCHAR pcLibName,
if (!bCreate) { /* 如果没有找到, 不需要创建 */
return (LW_NULL);
}
-
- /*
- * 获取动态链接库位置
- */
- if (ERROR_NONE != moduleGetLibPath(pcLibName, cLibPath, MAX_FILENAME_LENGTH, "LD_LIBRARY_PATH")) {
- if (ERROR_NONE != moduleGetLibPath(pcLibName, cLibPath, MAX_FILENAME_LENGTH, "PATH")) {
- fprintf(stderr, "[ld]Can not find dependent library: %s\n", pcLibName);
- _ErrorHandle(ERROR_LOADER_NO_MODULE);
- return (LW_NULL);
- }
- }
if (pmodule->EMOD_bIsSymbolEntry) {
pcEntry = LW_NULL; /* 已找到了进程入口, 不必找了 */
@@ -436,6 +441,7 @@ LW_LD_EXEC_MODULE *moduleLoadSub (LW_LD_EXEC_MODULE *pmodule, CPCHAR pcLibName,
pmodule->EMOD_pcExit,
pcEntry,
LW_NULL,
+ &statFile,
pmodule->EMOD_pvproc);
/* 创建模块 */
if (LW_NULL == pmoduleNeed) {
@@ -864,6 +870,7 @@ PVOID API_ModuleLoadEx (CPCHAR pcFile,
PVOID pvVProc)
{
CHAR cLibPath[MAX_FILENAME_LENGTH];
+ struct stat statFile;
LW_LD_EXEC_MODULE *pmodule = LW_NULL;
LW_LD_EXEC_MODULE *pmodVProc = LW_NULL;
LW_LD_VPROC *pvproc;
@@ -880,8 +887,6 @@ PVOID API_ModuleLoadEx (CPCHAR pcFile,
} else {
bIsGlobal = LW_FALSE;
}
-
- _PathLastName(pcFile, &pcFileName); /* 取出文件名 */
pvproc = (LW_LD_VPROC *)pvVProc;
if (LW_NULL == pvproc) { /* 内核模块 */
@@ -898,15 +903,13 @@ PVOID API_ModuleLoadEx (CPCHAR pcFile,
}
if (pmodVProc) {
+ _PathLastName(pcFile, &pcFileName); /* 取出文件名 */
pmodule = moduleLoadSub(pmodVProc, pcFileName, LW_FALSE); /* 查找进程已装载模块链表 */
}
- if (LW_NULL == pmodule) {
- /*
- * 获取动态链接库位置
- */
- if (ERROR_NONE != moduleGetLibPath(pcFile, cLibPath, MAX_FILENAME_LENGTH, "LD_LIBRARY_PATH")) {
- if (ERROR_NONE != moduleGetLibPath(pcFile, cLibPath, MAX_FILENAME_LENGTH, "PATH")) {
+ if (LW_NULL == pmodule) { /* 获取动态链接库位置 */
+ if (ERROR_NONE != moduleGetLibPath(pcFile, cLibPath, MAX_FILENAME_LENGTH, "LD_LIBRARY_PATH", &statFile)) {
+ if (ERROR_NONE != moduleGetLibPath(pcFile, cLibPath, MAX_FILENAME_LENGTH, "PATH", &statFile)) {
fprintf(stderr, "[ld]Can not find dependent library: %s\n", pcFile);
_ErrorHandle(ERROR_LOADER_NO_MODULE);
return (LW_NULL);
@@ -915,12 +918,13 @@ PVOID API_ModuleLoadEx (CPCHAR pcFile,
pmodule = moduleCreate(cLibPath, LW_TRUE, bIsGlobal,
pcInit, pcExit, pcEntry,
- pcSection, pvproc); /* 创建新子模块 */
+ pcSection, &statFile, pvproc); /* 创建新子模块 */
if (pmodule) {
LW_VP_LOCK(pmodule->EMOD_pvproc);
_List_Ring_Add_Last(&pmodule->EMOD_ringModules, &pvproc->VP_ringModules);
LW_VP_UNLOCK(pmodule->EMOD_pvproc);
}
+
} else {
if (bIsGlobal) { /* 只要一次global加载则为global*/
pmodule->EMOD_bIsGlobal = bIsGlobal;
@@ -1430,7 +1434,7 @@ ssize_t API_ModuleGetName (PVOID pvAddr, PCHAR pcFullPath, size_t stLen)
return (sstRet);
}
/*********************************************************************************************************
-** 函数名称: API_ModuleUpdate
+** 函数名称: API_ModuleGlobal
** 功能描述: 查找模块并更新模块相关设置.
** 输 入 : pcFile 模块文件
** iMode 装载模式 (全局还是局部)
@@ -1446,6 +1450,7 @@ PVOID API_ModuleGlobal (CPCHAR pcFile,
PVOID pvVProc)
{
CHAR cLibPath[MAX_FILENAME_LENGTH];
+ struct stat statFile;
BOOL bStart;
LW_LIST_RING *pringTemp;
LW_LD_EXEC_MODULE *pmodTemp;
@@ -1464,8 +1469,8 @@ PVOID API_ModuleGlobal (CPCHAR pcFile,
pvproc = (LW_LD_VPROC *)pvVProc;
}
- if (ERROR_NONE != moduleGetLibPath(pcFile, cLibPath, MAX_FILENAME_LENGTH, "LD_LIBRARY_PATH")) {
- if (ERROR_NONE != moduleGetLibPath(pcFile, cLibPath, MAX_FILENAME_LENGTH, "PATH")) {
+ if (ERROR_NONE != moduleGetLibPath(pcFile, cLibPath, MAX_FILENAME_LENGTH, "LD_LIBRARY_PATH", &statFile)) {
+ if (ERROR_NONE != moduleGetLibPath(pcFile, cLibPath, MAX_FILENAME_LENGTH, "PATH", &statFile)) {
fprintf(stderr, "[ld]Can not find dependent library: %s\n", pcFile);
_ErrorHandle(ERROR_LOADER_NO_MODULE);
return (LW_NULL);
@@ -1478,7 +1483,8 @@ PVOID API_ModuleGlobal (CPCHAR pcFile,
pringTemp = _list_ring_get_next(pringTemp), bStart = LW_FALSE) {
pmodTemp = _LIST_ENTRY(pringTemp, LW_LD_EXEC_MODULE, EMOD_ringModules);
- if (lib_strcmp(pmodTemp->EMOD_pcModulePath, cLibPath) == 0) {
+ if (pmodTemp->EMOD_dev == statFile.st_dev &&
+ pmodTemp->EMOD_ino == statFile.st_ino) {
if ((pmodTemp->EMOD_bIsGlobal == LW_FALSE) &&
(iMode & LW_OPTION_LOADER_SYM_GLOBAL)) {
pmodTemp->EMOD_bIsGlobal = LW_TRUE; /* 可对外提供符号的模块 */
diff --git a/SylixOS/loader/src/loader_malloc.c b/SylixOS/loader/src/loader_malloc.c
index 0cb8e84..0556382 100644
--- a/SylixOS/loader/src/loader_malloc.c
+++ b/SylixOS/loader/src/loader_malloc.c
@@ -616,6 +616,22 @@ INT __ldMmap (PVOID pvBase, size_t stAddrOft, INT iFd, struct stat64 *pstat6
#endif /* LW_CFG_VMM_EN > 0 */
}
/*********************************************************************************************************
+** 函数名称: __ldProtect
+** 功能描述: 设置内存保护区, 不允许写.
+** 输 入 : pvBase __ldMallocArea 或者 __ldMallocAreaAlign 返回的地址 (__ldMmap 已经装载完成)
+** stAddrOft 起始偏移量
+** stLen 大小
+** 输 出 : NONE
+** 全局变量:
+** 调用模块:
+*********************************************************************************************************/
+VOID __ldProtect (PVOID pvBase, size_t stAddrOft, size_t stLen)
+{
+#if LW_CFG_MODULELOADER_TEXT_RO_EN > 0
+ API_VmmSetProtect(pvBase, (PVOID)((addr_t)pvBase + stAddrOft), stLen);
+#endif
+}
+/*********************************************************************************************************
** 函数名称: __ldShare
** 功能描述: 允许共享当前共享库
** 输 入 : pvBase __ldMallocArea 或者 __ldMallocAreaAlign 返回的地址 (__ldMmap 已经装载完成)
diff --git a/SylixOS/loader/src/loader_shell.c b/SylixOS/loader/src/loader_shell.c
index 2f5400b..f120681 100644
--- a/SylixOS/loader/src/loader_shell.c
+++ b/SylixOS/loader/src/loader_shell.c
@@ -99,16 +99,20 @@ static const CHAR _G_cVProcInfoHdr[] = "\n\
** 函数名称: __ldPathIsFile
** 功能描述: 判断文件的路径是否为文件
** 输 入 : pcParam 用户路径参数
+** pstatFile 获取文件 stat
** 输 出 : BOOL
** 全局变量:
** 调用模块:
*********************************************************************************************************/
-BOOL __ldPathIsFile (CPCHAR pcName)
+BOOL __ldPathIsFile (CPCHAR pcName, struct stat *pstatFile)
{
struct stat statFs;
if (stat(pcName, &statFs) >= 0) {
if (S_ISREG(statFs.st_mode)) {
+ if (pstatFile) {
+ *pstatFile = statFs;
+ }
return (LW_TRUE);
}
}
@@ -138,7 +142,7 @@ INT __ldGetFilePath (CPCHAR pcParam, PCHAR pcPathBuffer, size_t stMaxLen)
}
if (lib_strchr(pcParam, '/')) { /* 是一个路径 */
- if (__ldPathIsFile(pcParam)) { /* 直接使用参数即可 */
+ if (__ldPathIsFile(pcParam, LW_NULL)) { /* 直接使用参数即可 */
_PathGetFull(pcPathBuffer, stMaxLen, pcParam); /* 保存绝对路径 */
return (ERROR_NONE);
}
@@ -162,7 +166,7 @@ INT __ldGetFilePath (CPCHAR pcParam, PCHAR pcPathBuffer, size_t stMaxLen)
}
snprintf(pcPathBuffer, stMaxLen, "%s/%s", pcStart, pcParam);/* 合并为完整的目录 */
- if (__ldPathIsFile(pcPathBuffer)) { /* 此文件可以被访问 */
+ if (__ldPathIsFile(pcPathBuffer, LW_NULL)) { /* 此文件可以被访问 */
return (ERROR_NONE);
}
} while (pcDiv);
diff --git a/SylixOS/net/lwip/src/api/api_msg.c b/SylixOS/net/lwip/src/api/api_msg.c
index 233cc05..2cfc1d3 100644
--- a/SylixOS/net/lwip/src/api/api_msg.c
+++ b/SylixOS/net/lwip/src/api/api_msg.c
@@ -1020,8 +1020,8 @@ lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM)
err = ERR_OK;
/* linger enabled/required at all? (i.e. is there untransmitted data left?) */
/* SylixOS Fixed listen conn do not need check linger */
- if ((conn->state != NETCONN_LISTEN) &&
- (conn->linger >= 0) && (conn->pcb.tcp->unsent || conn->pcb.tcp->unacked)) {
+ if ((conn->linger >= 0) &&
+ (conn->pcb.tcp->state != LISTEN) && (conn->pcb.tcp->unsent || conn->pcb.tcp->unacked)) {
if ((conn->linger == 0)) {
/* data left but linger prevents waiting */
tcp_abort(tpcb);
diff --git a/SylixOS/shell/ttinyShell/ttinyShellLib.c b/SylixOS/shell/ttinyShell/ttinyShellLib.c
index 00f2216..7626bdd 100644
--- a/SylixOS/shell/ttinyShell/ttinyShellLib.c
+++ b/SylixOS/shell/ttinyShell/ttinyShellLib.c
@@ -152,7 +152,7 @@ static INT __tshellBgCreate(INT iFd,
装载器内部函数声明
*********************************************************************************************************/
#if LW_CFG_MODULELOADER_EN > 0
-extern BOOL __ldPathIsFile(CPCHAR pcName);
+extern BOOL __ldPathIsFile(CPCHAR pcName, struct stat *pstatFile);
/*********************************************************************************************************
** 函数名称: __tshellIsResCmd
** 功能描述: 是否为强制内建命令
@@ -190,7 +190,7 @@ static BOOL __tshellCheckFile (CPCHAR pcKeyword)
PCHAR pcDiv;
if (lib_strchr(pcKeyword, PX_DIVIDER)) { /* 是一个路径 */
- if (__ldPathIsFile(pcKeyword)) {
+ if (__ldPathIsFile(pcKeyword, LW_NULL)) {
return (LW_TRUE);
} else {
@@ -223,7 +223,7 @@ static BOOL __tshellCheckFile (CPCHAR pcKeyword)
snprintf(pcPathBuffer, MAX_FILENAME_LENGTH, "%s/%s",
pcStart, pcKeyword); /* 合并为完整的目录 */
- if (__ldPathIsFile(pcPathBuffer)) { /* 此文件可以被访问 */
+ if (__ldPathIsFile(pcPathBuffer, LW_NULL)) { /* 此文件可以被访问 */
__SHEAP_FREE(pcBuffer);
return (LW_TRUE);
}