]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_filedb/lib/AtomicFile.cpp
Security-58286.270.3.0.1.tar.gz
[apple/security.git] / OSX / libsecurity_filedb / lib / AtomicFile.cpp
index 68049c24a6375527c1e1c8a2cdef6aee1ef25a3d..9dd9bbfdc3580061d399b1cc5b42a0cc935aa39a 100644 (file)
@@ -36,6 +36,7 @@
 #include <copyfile.h>
 #include <sandbox.h>
 #include <set>
+#include <assert.h>
 
 #define kAtomicFileMaxBlockSize INT_MAX
 
@@ -89,7 +90,7 @@ AtomicFile::~AtomicFile()
 {
 }
 
-// Aquire the write lock and remove the file.
+// Acquire the write lock and remove the file.
 void
 AtomicFile::performDelete()
 {
@@ -97,7 +98,7 @@ AtomicFile::performDelete()
        if (::unlink(mPath.c_str()) != 0)
        {
                int error = errno;
-               secdebug("atomicfile", "unlink %s: %s", mPath.c_str(), strerror(error));
+               secinfo("atomicfile", "unlink %s: %s", mPath.c_str(), strerror(error));
         if (error == ENOENT)
                        CssmError::throwMe(CSSMERR_DL_DATASTORE_DOESNOT_EXIST);
                else
@@ -108,7 +109,7 @@ AtomicFile::performDelete()
        ::unlink(mLockFilePath.c_str());
 }
 
-// Aquire the write lock and rename the file (and bump the version and stuff).
+// Acquire the write lock and rename the file (and bump the version and stuff).
 void
 AtomicFile::rename(const std::string &inNewPath)
 {
@@ -120,7 +121,7 @@ AtomicFile::rename(const std::string &inNewPath)
        if (::rename(path, newPath) != 0)
        {
                int error = errno;
-               secdebug("atomicfile", "rename(%s, %s): %s", path, newPath, strerror(error));
+               secinfo("atomicfile", "rename(%s, %s): %s", path, newPath, strerror(error));
                UnixError::throwMe(error);
        }
 }
@@ -139,7 +140,7 @@ AtomicFile::create(mode_t mode)
     if (fileRef == -1)
     {
         int error = errno;
-               secdebug("atomicfile", "open %s: %s", path, strerror(error));
+               secinfo("atomicfile", "open %s: %s", path, strerror(error));
 
         // Do the obvious error code translations here.
                // @@@ Consider moving these up a level.
@@ -157,7 +158,7 @@ AtomicFile::create(mode_t mode)
                // Now that we have created the lock and the new db file create a tempfile
                // object.
                RefPointer<AtomicTempFile> temp(new AtomicTempFile(*this, lock, mode));
-               secdebug("atomicfile", "%p created %s", this, path);
+               secinfo("atomicfile", "%p created %s", this, path);
                return temp;
        }
        catch (...)
@@ -165,7 +166,7 @@ AtomicFile::create(mode_t mode)
                // Creating the temp file failed so remove the db file we just created too.
                if (::unlink(path) == -1)
                {
-                       secdebug("atomicfile", "unlink %s: %s", path, strerror(errno));
+                       secnotice("atomicfile", "unlink %s: %s", path, strerror(errno));
                }
                throw;
        }
@@ -201,7 +202,7 @@ AtomicFile::mode() const
        if (::stat(path, &st) == -1)
        {
                int error = errno;
-               secdebug("atomicfile", "stat %s: %s", path, strerror(error));
+               secinfo("atomicfile", "stat %s: %s", path, strerror(error));
                UnixError::throwMe(error);
        }
        return st.st_mode;
@@ -337,6 +338,7 @@ AtomicFile::ropen(const char *const name, int flags, mode_t mode)
             int result = sandbox_check(getpid(), "file-read-data", (sandbox_filter_type) (SANDBOX_FILTER_PATH | SANDBOX_CHECK_NO_REPORT), name);
             if (result != 0)
             {
+                secdebug("atomicfile", "sandboxing rejected read access to %s", name);
                 return -1;
             }
         }
@@ -346,6 +348,7 @@ AtomicFile::ropen(const char *const name, int flags, mode_t mode)
             int result = sandbox_check(getpid(), "file-write-data", (sandbox_filter_type) (SANDBOX_FILTER_PATH | SANDBOX_CHECK_NO_REPORT), name);
             if (result != 0)
             {
+                secdebug("atomicfile", "sandboxing rejected write access to %s", name);
                 return -1;
             }
         }
