From c7d2c2c6ee645e10cbccdd01c6191873ec77239d Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 25 Feb 2016 22:12:46 +0000 Subject: [PATCH] xnu-3248.30.4.tar.gz --- bsd/kern/kern_descrip.c | 7 +++++- bsd/sys/priv.h | 3 ++- config/MasterVersion | 2 +- iokit/IOKit/IOUserClient.h | 3 ++- iokit/Kernel/IOBufferMemoryDescriptor.cpp | 1 + iokit/Kernel/IOMemoryDescriptor.cpp | 28 ++++++++++++++--------- iokit/Kernel/IOUserClient.cpp | 27 ++++++++++++++++++++-- libkern/libkern/Makefile | 4 ---- 8 files changed, 54 insertions(+), 21 deletions(-) diff --git a/bsd/kern/kern_descrip.c b/bsd/kern/kern_descrip.c index df33970ca..62a9d94f7 100644 --- a/bsd/kern/kern_descrip.c +++ b/bsd/kern/kern_descrip.c @@ -81,6 +81,7 @@ #include #include #include +#include #include #include #include @@ -2018,7 +2019,11 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, int32_t *retval) struct vnode *dst_vp = NULLVP; /* We need to grab the 2nd FD out of the argments before moving on. */ int fd2 = CAST_DOWN_EXPLICIT(int32_t, uap->arg); - + + error = priv_check_cred(kauth_cred_get(), PRIV_VFS_MOVE_DATA_EXTENTS, 0); + if (error) + goto out; + if (fp->f_type != DTYPE_VNODE) { error = EBADF; goto out; diff --git a/bsd/sys/priv.h b/bsd/sys/priv.h index ff38da81d..fe42c655d 100644 --- a/bsd/sys/priv.h +++ b/bsd/sys/priv.h @@ -113,7 +113,8 @@ /* * VFS privileges */ -#define PRIV_VFS_OPEN_BY_ID 14000 /*Allow calling openbyid_np()*/ +#define PRIV_VFS_OPEN_BY_ID 14000 /* Allow calling openbyid_np() */ +#define PRIV_VFS_MOVE_DATA_EXTENTS 14001 /* Allow F_MOVEDATAEXTENTS fcntl */ #ifdef KERNEL /* diff --git a/config/MasterVersion b/config/MasterVersion index a378f284b..6e5b5944b 100644 --- a/config/MasterVersion +++ b/config/MasterVersion @@ -1,4 +1,4 @@ -15.2.0 +15.3.0 # The first line of this file contains the master version number for the kernel. # All other instances of the kernel version in xnu are derived from this file. diff --git a/iokit/IOKit/IOUserClient.h b/iokit/IOKit/IOUserClient.h index 6286b8535..06a9931db 100644 --- a/iokit/IOKit/IOUserClient.h +++ b/iokit/IOKit/IOUserClient.h @@ -207,7 +207,8 @@ private: #endif OSSet * mappings; UInt8 sharedInstance; - UInt8 __reservedA[3]; + UInt8 closed; + UInt8 __reservedA[2]; void * __reserved[7]; public: diff --git a/iokit/Kernel/IOBufferMemoryDescriptor.cpp b/iokit/Kernel/IOBufferMemoryDescriptor.cpp index 9f1902605..046274c59 100644 --- a/iokit/Kernel/IOBufferMemoryDescriptor.cpp +++ b/iokit/Kernel/IOBufferMemoryDescriptor.cpp @@ -554,6 +554,7 @@ vm_size_t IOBufferMemoryDescriptor::getCapacity() const void IOBufferMemoryDescriptor::setLength(vm_size_t length) { assert(length <= _capacity); + if (length > _capacity) return; _length = length; _ranges.v64->length = length; diff --git a/iokit/Kernel/IOMemoryDescriptor.cpp b/iokit/Kernel/IOMemoryDescriptor.cpp index 4bd9659e7..f61b0f9d6 100644 --- a/iokit/Kernel/IOMemoryDescriptor.cpp +++ b/iokit/Kernel/IOMemoryDescriptor.cpp @@ -1571,19 +1571,18 @@ IOGeneralMemoryDescriptor::initWithOptions(void * buffers, // Find starting address within the vector of ranges Ranges vec = _ranges; - UInt32 length = 0; - UInt32 pages = 0; - for (unsigned ind = 0; ind < count; ind++) { + mach_vm_size_t totalLength = 0; + unsigned int ind, pages = 0; + for (ind = 0; ind < count; ind++) { mach_vm_address_t addr; mach_vm_size_t len; // addr & len are returned by this function getAddrLenForInd(addr, len, type, vec, ind); + if ((addr + len + PAGE_MASK) < addr) break; /* overflow */ pages += (atop_64(addr + len + PAGE_MASK) - atop_64(addr)); - len += length; - assert(len >= length); // Check for 32 bit wrap around - length = len; - + totalLength += len; + if (totalLength < len) break; /* overflow */ if ((kIOMemoryTypePhysical == type) || (kIOMemoryTypePhysical64 == type)) { ppnum_t highPage = atop_64(addr + len - 1); @@ -1591,7 +1590,10 @@ IOGeneralMemoryDescriptor::initWithOptions(void * buffers, _highestPage = highPage; } } - _length = length; + if ((ind < count) + || (totalLength != ((IOByteCount) totalLength))) return (false); /* overflow */ + + _length = totalLength; _pages = pages; _rangesCount = count; @@ -1601,7 +1603,8 @@ IOGeneralMemoryDescriptor::initWithOptions(void * buffers, _wireCount++; // Physical MDs are, by definition, wired else { /* kIOMemoryTypeVirtual | kIOMemoryTypeVirtual64 | kIOMemoryTypeUIO */ ioGMDData *dataP; - unsigned dataSize = computeDataSize(_pages, /* upls */ count * 2); + mach_vm_size_t dataSize = computeDataSize(_pages, /* upls */ count * 2); + if (dataSize != ((unsigned) dataSize)) return false; /* overflow */ if (!initMemoryEntries(dataSize, mapper)) return false; dataP = getDataP(_memoryEntries); @@ -1758,7 +1761,8 @@ IOByteCount IOMemoryDescriptor::readBytes // Assert that this entire I/O is withing the available range assert(offset <= _length); assert(offset + length <= _length); - if (offset >= _length) { + if ((offset >= _length) + || ((offset + length) > _length)) { return 0; } @@ -1807,7 +1811,9 @@ IOByteCount IOMemoryDescriptor::writeBytes assert( !(kIOMemoryPreparedReadOnly & _flags) ); - if ( (kIOMemoryPreparedReadOnly & _flags) || offset >= _length) { + if ( (kIOMemoryPreparedReadOnly & _flags) + || (offset >= _length) + || ((offset + length) > _length)) { return 0; } diff --git a/iokit/Kernel/IOUserClient.cpp b/iokit/Kernel/IOUserClient.cpp index 8c628ddf1..06e4a612c 100644 --- a/iokit/Kernel/IOUserClient.cpp +++ b/iokit/Kernel/IOUserClient.cpp @@ -1299,7 +1299,14 @@ void IOUserClient::free() IOReturn IOUserClient::clientDied( void ) { - return( clientClose()); + IOReturn ret = kIOReturnNotReady; + + if (sharedInstance || OSCompareAndSwap8(0, 1, &closed)) + { + ret = clientClose(); + } + + return (ret); } IOReturn IOUserClient::clientClose( void ) @@ -1930,6 +1937,8 @@ kern_return_t is_io_service_get_matching_services_ool( if( KERN_SUCCESS == kr) { // must return success after vm_map_copyout() succeeds + // and mig will copy out objects on success + *existing = 0; *result = internal_io_service_get_matching_services(master_port, (const char *) data, matchingCnt, existing); vm_deallocate( kernel_map, data, matchingCnt ); @@ -2002,6 +2011,8 @@ kern_return_t is_io_service_get_matching_service_ool( if( KERN_SUCCESS == kr) { // must return success after vm_map_copyout() succeeds + // and mig will copy out objects on success + *service = 0; *result = internal_io_service_get_matching_service(master_port, (const char *) data, matchingCnt, service ); vm_deallocate( kernel_map, data, matchingCnt ); @@ -2188,6 +2199,8 @@ static kern_return_t internal_io_service_add_notification_ool( if( KERN_SUCCESS == kr) { // must return success after vm_map_copyout() succeeds + // and mig will copy out objects on success + *notification = 0; *result = internal_io_service_add_notification( master_port, notification_type, (char *) data, matchingCnt, wake_port, reference, referenceSize, client64, notification ); vm_deallocate( kernel_map, data, matchingCnt ); @@ -3257,6 +3270,7 @@ kern_return_t is_io_service_open_extended( break; } client->sharedInstance = (0 != client->getProperty(kIOUserClientSharedInstanceKey)); + client->closed = false; OSString * creatorName = IOCopyLogNameForPID(proc_selfpid()); if (creatorName) { @@ -3285,7 +3299,16 @@ kern_return_t is_io_service_close( CHECK( IOUserClient, connection, client ); IOStatisticsClientCall(); - client->clientClose(); + + if (client->sharedInstance || OSCompareAndSwap8(0, 1, &client->closed)) + { + client->clientClose(); + } + else + { + IOLog("ignored is_io_service_close(0x%qx,%s)\n", + client->getRegistryEntryID(), client->getName()); + } return( kIOReturnSuccess ); } diff --git a/libkern/libkern/Makefile b/libkern/libkern/Makefile index fb623933c..db475229b 100644 --- a/libkern/libkern/Makefile +++ b/libkern/libkern/Makefile @@ -75,11 +75,7 @@ EXPORT_MI_LIST = \ kxld_types.h \ stack_protector.h -INSTALL_KF_MI_LCL_LIST += \ - section_keywords.h -EXPORT_MI_LIST += \ - section_keywords.h EXPORT_MI_GEN_LIST = version.h -- 2.45.2