fix: dyload open close failed
本次提交修复内核加载器,异常情况分支的一个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 <guangyao.ma@outlook.com> Change-Id: Ifca809f88b5ffcfb879dc5520d1f6adf5cf92bcd
This commit is contained in:
parent
5f970888ef
commit
5e87d8c183
|
@ -89,7 +89,7 @@ typedef struct {
|
||||||
LD_ELF_EHDR elfEhdr;
|
LD_ELF_EHDR elfEhdr;
|
||||||
LD_ELF_PHDR *elfPhdr;
|
LD_ELF_PHDR *elfPhdr;
|
||||||
UINT32 fileLen;
|
UINT32 fileLen;
|
||||||
INT32 fd;
|
INT32 procfd;
|
||||||
} ELFInfo;
|
} ELFInfo;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -62,6 +62,20 @@ static int OsELFOpen(const CHAR *fileName, INT32 oflags)
|
||||||
}
|
}
|
||||||
|
|
||||||
AssociateSystemFd(procFd, ret);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,10 +109,11 @@ STATIC INT32 OsGetFileLength(UINT32 *fileLen, const CHAR *fileName)
|
||||||
return LOS_OK;
|
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;
|
ssize_t byteNum;
|
||||||
off_t returnPos;
|
off_t returnPos;
|
||||||
|
INT32 fd = GetAssociatedSystemFd(procfd);
|
||||||
|
|
||||||
if (readSize > 0) {
|
if (readSize > 0) {
|
||||||
returnPos = lseek(fd, offset, SEEK_SET);
|
returnPos = lseek(fd, offset, SEEK_SET);
|
||||||
|
@ -172,8 +187,8 @@ STATIC VOID OsLoadInit(ELFLoadInfo *loadInfo)
|
||||||
#else
|
#else
|
||||||
loadInfo->oldFiles = NULL;
|
loadInfo->oldFiles = NULL;
|
||||||
#endif
|
#endif
|
||||||
loadInfo->execInfo.fd = INVALID_FD;
|
loadInfo->execInfo.procfd = INVALID_FD;
|
||||||
loadInfo->interpInfo.fd = INVALID_FD;
|
loadInfo->interpInfo.procfd = INVALID_FD;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC INT32 OsReadEhdr(const CHAR *fileName, ELFInfo *elfInfo, BOOL isExecFile)
|
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);
|
PRINT_ERR("%s[%d], Failed to open ELF file: %s!\n", __FUNCTION__, __LINE__, fileName);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
elfInfo->fd = ret;
|
elfInfo->procfd = ret;
|
||||||
|
|
||||||
#ifdef LOSCFG_DRIVERS_TZDRIVER
|
#ifdef LOSCFG_DRIVERS_TZDRIVER
|
||||||
if (isExecFile) {
|
if (isExecFile) {
|
||||||
ret = fs_getfilep(elfInfo->fd, &OsCurrProcessGet()->execFile);
|
ret = fs_getfilep(GetAssociatedSystemFd(elfInfo->procfd), &OsCurrProcessGet()->execFile);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
PRINT_ERR("%s[%d], Failed to get struct file %s!\n", __FUNCTION__, __LINE__, fileName);
|
PRINT_ERR("%s[%d], Failed to get struct file %s!\n", __FUNCTION__, __LINE__, fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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) {
|
if (ret != LOS_OK) {
|
||||||
PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__);
|
PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
@ -240,7 +255,7 @@ STATIC INT32 OsReadPhdrs(ELFInfo *elfInfo, BOOL isExecFile)
|
||||||
return -ENOMEM;
|
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) {
|
if (ret != LOS_OK) {
|
||||||
(VOID)LOS_MemFree(m_aucSysMem0, elfInfo->elfPhdr);
|
(VOID)LOS_MemFree(m_aucSysMem0, elfInfo->elfPhdr);
|
||||||
elfInfo->elfPhdr = NULL;
|
elfInfo->elfPhdr = NULL;
|
||||||
|
@ -281,7 +296,7 @@ STATIC INT32 OsReadInterpInfo(ELFLoadInfo *loadInfo)
|
||||||
return -ENOMEM;
|
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) {
|
if (ret != LOS_OK) {
|
||||||
PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__);
|
PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
|
@ -466,13 +481,14 @@ STATIC INT32 OsSetBss(const LD_ELF_PHDR *elfPhdr, INT32 fd, UINTPTR bssStart, UI
|
||||||
return LOS_OK;
|
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)
|
UINT32 mapSize, UINTPTR *loadBase)
|
||||||
{
|
{
|
||||||
const LD_ELF_PHDR *elfPhdrTemp = elfPhdr;
|
const LD_ELF_PHDR *elfPhdrTemp = elfPhdr;
|
||||||
UINTPTR vAddr, mapAddr, bssStart;
|
UINTPTR vAddr, mapAddr, bssStart;
|
||||||
UINT32 bssEnd, elfProt, elfFlags;
|
UINT32 bssEnd, elfProt, elfFlags;
|
||||||
INT32 ret, i;
|
INT32 ret, i;
|
||||||
|
INT32 fd = GetAssociatedSystemFd(procfd);
|
||||||
|
|
||||||
for (i = 0; i < elfEhdr->elfPhNum; ++i, ++elfPhdrTemp) {
|
for (i = 0; i < elfEhdr->elfPhNum; ++i, ++elfPhdrTemp) {
|
||||||
if (elfPhdrTemp->type != LD_PT_LOAD) {
|
if (elfPhdrTemp->type != LD_PT_LOAD) {
|
||||||
|
@ -538,7 +554,7 @@ STATIC INT32 OsLoadInterpBinary(const ELFLoadInfo *loadInfo, UINTPTR *interpMapB
|
||||||
return -EINVAL;
|
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);
|
interpMapBase, mapSize, &loadBase);
|
||||||
if (ret != LOS_OK) {
|
if (ret != LOS_OK) {
|
||||||
PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__);
|
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);
|
&loadInfo->loadAddr, mapSize, &loadBase);
|
||||||
if (ret != LOS_OK) {
|
if (ret != LOS_OK) {
|
||||||
PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__);
|
PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadInfo->interpInfo.fd != INVALID_FD) {
|
if (loadInfo->interpInfo.procfd != INVALID_FD) {
|
||||||
ret = OsLoadInterpBinary(loadInfo, &interpMapBase);
|
ret = OsLoadInterpBinary(loadInfo, &interpMapBase);
|
||||||
if (ret != LOS_OK) {
|
if (ret != LOS_OK) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -961,12 +977,12 @@ STATIC VOID OsDeInitLoadInfo(ELFLoadInfo *loadInfo)
|
||||||
|
|
||||||
STATIC VOID OsDeInitFiles(ELFLoadInfo *loadInfo)
|
STATIC VOID OsDeInitFiles(ELFLoadInfo *loadInfo)
|
||||||
{
|
{
|
||||||
if (loadInfo->execInfo.fd != INVALID_FD) {
|
if (loadInfo->execInfo.procfd != INVALID_FD) {
|
||||||
(VOID)close(loadInfo->execInfo.fd);
|
(VOID)OsELFClose(loadInfo->execInfo.procfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadInfo->interpInfo.fd != INVALID_FD) {
|
if (loadInfo->interpInfo.procfd != INVALID_FD) {
|
||||||
(VOID)close(loadInfo->interpInfo.fd);
|
(VOID)OsELFClose(loadInfo->interpInfo.procfd);
|
||||||
}
|
}
|
||||||
#ifdef LOSCFG_FS_VFS
|
#ifdef LOSCFG_FS_VFS
|
||||||
delete_files_snapshot((struct files_struct *)loadInfo->oldFiles);
|
delete_files_snapshot((struct files_struct *)loadInfo->oldFiles);
|
||||||
|
|
Loading…
Reference in New Issue