@@ -380,8 +383,7 @@ AtomicBufferedFile::AtomicBufferedFile(const std::string &inPath, bool isLocal)
        mPath(inPath),
        mFileRef(-1),
        mBuffer(NULL),
-       mLength(0),
-       mIsMapped(isLocal)
+       mLength(0)
 {
 }
 
@@ -389,13 +391,15 @@ AtomicBufferedFile::~AtomicBufferedFile()
 {
        if (mFileRef >= 0)
        {
-               AtomicFile::rclose(mFileRef);
-               secdebug("atomicfile", "%p closed %s", this, mPath.c_str());
+               // In release mode, the assert() is compiled out so rv may be unused.
+               __unused int rv = AtomicFile::rclose(mFileRef);
+               assert(rv == 0);
+               secinfo("atomicfile", "%p closed %s", this, mPath.c_str());
        }
 
        if (mBuffer)
        {
-               secdebug("atomicfile", "%p free %s buffer %p", this, mPath.c_str(), mBuffer);
+               secinfo("atomicfile", "%p free %s buffer %p", this, mPath.c_str(), mBuffer);
                unloadBuffer();
        }
 }
@@ -409,7 +413,7 @@ AtomicBufferedFile::open()
        const char *path = mPath.c_str();
        if (mFileRef >= 0)
        {
-               secdebug("atomicfile", "open %s: already open, closing and reopening", path);
+               secinfo("atomicfile", "open %s: already open, closing and reopening", path);
                close();
        }
 
@@ -417,7 +421,7 @@ AtomicBufferedFile::open()
     if (mFileRef == -1)
     {
         int error = errno;
-               secdebug("atomicfile", "open %s: %s", path, strerror(error));
+               secinfo("atomicfile", "open %s: %s", path, strerror(error));
 
         // Do the obvious error code translations here.
                // @@@ Consider moving these up a level.
@@ -438,12 +442,13 @@ AtomicBufferedFile::open()
        else
        {
                int error = errno;
-               secdebug("atomicfile", "lseek(%s, END): %s", path, strerror(error));
+               secinfo("atomicfile", "lseek(%s, END): %s", path, strerror(error));
                AtomicFile::rclose(mFileRef);
+               mFileRef = -1;
                UnixError::throwMe(error);
        }
 
-       secdebug("atomicfile", "%p opened %s: %qd bytes", this, path, mLength);
+       secinfo("atomicfile", "%p opened %s: %qd bytes", this, path, mLength);
 
        return mLength;
 }
@@ -454,63 +459,47 @@ AtomicBufferedFile::open()
 void
 AtomicBufferedFile::unloadBuffer()
 {
-       if (!mIsMapped)
-       {
-               delete [] mBuffer;
-       }
-       else
-       {
-               munmap(mBuffer, (size_t)mLength);
-       }
+    if(mBuffer) {
+        delete [] mBuffer;
+        mBuffer = NULL;
+    }
 }
 
 //
 // Load the contents of the file into memory.
