diff options
author | drh <drh@noemail.net> | 2019-11-22 00:42:01 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2019-11-22 00:42:01 +0000 |
commit | c398c65bee850b6b8f24a44852872a27f114535d (patch) | |
tree | 400756f2c2735468faaa02daa969838df2854778 /src | |
parent | cd30064bd502b9b42a4e0c0e04850f09cefa2617 (diff) | |
download | sqlite-c398c65bee850b6b8f24a44852872a27f114535d.tar.gz sqlite-c398c65bee850b6b8f24a44852872a27f114535d.zip |
Revise the SQLITE_OPEN_NOFOLLOW so that it actually uses O_NOFOLLOW in the
open() system call. This backs out the SQLITE_ACCESS_SYMLINK value but adds
the new SQLITE_OK_SYMLINK return code from the xFullPathname method of
sqlite3_vfs when that routine resolves symbolic links. O_NOFOLLOW is always
included in open() system calls for journal files.
FossilOrigin-Name: 6a64fb6a2da6c98f1e87b55ad5689967e1db4eae2e08345471d95e28cd567e0f
Diffstat (limited to 'src')
-rw-r--r-- | src/btree.c | 10 | ||||
-rw-r--r-- | src/os.c | 2 | ||||
-rw-r--r-- | src/os_unix.c | 42 | ||||
-rw-r--r-- | src/os_win.c | 12 | ||||
-rw-r--r-- | src/pager.c | 15 | ||||
-rw-r--r-- | src/sqlite.h.in | 2 | ||||
-rw-r--r-- | src/test_demovfs.c | 6 | ||||
-rw-r--r-- | src/test_vfs.c | 1 |
8 files changed, 36 insertions, 54 deletions
diff --git a/src/btree.c b/src/btree.c index 57634f69b..d0eed5dd4 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2403,9 +2403,13 @@ int sqlite3BtreeOpen( rc = sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname); if( rc ){ - sqlite3_free(zFullPathname); - sqlite3_free(p); - return rc; + if( rc==SQLITE_OK_SYMLINK ){ + rc = SQLITE_OK; + }else{ + sqlite3_free(zFullPathname); + sqlite3_free(p); + return rc; + } } } #if SQLITE_THREADSAFE @@ -215,7 +215,7 @@ int sqlite3OsOpen( ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before ** reaching the VFS. */ - rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut); + rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut); assert( rc==SQLITE_OK || pFile->pMethods==0 ); return rc; } diff --git a/src/os_unix.c b/src/os_unix.c index 7217a5d5f..18f2afcb6 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -3685,7 +3685,7 @@ static int openDirectory(const char *zFilename, int *pFd){ if( zDirname[0]!='/' ) zDirname[0] = '.'; zDirname[1] = 0; } - fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0); + fd = robust_open(zDirname, O_RDONLY|O_BINARY|O_NOFOLLOW, 0); if( fd>=0 ){ OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); } @@ -4576,10 +4576,12 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ if( pInode->bProcessLock==0 ){ if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ - pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT,(sStat.st_mode&0777)); + pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT|O_NOFOLLOW, + (sStat.st_mode&0777)); } if( pShmNode->hShm<0 ){ - pShmNode->hShm = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777)); + pShmNode->hShm = robust_open(zShm, O_RDONLY|O_NOFOLLOW, + (sStat.st_mode&0777)); if( pShmNode->hShm<0 ){ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm); goto shm_open_err; @@ -5929,7 +5931,7 @@ static int unixOpen( unixFile *p = (unixFile *)pFile; int fd = -1; /* File descriptor returned by open() */ int openFlags = 0; /* Flags to pass to open() */ - int eType = flags&0xFFFFFF00; /* Type of file to open */ + int eType = flags&0x0FFF00; /* Type of file to open */ int noLock; /* True to omit locking primitives */ int rc = SQLITE_OK; /* Function Return Code */ int ctrlFlags = 0; /* UNIXFILE_* flags */ @@ -6039,7 +6041,7 @@ static int unixOpen( if( isReadWrite ) openFlags |= O_RDWR; if( isCreate ) openFlags |= O_CREAT; if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW); - openFlags |= (O_LARGEFILE|O_BINARY); + openFlags |= (O_LARGEFILE|O_BINARY|O_NOFOLLOW); if( fd<0 ){ mode_t openMode; /* Permissions to create file with */ @@ -6251,25 +6253,15 @@ static int unixAccess( SimulateIOError( return SQLITE_IOERR_ACCESS; ); assert( pResOut!=0 ); - /* The spec says there are four possible values for flags. But the - ** SQLITE_ACCESS_READ flag is never used */ - assert( flags==SQLITE_ACCESS_EXISTS - || flags==SQLITE_ACCESS_READWRITE - || flags==SQLITE_ACCESS_SYMLINK ); + /* The spec says there are three possible values for flags. But only + ** two of them are actually used */ + assert( flags==SQLITE_ACCESS_EXISTS || flags==SQLITE_ACCESS_READWRITE ); if( flags==SQLITE_ACCESS_EXISTS ){ struct stat buf; *pResOut = (0==osStat(zPath, &buf) && buf.st_size>0); - }else if( flags==SQLITE_ACCESS_READWRITE ){ - *pResOut = osAccess(zPath, W_OK|R_OK)==0; }else{ -#if !defined(HAVE_LSTAT) - *pResOut = 0; -#else - struct stat buf; - *pResOut = (0==osLstat(zPath, &buf) && S_ISLNK(buf.st_mode)); -#endif - assert( flags==SQLITE_ACCESS_SYMLINK ); + *pResOut = osAccess(zPath, W_OK|R_OK)==0; } return SQLITE_OK; } @@ -6321,7 +6313,7 @@ static int unixFullPathname( #else int rc = SQLITE_OK; int nByte; - int nLink = 1; /* Number of symbolic links followed so far */ + int nLink = 0; /* Number of symbolic links followed so far */ const char *zIn = zPath; /* Input path for each iteration of loop */ char *zDel = 0; @@ -6350,10 +6342,11 @@ static int unixFullPathname( } if( bLink ){ + nLink++; if( zDel==0 ){ zDel = sqlite3_malloc(nOut); if( zDel==0 ) rc = SQLITE_NOMEM_BKPT; - }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ + }else if( nLink>=SQLITE_MAX_SYMLINKS ){ rc = SQLITE_CANTOPEN_BKPT; } @@ -6389,6 +6382,7 @@ static int unixFullPathname( }while( rc==SQLITE_OK ); sqlite3_free(zDel); + if( rc==SQLITE_OK && nLink ) rc = SQLITE_OK_SYMLINK; return rc; #endif /* HAVE_READLINK && HAVE_LSTAT */ } @@ -6874,7 +6868,7 @@ static int proxyCreateUnixFile( int fd = -1; unixFile *pNew; int rc = SQLITE_OK; - int openFlags = O_RDWR | O_CREAT; + int openFlags = O_RDWR | O_CREAT | O_NOFOLLOW; sqlite3_vfs dummyVfs; int terrno = 0; UnixUnusedFd *pUnused = NULL; @@ -6904,7 +6898,7 @@ static int proxyCreateUnixFile( } } if( fd<0 ){ - openFlags = O_RDONLY; + openFlags = O_RDONLY | O_NOFOLLOW; fd = robust_open(path, openFlags, 0); terrno = errno; } @@ -7030,7 +7024,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){ goto end_breaklock; } /* write it out to the temporary break file */ - fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), 0); + fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW), 0); if( fd<0 ){ sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno); goto end_breaklock; diff --git a/src/os_win.c b/src/os_win.c index 698d6556c..32758ab76 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -81,14 +81,6 @@ #endif /* -** This constant is needed by the winAccess function; therefore, define -** it when it is missing from the SDK header files. -*/ -#ifndef FILE_ATTRIBUTE_REPARSE_POINT -# define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400 -#endif - -/* ** Check to see if the GetVersionEx[AW] functions are deprecated on the ** target system. GetVersionEx was first deprecated in Win8.1. */ @@ -5480,10 +5472,6 @@ static int winAccess( rc = attr!=INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_READONLY)==0; break; - case SQLITE_ACCESS_SYMLINK: - rc = attr!=INVALID_FILE_ATTRIBUTES && - (attr & FILE_ATTRIBUTE_REPARSE_POINT)!=0; - break; default: assert(!"Invalid flags argument"); } diff --git a/src/pager.c b/src/pager.c index 67e757640..9d4922c4a 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4790,12 +4790,6 @@ int sqlite3PagerOpen( */ if( zFilename && zFilename[0] ){ const char *z; - if( (vfsFlags & SQLITE_OPEN_NOFOLLOW)!=0 ){ - int isLink = 0; - int rc = sqlite3OsAccess(pVfs, zFilename, SQLITE_ACCESS_SYMLINK, &isLink); - if( rc==SQLITE_OK && isLink ) rc = SQLITE_CANTOPEN_SYMLINK; - if( rc ) return rc; - } nPathname = pVfs->mxPathname+1; zPathname = sqlite3DbMallocRaw(0, nPathname*2); if( zPathname==0 ){ @@ -4803,6 +4797,15 @@ int sqlite3PagerOpen( } zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */ rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_OK_SYMLINK ){ + if( vfsFlags & SQLITE_OPEN_NOFOLLOW ){ + rc = SQLITE_CANTOPEN_SYMLINK; + }else{ + rc = SQLITE_OK; + } + } + } nPathname = sqlite3Strlen30(zPathname); z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1]; while( *z ){ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 8373f5c7f..53fb22651 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -541,6 +541,7 @@ int sqlite3_exec( #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) #define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8)) +#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* ** CAPI3REF: Flags For File Open Operations @@ -1408,7 +1409,6 @@ struct sqlite3_vfs { #define SQLITE_ACCESS_EXISTS 0 #define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */ #define SQLITE_ACCESS_READ 2 /* Unused */ -#define SQLITE_ACCESS_SYMLINK 3 /* Test if file is symbolic link */ /* ** CAPI3REF: Flags for the xShmLock VFS method diff --git a/src/test_demovfs.c b/src/test_demovfs.c index baf14b10b..eaba20873 100644 --- a/src/test_demovfs.c +++ b/src/test_demovfs.c @@ -508,14 +508,8 @@ static int demoAccess( assert( flags==SQLITE_ACCESS_EXISTS /* access(zPath, F_OK) */ || flags==SQLITE_ACCESS_READ /* access(zPath, R_OK) */ || flags==SQLITE_ACCESS_READWRITE /* access(zPath, R_OK|W_OK) */ - || flags==SQLITE_ACCESS_SYMLINK /* Always false */ ); - if( flags==SQLITE_ACCESS_SYMLINK ){ - /* For this demo implementation, assume that symlinks do not exist. */ - *pResOut = 0; - return SQLITE_OK; - } if( flags==SQLITE_ACCESS_READWRITE ) eAccess = R_OK|W_OK; if( flags==SQLITE_ACCESS_READ ) eAccess = R_OK; diff --git a/src/test_vfs.c b/src/test_vfs.c index f1ed8d051..9d753896e 100644 --- a/src/test_vfs.c +++ b/src/test_vfs.c @@ -732,7 +732,6 @@ static int tvfsAccess( if( flags==SQLITE_ACCESS_EXISTS ) zArg = "SQLITE_ACCESS_EXISTS"; if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE"; if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ"; - if( flags==SQLITE_ACCESS_SYMLINK ) zArg = "SQLITE_ACCESS_SYMLINK"; tvfsExecTcl(p, "xAccess", Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0, 0 ); |