X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/fa7225c82381bac4432a6edf16f53b5370238d85..7e6b461318c8a779d91381531435a68ee4e8b6ed:/securityd/src/SharedMemoryServer.cpp?ds=sidebyside diff --git a/securityd/src/SharedMemoryServer.cpp b/securityd/src/SharedMemoryServer.cpp index cb01af52..60176b1b 100644 --- a/securityd/src/SharedMemoryServer.cpp +++ b/securityd/src/SharedMemoryServer.cpp @@ -1,6 +1,30 @@ +/* + * Copyright (c) 2016-2017 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include "SharedMemoryServer.h" #include #include +#include #include #include #include @@ -8,50 +32,92 @@ #include #include #include +#include + +/* + Logically, these should go in /var/run/mds, but we know that /var/db/mds + already exists at install time. +*/ + +static bool makedir(const char *path, mode_t mode) { + // Returns true on success. Primarily to centralize logging + if (::mkdir(path, mode)==0 || errno==EEXIST) { + return true; + } else { + secdebug("MDSPRIVACY","Failed to make directory: %s (%d)", path, errno); + return false; + } +} -static const char* kPrefix = "/private/var/db/mds/messages/se_"; +static void unlinkfile(const char *path) { + // Primarily to centralize logging + if (::unlink(path)==-1) { + secdebug("MDSPRIVACY","Failed to unlink file: %s (%d)", path, errno); + } +} -SharedMemoryServer::SharedMemoryServer (const char* segmentName, SegmentOffsetType segmentSize) : - mSegmentName (segmentName), mSegmentSize (segmentSize) +SharedMemoryServer::SharedMemoryServer (const char* segmentName, SegmentOffsetType segmentSize, uid_t uid, gid_t gid) : + mSegmentName (segmentName), mSegmentSize (segmentSize), mUID(SharedMemoryCommon::fixUID(uid)) { - mFileName = kPrefix; - mFileName += segmentName; - - // make the mds directory, just in case it doesn't exist - mkdir("/var/db/mds", 1777); - mkdir("/var/db/mds/messages", 0755); - - // make the file name - // clean any old file away - unlink (mFileName.c_str ()); - - // open the file - mBackingFile = open (mFileName.c_str (), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (mBackingFile < 0) - { - return; - } - - // set the segment size - ftruncate (mBackingFile, segmentSize); - - // map it into memory - mSegment = (u_int8_t*) mmap (NULL, mSegmentSize, PROT_READ | PROT_WRITE, MAP_SHARED, mBackingFile, 0); + const mode_t perm1777 = S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO; + const mode_t perm0755 = S_IRWXU | (S_IRGRP | S_IXGRP) | (S_IROTH | S_IXOTH); + const mode_t perm0600 = (S_IRUSR | S_IWUSR); + + // make the mds directory, just in case it doesn't exist + if (mUID == 0) { + makedir(SharedMemoryCommon::kMDSDirectory, perm1777); + makedir(SharedMemoryCommon::kMDSMessagesDirectory, perm0755); + } else { + // Assume kMDSMessagesDirectory was created first by securityd + std::string uidstr = std::to_string(mUID); + std::string upath = SharedMemoryCommon::kMDSMessagesDirectory; + upath += "/" + uidstr; + makedir(upath.c_str(), perm0755); + } + mFileName = SharedMemoryCommon::SharedMemoryFilePath(segmentName, uid); + + // make the file name + // clean any old file away + unlinkfile(mFileName.c_str()); + + // open the file + secdebug("MDSPRIVACY","creating %s",mFileName.c_str ()); + if(mUID != 0) { + mBackingFile = open (mFileName.c_str (), O_RDWR | O_CREAT | O_EXCL, perm0600); + } + else { + mBackingFile = open (mFileName.c_str (), O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + } - if (mSegment == (u_int8_t*) -1) // can't map the memory? - { - mSegment = NULL; - unlink (mFileName.c_str()); - } - - mDataPtr = mDataArea = mSegment + sizeof(SegmentOffsetType); - mDataMax = mSegment + segmentSize;; - - SetProducerOffset (0); + if (mBackingFile < 0) + { + secdebug("MDSPRIVACY","creation of %s failed", mFileName.c_str()); + return; + } + + int rx = fchown(mBackingFile, uid, gid); + if (rx) { + secdebug("MDSPRIVACY","chown of %s to %d/%d failed : %d", mFileName.c_str(), uid, gid, rx); + } + + // set the segment size + ftruncate (mBackingFile, segmentSize); + + // map it into memory + mSegment = (u_int8_t*) mmap (NULL, mSegmentSize, PROT_READ | PROT_WRITE, MAP_SHARED, mBackingFile, 0); + + if (mSegment == MAP_FAILED) // can't map the memory? + { + mSegment = NULL; + unlinkfile(mFileName.c_str()); + } else { + mDataPtr = mDataArea = mSegment + sizeof(SegmentOffsetType); + mDataMax = mSegment + segmentSize;; + + SetProducerOffset (0); + } } - - SharedMemoryServer::~SharedMemoryServer () { // go away @@ -66,7 +132,7 @@ SharedMemoryServer::~SharedMemoryServer () close(mBackingFile); // mark the segment for deletion - unlink (mFileName.c_str ()); + unlinkfile(mFileName.c_str ()); } @@ -80,18 +146,21 @@ const SegmentOffsetType void SharedMemoryServer::WriteMessage (SegmentOffsetType domain, SegmentOffsetType event, const void *message, SegmentOffsetType messageLength) { - // backing file MUST be right size - ftruncate (mBackingFile, mSegmentSize); + // backing file MUST be right size, don't ftruncate() more then needed though to avoid reaching too deep into filesystem + struct stat sb; + if (::fstat(mBackingFile, &sb) == 0 && sb.st_size != (off_t)mSegmentSize) { + ::ftruncate(mBackingFile, mSegmentSize); + } // assemble the final message ssize_t messageSize = kHeaderLength + messageLength; - u_int8_t finalMessage[messageSize]; - SegmentOffsetType *fm = (SegmentOffsetType*) finalMessage; + std::vector finalMessage(messageSize); + SegmentOffsetType *fm = (SegmentOffsetType*) finalMessage.data(); fm[0] = OSSwapHostToBigInt32(domain); fm[1] = OSSwapHostToBigInt32(event); memcpy(&fm[2], message, messageLength); - SegmentOffsetType crc = CalculateCRC(finalMessage, messageSize); + SegmentOffsetType crc = CalculateCRC(finalMessage.data(), messageSize); // write the length WriteOffset(int_cast(messageSize)); @@ -100,7 +169,7 @@ void SharedMemoryServer::WriteMessage (SegmentOffsetType domain, SegmentOffsetTy WriteOffset(crc); // write the data - WriteData (finalMessage, int_cast(messageSize)); + WriteData (finalMessage.data(), int_cast(messageSize)); // write the data count SetProducerOffset(int_cast(mDataPtr - mDataArea));