-// If we are on a local file system, we mmap the file.  Otherwise, we
-// read it all into memory
 void
 AtomicBufferedFile::loadBuffer()
 {
-       if (!mIsMapped)
-       {
-               // make a buffer big enough to hold the entire file
-               mBuffer = new uint8[mLength];
-               lseek(mFileRef, 0, SEEK_SET);
-               ssize_t pos = 0;
-               
-               ssize_t bytesToRead = (ssize_t)mLength;
-               while (bytesToRead > 0)
-               {
-                       ssize_t bytesRead = ::read(mFileRef, mBuffer + pos, bytesToRead);
-                       if (bytesRead == -1)
-                       {
-                               if (errno != EINTR)
-                               {
-                                       int error = errno;
-                                       secdebug("atomicfile", "lseek(%s, END): %s", mPath.c_str(), strerror(error));
-                                       AtomicFile::rclose(mFileRef);
-                                       UnixError::throwMe(error);
-                               }
-                       }
-                       else
-                       {
-                               bytesToRead -= bytesRead;
-                               pos += bytesRead;
-                       }
-               }
-       }
-       else
-       {
-               // mmap the buffer into place
-               mBuffer = (uint8*) mmap(NULL, (size_t)mLength, PROT_READ, MAP_PRIVATE, mFileRef, 0);
-               if (mBuffer == (uint8*) -1)
-               {
-                       int error = errno;
-                       secdebug("atomicfile", "lseek(%s, END): %s", mPath.c_str(), strerror(error));
-                       AtomicFile::rclose(mFileRef);
-                       UnixError::throwMe(error);
-               }
-       }
+    // make a buffer big enough to hold the entire file
+    mBuffer = new uint8[(size_t) mLength];
+    if(lseek(mFileRef, 0, SEEK_SET) < 0) {
+        int error = errno;
+        secinfo("atomicfile", "lseek(%s, BEGINNING): %s", mPath.c_str(), strerror(error));
+        UnixError::throwMe(error);
+    }
+    ssize_t pos = 0;
+
+    ssize_t bytesToRead = (ssize_t)mLength;
+    while (bytesToRead > 0)
+    {
+        ssize_t bytesRead = ::read(mFileRef, mBuffer + pos, bytesToRead);
+        if (bytesRead == -1)
+        {
+            if (errno != EINTR)
+            {
+                int error = errno;
+                secinfo("atomicfile", "read(%s, %zd): %s", mPath.c_str(), bytesToRead, strerror(error));
+                AtomicFile::rclose(mFileRef);
+                mFileRef = -1;
+                UnixError::throwMe(error);
+            }
+        }
+        else
+        {
+            bytesToRead -= bytesRead;
+            pos += bytesRead;
+        }
+    }
 }
 
 
@@ -526,20 +515,20 @@ AtomicBufferedFile::read(off_t inOffset, off_t inLength, off_t &outLength)
 {
        if (mFileRef < 0)
        {
-               secdebug("atomicfile", "read %s: file yet not opened, opening", mPath.c_str());
+               secinfo("atomicfile", "read %s: file yet not opened, opening", mPath.c_str());
                open();
        }
 
        off_t bytesLeft = inLength;
        if (mBuffer)
        {
-               secdebug("atomicfile", "%p free %s buffer %p", this, mPath.c_str(), mBuffer);
+               secinfo("atomicfile", "%p free %s buffer %p", this, mPath.c_str(), mBuffer);
                unloadBuffer();
        }
 
        loadBuffer();
        
-       secdebug("atomicfile", "%p allocated %s buffer %p size %qd", this, mPath.c_str(), mBuffer, bytesLeft);
+       secinfo("atomicfile", "%p allocated %s buffer %p size %qd", this, mPath.c_str(), mBuffer, bytesLeft);
        
        off_t maxEnd = inOffset + inLength;
        if (maxEnd > mLength)
@@ -557,7 +546,7 @@ AtomicBufferedFile::close()
 {
        if (mFileRef < 0)
        {
-               secdebug("atomicfile", "close %s: already closed", mPath.c_str());
+               secinfo("atomicfile", "close %s: already closed", mPath.c_str());
        }
        else
        {
@@ -566,11 +555,11 @@ AtomicBufferedFile::close()
                if (result == -1)
                {
                        int error = errno;
-                       secdebug("atomicfile", "close %s: %s", mPath.c_str(), strerror(errno));
+                       secnotice("atomicfile", "close %s: %s", mPath.c_str(), strerror(errno));
                        UnixError::throwMe(error);
                }
 
-               secdebug("atomicfile", "%p closed %s", this, mPath.c_str());
+               secinfo("atomicfile", "%p closed %s", this, mPath.c_str());
        }
 }
 
@@ -637,7 +626,7 @@ AtomicTempFile::create(mode_t mode)
     if (mFileRef == -1)
     {
         int error = errno;
-               secdebug("atomicfile", "open %s: %s", path, strerror(error));
+               secnotice("atomicfile", "create %s: %s", path, strerror(error));
 
         // Do the obvious error code translations here.
                // @@@ Consider moving these up a level.
@@ -656,12 +645,12 @@ AtomicTempFile::create(mode_t mode)
                if (::fchmod(mFileRef, mode))
                {
                        int error = errno;
-                       secdebug("atomicfile", "fchmod %s: %s", path, strerror(error));
+                       secnotice("atomicfile", "fchmod %s: %s", path, strerror(error));
                        UnixError::throwMe(error);
                }
        }
 
-       secdebug("atomicfile", "%p created %s", this, path);
+       secinfo("atomicfile", "%p created %s", this, path);
 }
 
 void
