X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/3e170ce000f1506b7b5d2c5c7faec85ceabb573d..7e41aa883dd258f888d0470250eead40a53ef1f5:/iokit/Kernel/IOMemoryDescriptor.cpp?ds=inline diff --git a/iokit/Kernel/IOMemoryDescriptor.cpp b/iokit/Kernel/IOMemoryDescriptor.cpp index 4bd9659e7..947461eaf 100644 --- a/iokit/Kernel/IOMemoryDescriptor.cpp +++ b/iokit/Kernel/IOMemoryDescriptor.cpp @@ -672,8 +672,7 @@ IOMemoryDescriptorMapAlloc(vm_map_t map, void * _ref) (((ref->options & kIOMapAnywhere) ? VM_FLAGS_ANYWHERE : VM_FLAGS_FIXED) - | VM_MAKE_TAG(ref->tag) - | VM_FLAGS_IOKIT_ACCT), /* iokit accounting */ + | VM_MAKE_TAG(ref->tag)), IPC_PORT_NULL, (memory_object_offset_t) 0, false, /* copy */ @@ -1571,19 +1570,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 +1589,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,8 +1602,11 @@ IOGeneralMemoryDescriptor::initWithOptions(void * buffers, _wireCount++; // Physical MDs are, by definition, wired else { /* kIOMemoryTypeVirtual | kIOMemoryTypeVirtual64 | kIOMemoryTypeUIO */ ioGMDData *dataP; - unsigned dataSize = computeDataSize(_pages, /* upls */ count * 2); + unsigned dataSize; + + if (_pages > atop_64(max_mem)) return false; + dataSize = computeDataSize(_pages, /* upls */ count * 2); if (!initMemoryEntries(dataSize, mapper)) return false; dataP = getDataP(_memoryEntries); dataP->fPageCnt = _pages; @@ -1758,7 +1762,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 +1812,9 @@ IOByteCount IOMemoryDescriptor::writeBytes assert( !(kIOMemoryPreparedReadOnly & _flags) ); - if ( (kIOMemoryPreparedReadOnly & _flags) || offset >= _length) { + if ( (kIOMemoryPreparedReadOnly & _flags) + || (offset >= _length) + || ((offset + length) > _length)) { return 0; } @@ -2867,8 +2874,9 @@ IOReturn IOGeneralMemoryDescriptor::wireVirtual(IODirection forDirection) pageInfo = getPageList(dataP); upl_page_list_ptr_t baseInfo = &pageInfo[pageIndex]; - upl_size_t ioplSize = round_page(numBytes); - unsigned int numPageInfo = atop_32(ioplSize); + mach_vm_size_t _ioplSize = round_page(numBytes); + upl_size_t ioplSize = (_ioplSize <= MAX_UPL_SIZE_BYTES) ? _ioplSize : MAX_UPL_SIZE_BYTES; + unsigned int numPageInfo = atop_32(ioplSize); if ((theMap == kernel_map) && (kernelStart >= io_kernel_static_start) @@ -2882,7 +2890,7 @@ IOReturn IOGeneralMemoryDescriptor::wireVirtual(IODirection forDirection) &highPage); } else if (_memRef) { - memory_object_offset_t entryOffset; + memory_object_offset_t entryOffset; entryOffset = mdOffset; entryOffset = (entryOffset - iopl.fPageOffset - memRefEntry->offset); @@ -2911,10 +2919,11 @@ IOReturn IOGeneralMemoryDescriptor::wireVirtual(IODirection forDirection) &ioplFlags); } - assert(ioplSize); if (error != KERN_SUCCESS) goto abortExit; + assert(ioplSize); + if (iopl.fIOPL) highPage = upl_get_highest_page(iopl.fIOPL); if (highPage > highestPage)