From 991b2ff74424165600b1fc77c688a50c04002556 Mon Sep 17 00:00:00 2001 From: Yibai Zhang Date: Thu, 1 Jul 2021 15:37:34 +0800 Subject: [PATCH] feat: support dynamic stack canary for userland. AT_RANDOM from auxv is used to generate different stack canary, kernel pass AT_RANDOM as NULL to the process so canary for every process is the same. We use PRNG generate AT_RANDOM for userland program, make sure canary is strong than before. Signed-off-by: Yibai Zhang Change-Id: I7af4b5c33df342dbe68887d555ae451971b10533 --- kernel/extended/dynload/src/los_load_elf.c | 76 ++++++++++++++++++++-- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/kernel/extended/dynload/src/los_load_elf.c b/kernel/extended/dynload/src/los_load_elf.c index 1d0fa835..7ad1d1e1 100644 --- a/kernel/extended/dynload/src/los_load_elf.c +++ b/kernel/extended/dynload/src/los_load_elf.c @@ -675,6 +675,46 @@ STATIC INT32 OsCopyParams(ELFLoadInfo *loadInfo, INT32 argc, CHAR *const *argv) return LOS_OK; } +STATIC INT32 OsCopyRandom(ELFLoadInfo *loadInfo) +{ + UINT32 aux_random[4]; + UINT32 offset; + errno_t err; + INT32 ret; + vaddr_t kvaddr = 0; + + srand(LOS_CurrNanosec()); + aux_random[0] = rand(); + aux_random[1] = rand(); + aux_random[2] = rand(); + aux_random[3] = rand(); + + ret = OsGetKernelVaddr(loadInfo->newSpace, loadInfo->stackParamBase, &kvaddr); + if (ret != LOS_OK) { + PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__); + return -EFAULT; + } + + offset = loadInfo->topOfMem - loadInfo->stackParamBase; + if (offset < sizeof(aux_random)) { + PRINT_ERR("%s[%d], The size of at_random is out of limit: %#x bytes!\n", __FUNCTION__, __LINE__, + USER_PARAM_BYTE_MAX); + return -E2BIG; + } + loadInfo->topOfMem -= sizeof(aux_random); + offset -= sizeof(aux_random); + + err = memcpy_s((VOID *)(UINTPTR)(kvaddr + offset), sizeof(aux_random), aux_random, sizeof(aux_random)); + + if (err != EOK) { + PRINT_ERR("%s[%d], copy random failed! err: %d\n", __FUNCTION__, __LINE__, err); + return -EFAULT; + } + + return LOS_OK; + +} + STATIC INT32 OsGetParamNum(CHAR *const *argv) { CHAR *argPtr = NULL; @@ -772,6 +812,11 @@ STATIC INT32 OsSetArgParams(ELFLoadInfo *loadInfo, CHAR *const *argv, CHAR *cons } loadInfo->execName = (CHAR *)loadInfo->topOfMem; + ret = OsCopyRandom(loadInfo); + if (ret != LOS_OK) { + return ret; + } + ret = OsCopyParams(loadInfo, loadInfo->envc, envp); if (ret != LOS_OK) { return ret; @@ -784,14 +829,36 @@ STATIC INT32 OsSetArgParams(ELFLoadInfo *loadInfo, CHAR *const *argv, CHAR *cons return LOS_OK; } -STATIC INT32 OsPutParamToStack(ELFLoadInfo *loadInfo, const UINTPTR *auxVecInfo, INT32 vecIndex) + +STATIC INT32 OsPutUserAuxv(UINTPTR *data, UINTPTR **sp, UINTPTR *auxVecInfo, INT32 vecIndex) +{ + size_t size; + int i; + for (i = 0; i < vecIndex; i+=2) { + if(auxVecInfo[i] == AUX_RANDOM) { + auxVecInfo[i + 1] = *data; + break; + } + } + + size = LOS_ArchCopyToUser(*sp, auxVecInfo, vecIndex * sizeof(UINTPTR)); + if (size != 0) { + PRINT_ERR("%s[%d], Failed to copy strings! Bytes not copied: %d\n", __FUNCTION__, __LINE__, size); + return -EFAULT; + } + ++(*sp); + + return LOS_OK; + +} + +STATIC INT32 OsPutParamToStack(ELFLoadInfo *loadInfo, UINTPTR *auxVecInfo, INT32 vecIndex) { UINTPTR argStart = loadInfo->topOfMem; UINTPTR *topMem = (UINTPTR *)ROUNDDOWN(loadInfo->topOfMem, sizeof(UINTPTR)); UINTPTR *argsPtr = NULL; UINTPTR stackBase; INT32 items = (loadInfo->argc + 1) + (loadInfo->envc + 1) + 1; - size_t size; INT32 stackFlags; loadInfo->topOfMem = ROUNDDOWN((UINTPTR)(topMem - vecIndex - items), STACK_ALIGN_SIZE); @@ -815,9 +882,8 @@ STATIC INT32 OsPutParamToStack(ELFLoadInfo *loadInfo, const UINTPTR *auxVecInfo, return -EFAULT; } - size = LOS_ArchCopyToUser(argsPtr, auxVecInfo, vecIndex * sizeof(UINTPTR)); - if (size != 0) { - PRINT_ERR("%s[%d], Failed to copy strings! Bytes not copied: %d\n", __FUNCTION__, __LINE__, size); + if(OsPutUserAuxv(&argStart, &argsPtr, auxVecInfo, vecIndex)){ + PRINT_ERR("%s[%d], Failed to put auxv to user stack!\n", __FUNCTION__, __LINE__); return -EFAULT; } -- Gitee