@@ -698,7 +687,7 @@ AtomicTempFile::write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const
                if (pos == -1)
                {
                        int error = errno;
-                       secdebug("atomicfile", "lseek(%s, %qd): %s", mPath.c_str(), inOffset, strerror(error));
+                       secnotice("atomicfile", "lseek(%s, %qd): %s", mPath.c_str(), inOffset, strerror(error));
                        UnixError::throwMe(error);
                }
        }
@@ -719,18 +708,18 @@ AtomicTempFile::write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const
                        if (error == EINTR)
                        {
                                // We got interrupted by a signal, so try again.
-                               secdebug("atomicfile", "write %s: interrupted, retrying", mPath.c_str());
+                               secnotice("atomicfile", "write %s: interrupted, retrying", mPath.c_str());
                                continue;
                        }
 
-                       secdebug("atomicfile", "write %s: %s", mPath.c_str(), strerror(error));
+                       secnotice("atomicfile", "write %s: %s", mPath.c_str(), strerror(error));
                        UnixError::throwMe(error);
                }
 
                // Write returning 0 is bad mmkay.
                if (bytesWritten == 0)
                {
-                       secdebug("atomicfile", "write %s: 0 bytes written", mPath.c_str());
+                       secnotice("atomicfile", "write %s: 0 bytes written", mPath.c_str());
                        CssmError::throwMe(CSSMERR_DL_INTERNAL_ERROR);
                }
 
@@ -747,7 +736,7 @@ AtomicTempFile::fsync()
 {
        if (mFileRef < 0)
        {
-               secdebug("atomicfile", "fsync %s: already closed", mPath.c_str());
+               secnotice("atomicfile", "fsync %s: already closed", mPath.c_str());
        }
        else
        {
@@ -760,11 +749,11 @@ AtomicTempFile::fsync()
                if (result == -1)
                {
                        int error = errno;
-                       secdebug("atomicfile", "fsync %s: %s", mPath.c_str(), strerror(errno));
+                       secnotice("atomicfile", "fsync %s: %s", mPath.c_str(), strerror(errno));
                        UnixError::throwMe(error);
                }
 
-               secdebug("atomicfile", "%p fsynced %s", this, mPath.c_str());
+               secinfo("atomicfile", "%p fsynced %s", this, mPath.c_str());
        }
 }
 
@@ -773,7 +762,7 @@ AtomicTempFile::close()
 {
        if (mFileRef < 0)
        {
-               secdebug("atomicfile", "close %s: already closed", mPath.c_str());
+               secnotice("atomicfile", "close %s: already closed", mPath.c_str());
        }
        else
        {
@@ -782,11 +771,11 @@ AtomicTempFile::close()
                if (result == -1)
                {
                        int error = errno;
-                       secdebug("atomicfile", "close %s: %s", mPath.c_str(), strerror(errno));
+                       secnotice("atomicfile", "close %s: %s", mPath.c_str(), strerror(errno));
                        UnixError::throwMe(error);
                }
 
-               secdebug("atomicfile", "%p closed %s", this, mPath.c_str());
+               secinfo("atomicfile", "%p closed %s", this, mPath.c_str());
        }
 }
 
@@ -813,7 +802,7 @@ AtomicTempFile::commit()
                s = copyfile_state_alloc();
 
                if(copyfile(newPath, oldPath, s, COPYFILE_SECURITY | COPYFILE_NOFOLLOW) == -1) // Not fatal
-                       secdebug("atomicfile", "copyfile (%s, %s): %s", oldPath, newPath, strerror(errno));
+                       secnotice("atomicfile", "copyfile (%s, %s): %s", oldPath, newPath, strerror(errno));
 
                copyfile_state_free(s);
                // END <rdar://problem/6991037>
@@ -823,14 +812,14 @@ AtomicTempFile::commit()
                if (::rename(oldPath, newPath) == -1)
                {
                        int error = errno;
-                       secdebug("atomicfile", "rename (%s, %s): %s", oldPath, newPath, strerror(errno));
+                       secnotice("atomicfile", "rename (%s, %s): %s", oldPath, newPath, strerror(errno));
                        UnixError::throwMe(error);
                }
 
+        secnotice("atomicfile", "%p commited %s to %s", this, oldPath, newPath);
+
                // Unlock the lockfile
                mLockedFile = NULL;
