diff --git a/CHANGELOG.md b/CHANGELOG.md index 79134eb9b..4e043ac92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - Native/Linux i386: write valid thread stack descriptors to minidumps when stack addresses use the upper half of the 32-bit address space. ([#2054](https://github.com/getsentry/sentry-native/pull/2054)) - Linux/ARM32: fix builds on 32-bit ARM systems, including 32-bit Raspberry Pi OS installations running a 64-bit kernel. ([#2063](https://github.com/getsentry/sentry-native/pull/2063)) - Guard size arithmetic when parsing envelopes and Linux OS release data, copying slices, and allocating memory during crash handling. ([#2059](https://github.com/getsentry/sentry-native/pull/2059)) +- macOS: prevent out-of-bounds reads while parsing Mach-O load commands. ([#2065](https://github.com/getsentry/sentry-native/pull/2065)) - Prevent out-of-bounds reads when parsing JSON numbers from length-delimited buffers. ([#2067](https://github.com/getsentry/sentry-native/pull/2067)) **Thank you**: diff --git a/src/modulefinder/sentry_modulefinder_apple.c b/src/modulefinder/sentry_modulefinder_apple.c index b7c8d7266..cde5b437e 100644 --- a/src/modulefinder/sentry_modulefinder_apple.c +++ b/src/modulefinder/sentry_modulefinder_apple.c @@ -50,15 +50,25 @@ add_image(const struct mach_header *mh, intptr_t UNUSED(vmaddr_slide)) sentry_value_set_by_key( module, "image_addr", sentry__value_new_addr((uint64_t)info.dli_fbase)); - const struct load_command *cmd = (const struct load_command *)(header + 1); + const char *commands = (const char *)(header + 1); + size_t pos = 0; bool has_size = false; bool has_uuid = false; - for (size_t i = 0; cmd && (i < header->ncmds) && (!has_uuid || !has_size); - ++i, - cmd - = (const struct load_command *)((const char *)cmd + cmd->cmdsize)) { - if (cmd->cmd == CMD_SEGMENT) { + for (size_t i = 0; i < header->ncmds && (!has_uuid || !has_size); i++) { + if (sizeof(struct load_command) > header->sizeofcmds - pos) { + break; + } + + const struct load_command *cmd + = (const struct load_command *)(commands + pos); + if (cmd->cmdsize < sizeof(struct load_command) + || cmd->cmdsize > header->sizeofcmds - pos) { + break; + } + + if (cmd->cmd == CMD_SEGMENT + && cmd->cmdsize >= sizeof(mach_segment_command_type)) { const mach_segment_command_type *seg = (const mach_segment_command_type *)cmd; @@ -67,7 +77,8 @@ add_image(const struct mach_header *mh, intptr_t UNUSED(vmaddr_slide)) sentry_value_new_int32((uint32_t)seg->vmsize)); has_size = true; } - } else if (cmd->cmd == LC_UUID) { + } else if (cmd->cmd == LC_UUID + && cmd->cmdsize >= sizeof(struct uuid_command)) { const struct uuid_command *ucmd = (const struct uuid_command *)cmd; sentry_uuid_t uuid = sentry_uuid_from_bytes((const char *)ucmd->uuid); @@ -75,6 +86,8 @@ add_image(const struct mach_header *mh, intptr_t UNUSED(vmaddr_slide)) module, "debug_id", sentry__value_new_uuid(&uuid)); has_uuid = true; } + + pos += cmd->cmdsize; } sentry__mutex_lock(&g_mutex);