From: adam Date: Wed, 16 May 2012 22:08:18 +0000 (+0000) Subject: Improve error reporting from sqlite3_file_control, SQLITE_FCNTL_REPLACE_DATABASE... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a1c468c3c3bf60c0067385fb8d7f878b8ddfa89;p=thirdparty%2Fsqlite.git Improve error reporting from sqlite3_file_control, SQLITE_FCNTL_REPLACE_DATABASE shouldn't copy file security/ACL metadata, bad bit mask fixed FossilOrigin-Name: 92e7bb907802c905f99ed4c47669f97723f63ed3 --- diff --git a/manifest b/manifest index 4d25672661..b5ba5bd448 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Version\s3.7.12 -D 2012-05-14T02:05:15.770 +C Improve\serror\sreporting\sfrom\ssqlite3_file_control,\sSQLITE_FCNTL_REPLACE_DATABASE\sshouldn't\scopy\sfile\ssecurity/ACL\smetadata,\sbad\sbit\smask\sfixed +D 2012-05-16T22:08:18.407 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 957c9693400fca6cb8b533b589e69ddee7bcb27c F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -143,7 +143,7 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c 015826a958f690302d27e096a68d50b3657e4201 F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416 F src/loadext.c f20382fbaeec832438a1ba7797bee3d3c8a6d51d -F src/main.c 75cdf5977022fe92a8fc2327934fd2ab4ccd29c0 +F src/main.c 9c3003dc0a5e2c7e1d79cf94a08229dd803fd8df F src/malloc.c 15afac5e59b6584efe072e9933aefb4230e74f97 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c b3677415e69603d6a0e7c5410a1b3731d55beda1 @@ -162,7 +162,7 @@ F src/os.c 4c8c8d72a6c58ad2fde4865783e8ae26b494a85e F src/os.h 59beba555b65a450bd1d804220532971d4299f60 F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440 -F src/os_unix.c f8c943a0f9c4e2e7fae9facb3a243cb58cc8ceb5 +F src/os_unix.c a87e927ca7c7d8cab313f8263cd24ea06fc20169 F src/os_win.c 24b57b4aec07ec78ae759244ab6d9759a70fe29b F src/pager.c 544cc84d50fea0ca921d448037b217ecabba359b F src/pager.h 42926ac0fe69e9d7e17a54e6b37417e581a429d7 @@ -179,7 +179,7 @@ F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1 F src/select.c cf2f8f771bab6417e51a0f17b086a87bb74d624c F src/shell.c 04399b2f9942bd02ed5ffee3b84bcdb39c52a1e6 F src/sqlite.h.in 192eb22f3f217c00ff48a8da356a8a020f6b4a8e -F src/sqlite3_private.h 97a1e15b3a078bb583622da01a2e9bc96c6edf14 +F src/sqlite3_private.h a81a9c5f97c095cc3e86914a05f8fabe0011f4a1 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 F src/sqliteInt.h ec90f0d797bbc93dd849629f18513b57bfd9a787 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d @@ -1002,7 +1002,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh a8a0a3babda96dfb1ff51adda3cbbf3dfb7266c2 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P bf57f0fb73500f384fc57cbe2501343c97dc433e 8654aa9540fe9fd210899d83d17f3f407096c004 -R 12b92e18e3ce253aa9f29c615d138e39 -U drh -Z f2b43ef80e7018715193d790be637b9b +P d9348b2a4e15873756adfd092e8128d9f1cf72b4 +R e2d571d2583903dcbc6ab145be90448d +U adam +Z f6b6e32f1d1ba2c99da3b7a6e5f275fb diff --git a/manifest.uuid b/manifest.uuid index a8d2839d7f..92cff82b2d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d9348b2a4e15873756adfd092e8128d9f1cf72b4 \ No newline at end of file +92e7bb907802c905f99ed4c47669f97723f63ed3 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 0282e7443c..c4c4de85f3 100644 --- a/src/main.c +++ b/src/main.c @@ -2844,7 +2844,7 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ }else if( fd->pMethods ){ rc = sqlite3OsFileControl(fd, op, pArg); #ifndef SQLITE_OMIT_WAL - if( (op==SQLITE_FCNTL_LAST_ERRNO)&&(*(int *)pArg==0) ){ + if( (rc==SQLITE_OK)&&(op==SQLITE_FCNTL_LAST_ERRNO)&&(*(int *)pArg==0) ){ sqlite3_file *pWalFd = sqlite3PagerWalFile(pPager); if( pWalFd&&(pWalFd->pMethods) ){ rc = sqlite3OsFileControl(pWalFd, op, pArg); @@ -2856,8 +2856,9 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ } sqlite3BtreeLeave(pBtree); } + sqlite3Error(db, rc, 0); sqlite3_mutex_leave(db->mutex); - return rc; + return rc; } /* diff --git a/src/os_unix.c b/src/os_unix.c index 3f5c728a2e..2ed927d2ad 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -3972,6 +3972,47 @@ static int unixTruncateDatabase(unixFile *, int); static int unixInvalidateSupportFiles(unixFile *, int); +static int findCreateFileMode(const char *, int, mode_t*, uid_t *,gid_t *); + +/* opens a read/write connection to a file zName inheriting the appropriate + ** user/perms from the database file if running as root. Returns the file + ** descriptor by reference */ +static int unixOpenChildFile(const char *zName, int openFlags, int dbOpenFlags, int protFlags, int *pFd) { + int fd = -1; + mode_t openMode; /* Permissions to create file with */ + uid_t uid; /* Userid for the file */ + gid_t gid; /* Groupid for the file */ + int rc; + + assert(pFd!=NULL); + rc = findCreateFileMode(zName, dbOpenFlags, &openMode, &uid, &gid); + if( rc!=SQLITE_OK ){ + return rc; + } + fd = robust_open(zName, openFlags, openMode); + OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags)); + if( fd<0 ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); + return rc; + } + /* if we're opening the wal or journal and running as root, set the journal uid/gid */ + if( dbOpenFlags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ + uid_t euid = geteuid(); + if( euid==0 && (euid!=uid || getegid()!=gid) ){ + if( fchown(fd, uid, gid) ){ + rc = SQLITE_CANTOPEN_BKPT; + } + } + } + if( rc==SQLITE_OK ){ + *pFd = fd; + } else { + *pFd = -1; + close(fd); + } + return rc; +} + static int unixReplaceDatabase(unixFile *pFile, sqlite3 *srcdb) { sqlite3_file *id = (sqlite3_file *)pFile; Btree *pSrcBtree = NULL; @@ -4072,14 +4113,16 @@ static int unixReplaceDatabase(unixFile *pFile, sqlite3 *srcdb) { if( !(srcWalFD<0) ){ char dstWalPath[MAXPATHLEN+5]; int dstWalFD = -1; + int protFlags = 0; strlcpy(dstWalPath, pFile->zPath, MAXPATHLEN+5); strlcat(dstWalPath, "-wal", MAXPATHLEN+5); - dstWalFD = open(dstWalPath, O_RDWR|O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS); - if( !(dstWalFD<0) ){ + + rc = unixOpenChildFile(dstWalPath, O_RDWR|O_CREAT, SQLITE_OPEN_WAL, protFlags, &dstWalFD); + if( rc==SQLITE_OK ){ s = copyfile_state_alloc(); lseek(srcWalFD, 0, SEEK_SET); lseek(dstWalFD, 0, SEEK_SET); - if( fcopyfile(srcWalFD, dstWalFD, s, COPYFILE_ALL) ){ + if( fcopyfile(srcWalFD, dstWalFD, s, COPYFILE_DATA) ){ int err=errno; switch(err) { case ENOMEM: @@ -4106,7 +4149,7 @@ static int unixReplaceDatabase(unixFile *pFile, sqlite3 *srcdb) { s = copyfile_state_alloc(); lseek(pSrcFile->h, 0, SEEK_SET); lseek(pFile->h, 0, SEEK_SET); - if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_ALL) ){ + if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_DATA) ){ int err=errno; switch(err) { case ENOMEM: @@ -5093,6 +5136,9 @@ static int unixUnsafeTruncateDatabase(unixFile *pFile){ char walPath[MAXPATHLEN]; int rc = SQLITE_OK; +#ifdef DEBUG + fprintf(stderr, "Force truncating database %s\n", pFile->zPath); +#endif strlcpy(journalPath, pFile->zPath, MAXPATHLEN); strlcat(journalPath, "-journal", MAXPATHLEN); strlcpy(walPath, pFile->zPath, MAXPATHLEN); @@ -5167,7 +5213,8 @@ static int unixTruncateDatabase(unixFile *pFile, int bFlags) { int corruptFileLock = 0; int isCorrupt = 0; int force = (bFlags & SQLITE_TRUNCATE_FORCE); - + int safeFailed = 0; + #if SQLITE_ENABLE_DATA_PROTECTION flags |= pFile->protFlags; #endif @@ -5186,6 +5233,7 @@ static int unixTruncateDatabase(unixFile *pFile, int bFlags) { if( rc && !force ){ return rc; } + rc = SQLITE_OK; /* Ignore the locking failure if force is true */ } if( (bFlags&SQLITE_TRUNCATE_INITIALIZE_HEADER_MASK)!=0 ){ /* initialize a new database in TMPDIR and copy the contents over */ @@ -5200,10 +5248,7 @@ static int unixTruncateDatabase(unixFile *pFile, int bFlags) { if( tFd==-1 ){ storeLastErrno(pFile, errno); rc = SQLITE_IOERR; - if( force ){ - /* attempt the truncation, even if we can't seed the database in a temp directory */ - rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L); - } + safeFailed = 1; }else{ sqlite3 *tDb = NULL; copyfile_state_t s; @@ -5247,28 +5292,38 @@ static int unixTruncateDatabase(unixFile *pFile, int bFlags) { s = copyfile_state_alloc(); lseek(tFd, 0, SEEK_SET); lseek(pFile->h, 0, SEEK_SET); - if( fcopyfile(tFd, pFile->h, s, COPYFILE_ALL) ){ + if( fcopyfile(tFd, pFile->h, s, COPYFILE_DATA) ){ int err=errno; switch(err) { case ENOMEM: - rc = SQLITE_NOMEM; + trc = SQLITE_NOMEM; break; default: storeLastErrno(pFile, err); - rc = SQLITE_IOERR; + trc = SQLITE_IOERR; } } copyfile_state_free(s); fsync(pFile->h); close(tFd); unlink(tDbPath); + if( trc!=SQLITE_OK ){ + safeFailed = 1; + rc = trc; + } } free(tDbPath); } else { rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L); + if( rc ){ + safeFailed = 1; + } } if( rc==SQLITE_OK || force ){ - unixInvalidateSupportFiles(pFile, 0); + rc = unixInvalidateSupportFiles(pFile, 0); + if( rc ){ + safeFailed = 1; + } } pFile->pMethod->xSync(id, SQLITE_SYNC_FULL); @@ -5281,8 +5336,8 @@ static int unixTruncateDatabase(unixFile *pFile, int bFlags) { assert(force); } - if( rc!=SQLITE_OK && force){ - unixUnsafeTruncateDatabase(pFile); + if( force && safeFailed){ + rc = unixUnsafeTruncateDatabase(pFile); } return rc; diff --git a/src/sqlite3_private.h b/src/sqlite3_private.h index a81bc59b94..29ad216138 100644 --- a/src/sqlite3_private.h +++ b/src/sqlite3_private.h @@ -49,7 +49,7 @@ extern int _sqlite3_lockstate(const char *path, pid_t pid); */ #define SQLITE_FCNTL_TRUNCATE_DATABASE 101 #define SQLITE_TRUNCATE_DATABASE SQLITE_FCNTL_TRUNCATE_DATABASE -#define SQLITE_TRUNCATE_INITIALIZE_HEADER_MASK (0x63<<0) +#define SQLITE_TRUNCATE_INITIALIZE_HEADER_MASK (0x7F<<0) #define SQLITE_TRUNCATE_JOURNALMODE_WAL (0x1<<0) #define SQLITE_TRUNCATE_AUTOVACUUM_MASK (0x3<<2) #define SQLITE_TRUNCATE_AUTOVACUUM_OFF (0x1<<2)