-
-               secdebug("atomicfile", "%p commited %s", this, oldPath);
        }
        catch (...)
        {
@@ -853,7 +842,7 @@ AtomicTempFile::rollback() throw()
        const char *path = mPath.c_str();
        if (::unlink(path) == -1)
        {
-               secdebug("atomicfile", "unlink %s: %s", path, strerror(errno));
+               secnotice("atomicfile", "unlink %s: %s", path, strerror(errno));
                // rollback can't throw
        }
 
@@ -863,7 +852,7 @@ AtomicTempFile::rollback() throw()
                const char *path = mFile.path().c_str();
                if (::unlink(path) == -1)
                {
-                       secdebug("atomicfile", "unlink %s: %s", path, strerror(errno));
+                       secnotice("atomicfile", "unlink %s: %s", path, strerror(errno));
                        // rollback can't throw
                }
        }
@@ -923,7 +912,7 @@ LocalFileLocker::lock(mode_t mode)
                int result = flock(mLockFile, LOCK_EX);
                IFDEBUG(double endTime = GetTime());
                
-               IFDEBUG(secdebug("atomictime", "Waited %.4f milliseconds for file lock", (endTime - startTime) * 1000.0));
+               IFDEBUG(secnotice("atomictime", "Waited %.4f milliseconds for file lock", (endTime - startTime) * 1000.0));
                
                // errors at this point are bad
                if (result == -1)
@@ -1017,7 +1006,7 @@ NetworkFileLocker::unique(mode_t mode)
        {
                int error = errno;
                ::syslog(LOG_ERR, "Couldn't create temp file %s: %s", fullname.c_str(), strerror(error));
-               secdebug("atomicfile", "Couldn't create temp file %s: %s", fullname.c_str(), strerror(error));
+               secnotice("atomicfile", "Couldn't create temp file %s: %s", fullname.c_str(), strerror(error));
                UnixError::throwMe(error);
        }
 
@@ -1124,7 +1113,7 @@ NetworkFileLocker::lock(mode_t mode)
                else
                        doSyslog = true;
 
-               secdebug("atomicfile", "Locking %s", path);          /* in order to cater for clock skew: get */
+               secinfo("atomicfile", "Locking %s", path);          /* in order to cater for clock skew: get */
                if (!xcreat(path, mode, t))    /* time t from the filesystem */
                {
                        /* lock acquired, hurray! */
@@ -1147,12 +1136,12 @@ NetworkFileLocker::lock(mode_t mode)
                                {
                                        triedforce=true;
                                        ::syslog(LOG_ERR, "Forced unlock denied on %s", path);
-                                       secdebug("atomicfile", "Forced unlock denied on %s", path);
+                                       secnotice("atomicfile", "Forced unlock denied on %s", path);
                                }
                                else
                                {
                                        ::syslog(LOG_ERR, "Forcing lock on %s", path);
-                                       secdebug("atomicfile", "Forcing lock on %s", path);
+                                       secnotice("atomicfile", "Forcing lock on %s", path);
                                        sleep(16 /* DEFsuspend */);
                                        break;
                                }
@@ -1183,7 +1172,7 @@ NetworkFileLocker::lock(mode_t mode)
                case ENAMETOOLONG:     /* Filename is too long, shorten and retry */
                        if (mPath.size() > mDir.size() + 8)
                        {
-                               secdebug("atomicfile", "Truncating %s and retrying lock", path);
+                               secnotice("atomicfile", "Truncating %s and retrying lock", path);
                                mPath.erase(mPath.end() - 1);
                                path = mPath.c_str();
                                /* Reset retry counter. */
@@ -1202,7 +1191,7 @@ NetworkFileLocker::lock(mode_t mode)
        {
                int error = errno;
                ::syslog(LOG_ERR, "Lock failure on %s: %s", path, strerror(error));
-               secdebug("atomicfile", "Lock failure on %s: %s", path, strerror(error));
+               secnotice("atomicfile", "Lock failure on %s: %s", path, strerror(error));
                UnixError::throwMe(error);
        }
 }
@@ -1213,7 +1202,7 @@ NetworkFileLocker::unlock()
        const char *path = mPath.c_str();
        if (::unlink(path) == -1)
        {
-               secdebug("atomicfile", "unlink %s: %s", path, strerror(errno));
+               secnotice("atomicfile", "unlink %s: %s", path, strerror(errno));
                // unlock can't throw
        }
 }