Apple iOS
Apple watchOS
Apple tvOS
iOS 10.3.1 and earlier
watchOS 3.2 and earlier
tvOS 10.2 and earlier
Update to latest versions.
An issue exists in iokit\Kernel\IONVRAM.cpp
:
At (1)
, the function allocates a buffer with the size of kIODTNVRAMImageSize
(0x2000). It then proceeds to initProxyData()
:
bool IODTNVRAM::init(IORegistryEntry *old, const IORegistryPlane *plane)
{
[...]
_nvramImage = IONew(UInt8, kIODTNVRAMImageSize); // (1)
if (_nvramImage == 0) return false;
[...]
initProxyData();
[...]
}
At (2)
, The functions copies over the _nvramImage
variable with data obtained from /chosen/nvram-proxy-data
device-tree entry, without properly checking the length of the data, which should be no bigger than kIODTNVRAMImageSize
.
void IODTNVRAM::initProxyData(void)
{
IORegistryEntry *entry;
const char *key = "nvram-proxy-data";
OSObject *prop;
OSData *data;
const void *bytes;
entry = IORegistryEntry::fromPath("/chosen", gIODTPlane);
if (entry != 0) {
prop = entry->getProperty(key);
if (prop != 0) {
data = OSDynamicCast(OSData, prop);
if (data != 0) {
bytes = data->getBytesNoCopy();
if (bytes != 0) {
bcopy(bytes, _nvramImage, data->getLength()); // (2) - no size check.
initNVRAMImage();
_isProxied = true;
}
}
}
entry->removeProperty(key);
entry->release();
}
}
An attacker with access to the device-tree entry nvram-proxy-data
, which is available in the firmware updates, could potentially overflow the buffer.
Apple has addressed the issue through additional kernel hardening.