diff --git a/BUILD.gn b/BUILD.gn index aba0de39e3aee571ac91fb765cc82142cba2fd3e..570cebbf962dbc6ee439db88d4a4e73cae809735 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -32,6 +32,7 @@ group("libsqlite") { } ohos_shared_library("sqlite") { + branch_protector_ret = "pac_ret" sources = [ "src/sqlite3.c" ] defines = [ @@ -63,6 +64,9 @@ ohos_shared_library("sqlite") { "SQLITE_CODEC_ATTACH_CHANGED", "SQLITE_ENABLE_DROPTABLE_CALLBACK", "OPENSSL_SUPPRESS_DEPRECATED", + "LOG_DUMP", + "FDSAN_ENABLE", + "HARMONY_OS", ] cflags_c = [ "-fvisibility=hidden", @@ -123,6 +127,9 @@ ohos_executable("sqlite3") { "SQLITE_DIRECT_OVERFLOW_READ", "SQLITE_SHARED_BLOCK_OPTIMIZATION", "OPENSSL_SUPPRESS_DEPRECATED", + "LOG_DUMP", + "FDSAN_ENABLE", + "HARMONY_OS", ] cflags = [ diff --git a/src/sqlite3.c b/src/sqlite3.c index 9988125638de38fb65a6969c6295dfe4761d82a2..b80d9f2aa739cfdf41b171ed6cf9f8e768f5e3a3 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c @@ -21179,6 +21179,10 @@ SQLITE_API extern int sqlite3_open_file_count; #define OpenCounter(X) #endif /* defined(SQLITE_TEST) */ +#ifdef FDSAN_ENABLE +#define SQLITE_FDSAN_TAG 5351 +#endif + #endif /* !defined(_OS_COMMON_H_) */ /************** End of os_common.h *******************************************/ @@ -37124,6 +37128,29 @@ static pid_t randomnessPid = 0; #define F2FS_FEATURE_ATOMIC_WRITE 0x0004 #endif /* __linux__ */ +#ifdef HARMONY_OS +#define HMFS_MONITOR_FL 0x00000002 +#define HMFS_IOCTL_HW_GET_FLAGS _IOR(0xf5, 70, unsigned int) +#define HMFS_IOCTL_HW_SET_FLAGS _IOR(0xf5, 71, unsigned int) + +static void enableDbFileDelMonitor(int32_t fd) +{ + unsigned int flags = 0; + int ret = ioctl(fd, HMFS_IOCTL_HW_GET_FLAGS, &flags); + if (ret < 0) { + return; + } + if (flags & HMFS_MONITOR_FL) { + return; + } + flags |= HMFS_MONITOR_FL; + ret = ioctl(fd, HMFS_IOCTL_HW_SET_FLAGS, &flags); + if (ret < 0) { + sqlite3_log(SQLITE_WARNING, "Fd %d enable del monitor go wrong, errno = %d", fd, errno); + } +} + +#endif /* __HARMONY_OS__ */ /* ** Different Unix systems declare open() in different ways. Same use @@ -37134,7 +37161,29 @@ static pid_t randomnessPid = 0; ** which always has the same well-defined interface. */ static int posixOpen(const char *zFile, int flags, int mode){ - return open(zFile, flags, mode); + int fd = open(zFile, flags, mode); +#ifdef FDSAN_ENABLE + if( fd >= 0 ){ + fdsan_exchange_owner_tag(fd, 0, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, SQLITE_FDSAN_TAG)); + } +#endif +#ifdef HARMONY_OS + if( fd >= 0 ){ + enableDbFileDelMonitor(fd); + } +#endif + return fd; +} + +/* +** Change close to posixClose, use fdsan_close_with_tag when fdsan enable. +*/ +static int posixClose(int fd) { +#ifdef FDSAN_ENABLE + return fdsan_close_with_tag(fd, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, SQLITE_FDSAN_TAG)); +#else + return close(fd); +#endif } /* Forward reference */ @@ -37155,7 +37204,7 @@ static struct unix_syscall { { "open", (sqlite3_syscall_ptr)posixOpen, 0 }, #define osOpen ((int(*)(const char*,int,int))aSyscall[0].pCurrent) - { "close", (sqlite3_syscall_ptr)close, 0 }, + { "close", (sqlite3_syscall_ptr)posixClose, 0 }, #define osClose ((int(*)(int))aSyscall[1].pCurrent) { "access", (sqlite3_syscall_ptr)access, 0 }, @@ -38148,6 +38197,9 @@ static int findInodeInfo( storeLastErrno(pFile, errno); #if defined(EOVERFLOW) && defined(SQLITE_DISABLE_LFS) if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS; +#endif +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR, "findInodeInfo-osFstat, fd[%d], errno[%d], osFstat[%d]", fd, errno, rc); #endif return SQLITE_IOERR; } @@ -38167,11 +38219,17 @@ static int findInodeInfo( do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR ); if( rc!=1 ){ storeLastErrno(pFile, errno); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR, "findInodeInfo-osWrite, fd[%d], errno[%d], osFstat[%d]", fd, errno, rc); +#endif return SQLITE_IOERR; } rc = osFstat(fd, &statbuf); if( rc!=0 ){ storeLastErrno(pFile, errno); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR, "findInodeInfo-msdos-osFstat, fd[%d], errno[%d], osFstat[%d]", fd, errno, rc); +#endif return SQLITE_IOERR; } } @@ -39333,6 +39391,9 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) { #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS return SQLITE_OK; #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_UNLOCK, "IOERR_UNLOCK fd[%d], eFileLock[%d]", pFile->h, eFileLock); +#endif return SQLITE_IOERR_UNLOCK; }else{ pFile->eFileLock = NO_LOCK; @@ -40159,9 +40220,15 @@ static int unixRead( #endif #ifdef EDEVERR case EDEVERR: +#endif +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_CORRUPTFS, "unixRead-EDEVERR, fd:[%d], amt[%d], got[%d], offset[%lld]", pFile->h, amt, got, offset); #endif return SQLITE_IOERR_CORRUPTFS; } +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_READ, "unixRead-got<0, fd: [%d], amt[%d], got[%d], offset[%lld]", pFile->h, amt, got, offset); +#endif return SQLITE_IOERR_READ; }else{ storeLastErrno(pFile, 0); /* not a system error */ @@ -40303,9 +40370,27 @@ static int unixWrite( if( amt>wrote ){ if( wrote<0 && pFile->lastErrno!=ENOSPC ){ /* lastErrno set by seekAndWrite */ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_WRITE, + "unixWrite, lastErrno set by seekAndWrite, fd[%d], offset[%lld], wrote[%d], amt[%d], lastErrno[%d]", + pFile->h, + offset, + wrote, + amt, + pFile->lastErrno); +#endif return SQLITE_IOERR_WRITE; }else{ storeLastErrno(pFile, 0); /* not a system error */ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_WRITE, + "unixWrite, not a system error, fd[%d], offset[%lld], wrote[%d], amt[%d], lastErrno[%d]", + pFile->h, + offset, + wrote, + amt, + pFile->lastErrno); +#endif return SQLITE_FULL; } } @@ -40659,7 +40744,17 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ do{ err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); }while( err==EINTR ); - if( err && err!=EINVAL ) return SQLITE_IOERR_WRITE; + if( err && err!=EINVAL ){ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_WRITE, + "fcntlSizeHint-fallocate, fd[%d], bufSize[%lld], nSize[%lld] err[%d]", + pFile->h, + buf.st_size, + nSize, + err); +#endif + return SQLITE_IOERR_WRITE; + } #else /* If the OS does not have posix_fallocate(), fake it. Write a ** single byte to the last byte in each block that falls entirely @@ -40678,7 +40773,18 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ for(/*no-op*/; iWrite=nSize ) iWrite = nSize - 1; nWrite = seekAndWrite(pFile, iWrite, "", 1); - if( nWrite!=1 ) return SQLITE_IOERR_WRITE; + if( nWrite!=1 ){ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_WRITE, + "fcntlSizeHint-seekAndWrite, fd[%d], nWrite[%d], nSize[%d], nBlk[%d], iWrite[%lld]", + pFile->h, + nWrite, + nSize, + nBlk, + iWrite); +#endif + return SQLITE_IOERR_WRITE; + } } #endif } @@ -40733,14 +40839,29 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ #if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: { int rc = osIoctl(pFile->h, F2FS_IOC_START_ATOMIC_WRITE); +#ifdef LOG_DUMP + if( rc ){ + sqlite3_log(SQLITE_IOERR_BEGIN_ATOMIC, "unixFileControl-begin, fd[%d], op[%d]", pFile->h, op); + } +#endif return rc ? SQLITE_IOERR_BEGIN_ATOMIC : SQLITE_OK; } case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: { int rc = osIoctl(pFile->h, F2FS_IOC_COMMIT_ATOMIC_WRITE); +#ifdef LOG_DUMP + if( rc ){ + sqlite3_log(SQLITE_IOERR_COMMIT_ATOMIC, "unixFileControl-commit, fd[%d], op[%d]", pFile->h, op); + } +#endif return rc ? SQLITE_IOERR_COMMIT_ATOMIC : SQLITE_OK; } case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: { int rc = osIoctl(pFile->h, F2FS_IOC_ABORT_VOLATILE_WRITE); +#ifdef LOG_DUMP + if( rc ){ + sqlite3_log(SQLITE_IOERR_ROLLBACK_ATOMIC, "unixFileControl-rollback, fd[%d], op[%d]", pFile->h, op); + } +#endif return rc ? SQLITE_IOERR_ROLLBACK_ATOMIC : SQLITE_OK; } #endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ @@ -41686,9 +41807,19 @@ static int unixShmLock( int *aLock; p = pDbFd->pShm; - if( p==0 ) return SQLITE_IOERR_SHMLOCK; + if( p==0 ){ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_SHMLOCK, "unixShmLock-pShm, fd[%d], ofst[%d], n[%d], flags[%d]", ofst, n, flags); +#endif + return SQLITE_IOERR_SHMLOCK; + } pShmNode = p->pShmNode; - if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK; + if( NEVER(pShmNode==0) ){ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_SHMLOCK, "unixShmLock-pShmNode, fd[%d], ofst[%d], n[%d], flags[%d]", ofst, n, flags); +#endif + return SQLITE_IOERR_SHMLOCK; + } aLock = pShmNode->aLock; assert( pShmNode==pDbFd->pInode->pShmNode ); @@ -43060,6 +43191,9 @@ static int unixOpen( if( fstatfs(fd, &fsInfo) == -1 ){ storeLastErrno(p, errno); robust_close(p, fd, __LINE__); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_ACCESS, "unixOpen, fd[%d], flags[%d], errno[%d]", fd, errno, flags); +#endif return SQLITE_IOERR_ACCESS; } if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { @@ -43782,6 +43916,9 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){ OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n", lPath, errno, osGetpid(0))); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_LOCK, "proxyGetLockPath len[%d], dbLen[%d], i[%d]", len, dbLen, i); +#endif return SQLITE_IOERR_LOCK; } len = strlcat(lPath, "sqliteplocks", maxLen); @@ -43900,6 +44037,7 @@ static int proxyCreateUnixFile( case EACCES: return SQLITE_PERM; case EIO: + sqlite3_log(SQLITE_IOERR_LOCK, "proxyCreateUnixFile-EIO, fd[%d]", fd); return SQLITE_IOERR_LOCK; /* even though it is the conch */ default: return SQLITE_CANTOPEN_BKPT; @@ -44068,6 +44206,9 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ struct stat buf; if( osFstat(conchFile->h, &buf) ){ storeLastErrno(pFile, errno); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_LOCK, "proxyConchLock pFile fd[%d], conchFile fd[%d], lastErrno[%d]", pFile->h, conchFile->h, errno); +#endif return SQLITE_IOERR_LOCK; } @@ -44088,6 +44229,9 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0); if( len<0 ){ storeLastErrno(pFile, errno); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_LOCK, "proxyConchLock tries 2, pFile fd[%d], conchFile fd[%d], lastErrno[%d]", pFile->h, conchFile->h, errno); +#endif return SQLITE_IOERR_LOCK; } if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){ @@ -44162,6 +44306,9 @@ static int proxyTakeConch(unixFile *pFile){ if( readLen<0 ){ /* I/O error: lastErrno set by seekAndRead */ storeLastErrno(pFile, conchFile->lastErrno); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_READ, "proxyTakeConch pFile fd[%d], conchFile fd[%d], lastErrno[%d]", pFile->h, conchFile->h, conchFile->lastErrno); +#endif rc = SQLITE_IOERR_READ; goto end_takeconch; }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || @@ -65214,7 +65361,9 @@ static void walRestartHdr(Wal *pWal, u32 salt1){ for(i=2; iaReadMark[i] = READMARK_NOT_USED; assert( pInfo->aReadMark[0]==0 ); } +static int checkHeaderValid(Pager *pager, u8 *zBuf, const char *logStr); +static int checkDbHeaderValid(sqlite3 *db, int iDbpage, u8 *zBuf); /* ** Copy as much content as we can from the WAL back into the database file ** in response to an sqlite3_wal_checkpoint() request or the equivalent. @@ -65355,6 +65504,8 @@ static int walCheckpoint( if( rc!=SQLITE_OK ) break; iOffset = (iDbpage-1)*(i64)szPage; testcase( IS_BIG_INT(iOffset) ); + rc = checkDbHeaderValid(db, iDbpage, zBuf); + if( rc!=SQLITE_OK ) break; rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); if( rc!=SQLITE_OK ) break; } @@ -66749,6 +66900,10 @@ static int walWriteOneFrame( int rc; /* Result code from subfunctions */ void *pData; /* Data actually written */ u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */ + if( pPage->pgno==1 ){ + rc = checkHeaderValid(pPage->pPager, pPage->pData, "walWrite"); + if( rc!=SQLITE_OK ) return rc; + } #if defined(SQLITE_HAS_CODEC) if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT; #else @@ -67051,6 +67206,8 @@ SQLITE_PRIVATE int sqlite3WalFrames( return rc; } +static sqlite3_int64 g_lastCkptTime = 0; + /* ** This routine is called to implement sqlite3_wal_checkpoint() and ** related interfaces. @@ -67174,6 +67331,12 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); pWal->ckptLock = 0; } +#ifdef LOG_DUMP + if( rc ){ + sqlite3_log(SQLITE_NOTICE, "ckpt rc[%d]", rc); + } + sqlite3OsCurrentTimeInt64(db->pVfs, &g_lastCkptTime); +#endif WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok")); #ifdef SQLITE_ENABLE_SETLK_TIMEOUT if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY; @@ -68550,6 +68713,30 @@ SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree *pBt){ } #endif +static int checkHeaderValid(Pager *pager, u8 *zBuf, const char *logStr){ +#ifdef SQLITE_HAS_CODEC + if( pager==NULL || pager->pCodec ){ + return SQLITE_OK; + } +#endif + if( zBuf && strncmp((const char *)zBuf, zMagicHeader, 16)!=0 ){ + sqlite3_log(SQLITE_NOTADB, "[%s]wrong header format, memory might be overwritten!", logStr); + return SQLITE_NOTADB; + } + return SQLITE_OK; +} + +static int checkDbHeaderValid(sqlite3 *db, int iDbpage, u8 *zBuf){ + if( iDbpage==1 && db->aDb ){ + Btree *p = db->aDb[0].pBt; + if( p && p->pBt ){ + Pager *pager = sqlite3BtreePager(p); + return checkHeaderValid(pager, zBuf, "ckpt"); + } + } + return SQLITE_OK; +} + /* ** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single ** (MemPage*) as an argument. The (MemPage*) must not be NULL. @@ -70380,6 +70567,24 @@ static int decodeFlags(MemPage *pPage, int flagByte){ pPage->intKeyLeaf = 0; pPage->xCellSize = cellSizePtr; pPage->xParseCell = btreeParseCellPtrIndex; +#ifdef LOG_DUMP + sqlite3_log(SQLITE_CORRUPT, + "database corruption at page[%u], flagByte[%x], isInit[%u], intKey[%u], intKeyLeaf[%u], leaf[%u], " + "childPtrSize[%u], cellOffset[%u], nCell[%u], hdrOffset[%u], minLocal[%u], maxLocal[%u], last ckpt time[%lld]", + pPage->pgno, + flagByte, + pPage->isInit, + pPage->intKey, + pPage->intKeyLeaf, + pPage->leaf, + pPage->childPtrSize, + pPage->cellOffset, + pPage->nCell, + pPage->hdrOffset, + pPage->minLocal, + pPage->maxLocal, + g_lastCkptTime); +#endif return SQLITE_CORRUPT_PAGE(pPage); } pPage->max1bytePayload = pBt->max1bytePayload; @@ -104621,7 +104826,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ sqlite3WalkExprList(pWalker, pList); if( is_agg ){ #ifndef SQLITE_OMIT_WINDOWFUNC - if( pWin ){ + if( pWin && pParse->nErr==0 ){ Select *pSel = pNC->pWinSelect; assert( pWin==0 || (ExprUseYWin(pExpr) && pWin==pExpr->y.pWin) ); if( IN_RENAME_OBJECT==0 ){