From 9db3407589bb0b2d4a5772faac3130032bc0b8a9 Mon Sep 17 00:00:00 2001 From: Haryslee Date: Sat, 26 Jun 2021 14:36:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9F=BA=E4=BA=8E=E6=B1=87=E7=BC=96?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=86=85=E6=A0=B8=E5=AF=B9=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=80=81=E5=86=85=E5=AD=98=E6=B8=85=E9=9B=B6=E7=9A=84=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 背景:LOS_UserMemClear接口原有实现是通过在内核中 申请一块堆内存并对其清零,调用copy_to_user来达到 对用户态内存清零的目的,需要使用堆内存。 修改方案:基于汇编实现内核对用户态内存清零的功能。 close #I3XXT0 Change-Id: I27cb1e45559cb75a9b330799fe427abd54f51c15 Signed-off-by: Haryslee --- arch/arm/arm/include/arm_user_clear.h | 50 +++++++++++ arch/arm/arm/src/clear_user.S | 100 +++++++++++++++++++++ arch/arm/arm/src/user_copy.c | 11 +-- kernel/extended/dynload/src/los_load_elf.c | 30 +------ 4 files changed, 157 insertions(+), 34 deletions(-) create mode 100644 arch/arm/arm/include/arm_user_clear.h create mode 100644 arch/arm/arm/src/clear_user.S diff --git a/arch/arm/arm/include/arm_user_clear.h b/arch/arm/arm/include/arm_user_clear.h new file mode 100644 index 00000000..d808208a --- /dev/null +++ b/arch/arm/arm/include/arm_user_clear.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _ARM_USER_CLEAR_H +#define _ARM_USER_CLEAR_H + +#include "los_typedef.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +size_t _arm_clear_user(void *addr, size_t bytes); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _ARM_USER_CLEAR_H */ diff --git a/arch/arm/arm/src/clear_user.S b/arch/arm/arm/src/clear_user.S new file mode 100644 index 00000000..907a5041 --- /dev/null +++ b/arch/arm/arm/src/clear_user.S @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "asm.h" + +.syntax unified +.arm + +// size_t _arm_clear_user(void *addr, size_t bytes) +FUNCTION(_arm_clear_user) + push {r0-r6, lr} + cmp r1, #0 + beq .Lclear_user_return + tst r0, #7 + beq .Lclear_user_aligned + +.Lclear_user_byte: + mov r2, #0 +0: strb r2, [r0], #1 + subs r1, r1, #1 + beq .Lclear_user_return + tst r0, #7 + bne 0b + +.Lclear_user_aligned: + eor r3, r3 + eor r4, r4 + bics r2, r1, #15 + bne .Lclear_user_16bytes + bics r2, r1, #7 + bne .Lclear_user_8bytes + b .Lclear_user_remaining + +.Lclear_user_16bytes: + eor r5, r5 + eor r6, r6 +1: stmia r0!, {r3, r4, r5, r6} + subs r2, r2, #16 + bne 1b + ands r1, r1, #15 + beq .Lclear_user_return + bics r2, r1, #7 + beq .Lclear_user_remaining + +.Lclear_user_8bytes: +2: stmia r0!, {r3, r4} + ands r1, r1, #7 + beq .Lclear_user_return + +.Lclear_user_remaining: + mov r2, #0 +3: strb r2, [r0], #1 + subs r1, r1, #1 + bne 3b + +.Lclear_user_return: + pop {r0-r6, lr} + mov r0, #0 + bx lr + +.Lclear_user_err: + pop {r0, r1} + sub r0, r2, r0 + sub r0, r1, r0 + pop {r2-r6, lr} + bx lr + +.pushsection __exc_table, "a" + .long 0b, .Lclear_user_err + .long 1b, .Lclear_user_err + .long 2b, .Lclear_user_err + .long 3b, .Lclear_user_err +.popsection diff --git a/arch/arm/arm/src/user_copy.c b/arch/arm/arm/src/user_copy.c index f4ecd91c..081bc413 100644 --- a/arch/arm/arm/src/user_copy.c +++ b/arch/arm/arm/src/user_copy.c @@ -31,6 +31,7 @@ #include "user_copy.h" #include "arm_user_copy.h" +#include "arm_user_clear.h" #include "securec.h" #include "los_memory.h" #include "los_vm_map.h" @@ -96,15 +97,9 @@ INT32 LOS_UserMemClear(unsigned char *buf, UINT32 len) if (!LOS_IsUserAddressRange((vaddr_t)(UINTPTR)buf, len)) { (VOID)memset_s(buf, len, 0, len); } else { - unsigned char *tmp = (unsigned char *)LOS_MemAlloc(OS_SYS_MEM_ADDR, len); - if (tmp == NULL) { - return -ENOMEM; + if (_arm_clear_user(buf, len)) { + return -EFAULT; } - (VOID)memset_s(tmp, len, 0, len); - if (_arm_user_copy(buf, tmp, len) != 0) { - ret = -EFAULT; - } - LOS_MemFree(OS_SYS_MEM_ADDR, tmp); } return ret; } diff --git a/kernel/extended/dynload/src/los_load_elf.c b/kernel/extended/dynload/src/los_load_elf.c index ef7411eb..a6133eb4 100644 --- a/kernel/extended/dynload/src/los_load_elf.c +++ b/kernel/extended/dynload/src/los_load_elf.c @@ -416,42 +416,20 @@ INT32 OsGetKernelVaddr(const LosVmSpace *space, VADDR_T vaddr, VADDR_T *kvaddr) STATIC INT32 OsSetBss(const LD_ELF_PHDR *elfPhdr, INT32 fd, UINTPTR bssStart, UINT32 bssEnd, UINT32 elfProt) { - UINTPTR bssPageStart, bssStartPageAlign, bssEndPageAlign; + UINTPTR bssStartPageAlign, bssEndPageAlign; UINTPTR mapBase; - UINT32 offset, size; UINT32 bssMapSize; INT32 stackFlags; INT32 ret; - vaddr_t kvaddr = 0; - bssPageStart = ROUNDDOWN(bssStart, PAGE_SIZE); bssStartPageAlign = ROUNDUP(bssStart, PAGE_SIZE); bssEndPageAlign = ROUNDUP(bssEnd, PAGE_SIZE); - ret = LOS_UnMMap(bssPageStart, (bssEndPageAlign - bssPageStart)); - if ((ret != LOS_OK) && (bssPageStart != 0)) { - PRINT_ERR("%s[%d], Failed to unmap a region, vaddr: %#x!\n", __FUNCTION__, __LINE__, bssPageStart); - } - ret = LOS_UserSpaceVmAlloc(OsCurrProcessGet()->vmSpace, PAGE_SIZE, (VOID **)&bssPageStart, - 0, OsCvtProtFlagsToRegionFlags(elfProt, MAP_FIXED)); - if (ret != LOS_OK) { - PRINT_ERR("%s[%d], Failed to do vmm alloc!\n", __FUNCTION__, __LINE__); - return -ENOMEM; - } - ret = OsGetKernelVaddr(OsCurrProcessGet()->vmSpace, bssPageStart, &kvaddr); - if (ret != LOS_OK) { - PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__); + ret = LOS_UserMemClear((VOID *)bssStart, PAGE_SIZE - ROUNDOFFSET(bssStart, PAGE_SIZE)); + if (ret != 0) { + PRINT_ERR("%s[%d], Failed to clear bss\n", __FUNCTION__, __LINE__); return -EFAULT; } - (VOID)memset_s((VOID *)(UINTPTR)kvaddr, PAGE_SIZE, 0, PAGE_SIZE); - - offset = ROUNDDOWN(elfPhdr->offset + elfPhdr->fileSize, PAGE_SIZE); - size = ROUNDOFFSET(elfPhdr->offset + elfPhdr->fileSize, PAGE_SIZE); - ret = OsReadELFInfo(fd, (UINT8 *)(UINTPTR)kvaddr, size, offset); - if (ret != LOS_OK) { - PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__); - return -EIO; - } bssMapSize = bssEndPageAlign - bssStartPageAlign; if (bssMapSize > 0) {