From 5e87d8c183471166294e2caa041ab4da8570c6a1 Mon Sep 17 00:00:00 2001 From: Guangyao Ma Date: Tue, 31 Aug 2021 16:56:21 +0800 Subject: [PATCH] fix: dyload open close failed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 本次提交修复内核加载器,异常情况分支的一个bug:mksh通过exec命令(mksh内置命令 ,正常情况下,该命令成功执行会复用mksh进程空间,拉起新的指定进程)。但是如果 进程没有成功加载的情况下,内核加载器的异常分支会错误释放mksh的fd句柄。最终导致 下次拉起其他进程时(fork + exec方式),新的进程会继承fd,映射了早就释放的sysfd ,此时的sysfd可能已经被复用,issue场景下这个sysfd被加载过程中打开的libc.so占用 ,exec时会释放procfd->sysfd(错误的映射关系),最终新进程libc.so被关闭。 导致内核崩溃。 close #I452Z7 Signed-off-by: Guangyao Ma Change-Id: Ifca809f88b5ffcfb879dc5520d1f6adf5cf92bcd --- .../extended/dynload/include/los_load_elf.h | 2 +- kernel/extended/dynload/src/los_load_elf.c | 48 ++++++++++++------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/kernel/extended/dynload/include/los_load_elf.h b/kernel/extended/dynload/include/los_load_elf.h index 9912954f..a7ff34bc 100644 --- a/kernel/extended/dynload/include/los_load_elf.h +++ b/kernel/extended/dynload/include/los_load_elf.h @@ -89,7 +89,7 @@ typedef struct { LD_ELF_EHDR elfEhdr; LD_ELF_PHDR *elfPhdr; UINT32 fileLen; - INT32 fd; + INT32 procfd; } ELFInfo; typedef struct { diff --git a/kernel/extended/dynload/src/los_load_elf.c b/kernel/extended/dynload/src/los_load_elf.c index 1d0fa835..b2bb47e5 100644 --- a/kernel/extended/dynload/src/los_load_elf.c +++ b/kernel/extended/dynload/src/los_load_elf.c @@ -62,6 +62,20 @@ static int OsELFOpen(const CHAR *fileName, INT32 oflags) } AssociateSystemFd(procFd, ret); + return procFd; +} + +static int OsELFClose(int procFd) +{ + int ret; + /* Process procfd convert to system global procfd */ + int sysfd = DisassociateProcessFd(procFd); + ret = close(sysfd); + if (ret < 0) { + AssociateSystemFd(procFd, sysfd); + return -get_errno(); + } + FreeProcessFd(procFd); return ret; } @@ -95,10 +109,11 @@ STATIC INT32 OsGetFileLength(UINT32 *fileLen, const CHAR *fileName) return LOS_OK; } -STATIC INT32 OsReadELFInfo(INT32 fd, UINT8 *buffer, size_t readSize, off_t offset) +STATIC INT32 OsReadELFInfo(INT32 procfd, UINT8 *buffer, size_t readSize, off_t offset) { ssize_t byteNum; off_t returnPos; + INT32 fd = GetAssociatedSystemFd(procfd); if (readSize > 0) { returnPos = lseek(fd, offset, SEEK_SET); @@ -172,8 +187,8 @@ STATIC VOID OsLoadInit(ELFLoadInfo *loadInfo) #else loadInfo->oldFiles = NULL; #endif - loadInfo->execInfo.fd = INVALID_FD; - loadInfo->interpInfo.fd = INVALID_FD; + loadInfo->execInfo.procfd = INVALID_FD; + loadInfo->interpInfo.procfd = INVALID_FD; } STATIC INT32 OsReadEhdr(const CHAR *fileName, ELFInfo *elfInfo, BOOL isExecFile) @@ -190,17 +205,17 @@ STATIC INT32 OsReadEhdr(const CHAR *fileName, ELFInfo *elfInfo, BOOL isExecFile) PRINT_ERR("%s[%d], Failed to open ELF file: %s!\n", __FUNCTION__, __LINE__, fileName); return ret; } - elfInfo->fd = ret; + elfInfo->procfd = ret; #ifdef LOSCFG_DRIVERS_TZDRIVER if (isExecFile) { - ret = fs_getfilep(elfInfo->fd, &OsCurrProcessGet()->execFile); + ret = fs_getfilep(GetAssociatedSystemFd(elfInfo->procfd), &OsCurrProcessGet()->execFile); if (ret) { PRINT_ERR("%s[%d], Failed to get struct file %s!\n", __FUNCTION__, __LINE__, fileName); } } #endif - ret = OsReadELFInfo(elfInfo->fd, (UINT8 *)&elfInfo->elfEhdr, sizeof(LD_ELF_EHDR), 0); + ret = OsReadELFInfo(elfInfo->procfd, (UINT8 *)&elfInfo->elfEhdr, sizeof(LD_ELF_EHDR), 0); if (ret != LOS_OK) { PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__); return -EIO; @@ -240,7 +255,7 @@ STATIC INT32 OsReadPhdrs(ELFInfo *elfInfo, BOOL isExecFile) return -ENOMEM; } - ret = OsReadELFInfo(elfInfo->fd, (UINT8 *)elfInfo->elfPhdr, size, elfEhdr->elfPhoff); + ret = OsReadELFInfo(elfInfo->procfd, (UINT8 *)elfInfo->elfPhdr, size, elfEhdr->elfPhoff); if (ret != LOS_OK) { (VOID)LOS_MemFree(m_aucSysMem0, elfInfo->elfPhdr); elfInfo->elfPhdr = NULL; @@ -281,7 +296,7 @@ STATIC INT32 OsReadInterpInfo(ELFLoadInfo *loadInfo) return -ENOMEM; } - ret = OsReadELFInfo(loadInfo->execInfo.fd, (UINT8 *)elfInterpName, elfPhdr->fileSize, elfPhdr->offset); + ret = OsReadELFInfo(loadInfo->execInfo.procfd, (UINT8 *)elfInterpName, elfPhdr->fileSize, elfPhdr->offset); if (ret != LOS_OK) { PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__); ret = -EIO; @@ -466,13 +481,14 @@ STATIC INT32 OsSetBss(const LD_ELF_PHDR *elfPhdr, INT32 fd, UINTPTR bssStart, UI return LOS_OK; } -STATIC INT32 OsMmapELFFile(INT32 fd, const LD_ELF_PHDR *elfPhdr, const LD_ELF_EHDR *elfEhdr, UINTPTR *elfLoadAddr, +STATIC INT32 OsMmapELFFile(INT32 procfd, const LD_ELF_PHDR *elfPhdr, const LD_ELF_EHDR *elfEhdr, UINTPTR *elfLoadAddr, UINT32 mapSize, UINTPTR *loadBase) { const LD_ELF_PHDR *elfPhdrTemp = elfPhdr; UINTPTR vAddr, mapAddr, bssStart; UINT32 bssEnd, elfProt, elfFlags; INT32 ret, i; + INT32 fd = GetAssociatedSystemFd(procfd); for (i = 0; i < elfEhdr->elfPhNum; ++i, ++elfPhdrTemp) { if (elfPhdrTemp->type != LD_PT_LOAD) { @@ -538,7 +554,7 @@ STATIC INT32 OsLoadInterpBinary(const ELFLoadInfo *loadInfo, UINTPTR *interpMapB return -EINVAL; } - ret = OsMmapELFFile(loadInfo->interpInfo.fd, loadInfo->interpInfo.elfPhdr, &loadInfo->interpInfo.elfEhdr, + ret = OsMmapELFFile(loadInfo->interpInfo.procfd, loadInfo->interpInfo.elfPhdr, &loadInfo->interpInfo.elfEhdr, interpMapBase, mapSize, &loadBase); if (ret != LOS_OK) { PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__); @@ -898,14 +914,14 @@ STATIC INT32 OsLoadELFSegment(ELFLoadInfo *loadInfo) } } - ret = OsMmapELFFile(loadInfo->execInfo.fd, loadInfo->execInfo.elfPhdr, &loadInfo->execInfo.elfEhdr, + ret = OsMmapELFFile(loadInfo->execInfo.procfd, loadInfo->execInfo.elfPhdr, &loadInfo->execInfo.elfEhdr, &loadInfo->loadAddr, mapSize, &loadBase); if (ret != LOS_OK) { PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__); return ret; } - if (loadInfo->interpInfo.fd != INVALID_FD) { + if (loadInfo->interpInfo.procfd != INVALID_FD) { ret = OsLoadInterpBinary(loadInfo, &interpMapBase); if (ret != LOS_OK) { return ret; @@ -961,12 +977,12 @@ STATIC VOID OsDeInitLoadInfo(ELFLoadInfo *loadInfo) STATIC VOID OsDeInitFiles(ELFLoadInfo *loadInfo) { - if (loadInfo->execInfo.fd != INVALID_FD) { - (VOID)close(loadInfo->execInfo.fd); + if (loadInfo->execInfo.procfd != INVALID_FD) { + (VOID)OsELFClose(loadInfo->execInfo.procfd); } - if (loadInfo->interpInfo.fd != INVALID_FD) { - (VOID)close(loadInfo->interpInfo.fd); + if (loadInfo->interpInfo.procfd != INVALID_FD) { + (VOID)OsELFClose(loadInfo->interpInfo.procfd); } #ifdef LOSCFG_FS_VFS delete_files_snapshot((struct files_struct *)loadInfo->oldFiles);