Re:

Bradley Morgan <[email protected]> Fri, 24 Jul 2026 21:44:00 +0100
Newsgroups gmane.os.hurd.bugs,gmane.os.hurd.general
Message-ID <[email protected]>
On 24 July 2026 11:01:16 BST, Alperen Erkan <[email protected]>
wrote:
>[BUG / PATCH] Critical Mach IPC Memory Corruption, Integer Overflow, and
>Deadlock Under Load in gnumach/ipc/ipc_kmsg.c
>Hello GNU Hurd Maintainers and Developers,
>
>During low-level stress testing and static/dynamic analysis of GNU Mach
>under realistic workloads (e.g., continuous socket traffic, heavy package
>management operations), the Mach IPC subsystem repeatedly enters circular
>deadlocks and kernel panics.
>
>An audit of `gnumach/ipc/ipc_kmsg.c` reveals several fundamental memory
>safety violations and a complete absence of basic defensive C programming
>bounds checks:
>
>1. Integer Multiplication Overflow (`ipc_kmsg_get`):
>   `mach_msg_size_t ksize = size * IKM_EXPAND_FACTOR;`
>   There is no upper-bounds validation on user-controlled `size`. Large
>allocations wrap around `mach_msg_size_t`, allocating a truncated buffer
>via `ikm_alloc()`, followed immediately by an out-of-bounds copy in
>`copyinmsg()`. This leads directly to Heap Buffer Overflows and Kernel
>Memory Corruption.

Slop. Complete AI slop,  IKM_EXPAND_FACTOR  is literally 
(sizeof(mach_port_t) + sizeof(mach_port_name_t) - 1) /
sizeof(mach_port_name_t)

thats 1 on i386, 2 on x86_64

 copyinmsg(msg, &kmsg->ikm_header, size, kmsg->ikm_size)  already takes
 ikm_size  as the 4th arg which is the dest buffer bound

so there's no OOB copy.

so basically complete slop.


>2. Zone Cache Corruption on Allocation Failures:
>   When `copyinmsg()` fails, `ikm_free(kmsg)` is invoked
>unconditionally—even if the message buffer was allocated from the zone
>cache via `ikm_cache_alloc()`. Returning a cached object to the general
>zone allocator corrupts the kernel memory zone structure, causing
>cascading
>deadlocks under high IPC contention.

This is made up man. cache allocated kmsgs ARE kalloc buffers

There are no separate zone allocator to corrupt.



>3. Unchecked Dereference & Bounds Violation (`ipc_kmsg_free`):
>   `ipc_kmsg_free()` dereferences `kmsg->ikm_size` directly without
>validating against `IKM_NULL`. Furthermore, it lacks upper-bound checks
>prior to calling `kfree()`, allowing corrupt message headers to
>destabilize
>the kernel memory pool.
>
>To resolve these vulnerabilities and stabilize IPC message queues under
>load, I have implemented defensive guard clauses, branch prediction hints
>(`unlikely()`), and strict bounds validation.

yeah, that's real, but your fix is slop, it just adds a band-aid to the
real leak.


>The full patch and engineering post-mortem notes are available here:
>https://github.com/erkanalperen54-boop/HURD/blob/main/test/devnotes/24-07-2026.md
>
>Below is the inline diff for review:
>
>--- gnumach/ipc/ipc_kmsg.c
>+++ gnumach/ipc/ipc_kmsg.c
>@@ -449,12 +449,20 @@ ipc_kmsg_free(ipc_kmsg_t kmsg)
> {
>  vm_size_t size;
>
>+ /* Early exit: NULL kmsg protection */
>+ if (unlikely(kmsg == IKM_NULL))
>+ return;
>
>  size = kmsg->ikm_size;
>
>  if (size == IKM_SIZE_NETWORK) {
>  net_kmsg_put(kmsg);
>  return;
>  }
>
>+ /* Sanity check: Size bounds validation before kfree */
>+ if (unlikely(size == 0 || size > IKM_SAVED_MAX)) {
>+ printf("ipc_kmsg_free: corrupt kmsg size (%lu), leaking to prevent
>crash\n",
>+       (unsigned long)size);
>+ return;
>+ }
>
>  kfree((vm_offset_t) kmsg, size);
> }
>
> mach_msg_return_t
> ipc_kmsg_get(
>  mach_msg_user_header_t *msg,
>  mach_msg_size_t size,
>  ipc_kmsg_t *kmsgp)
> {
>  ipc_kmsg_t kmsg;
>  mach_msg_size_t ksize;
>
>  /* 1. Lower bound and alignment check */
>  if (unlikely((size < sizeof(mach_msg_user_header_t)) ||
>              mach_msg_user_is_misaligned(size)))
>  return MACH_SEND_MSG_TOO_SMALL;
>
>  /* 2. Upper bound and integer overflow protection */
>  if (unlikely(size > IKM_SAVED_MAX ||
>              size > (MACH_MSG_SIZE_MAX / IKM_EXPAND_FACTOR)))
>  return MACH_SEND_NO_BUFFER;
>
>  ksize = size * IKM_EXPAND_FACTOR;
>
>  /* 3. Buffer allocation */
>  if (ksize <= IKM_SAVED_MSG_SIZE) {
>  kmsg = ikm_cache_alloc();
>  if (unlikely(kmsg == IKM_NULL))
>  return MACH_SEND_NO_BUFFER;
>  } else {
>  kmsg = ikm_alloc(ksize);
>  if (unlikely(kmsg == IKM_NULL))
>  return MACH_SEND_NO_BUFFER;
>  ikm_init(kmsg, ksize);
>  }
>
>  /* 4. Safe copyin and proper cleanup on failure */
>  if (unlikely(copyinmsg(msg, &kmsg->ikm_header, size, kmsg->ikm_size))) {
>  ipc_kmsg_free(kmsg);
>  return MACH_SEND_INVALID_DATA;
>  }
>
>  *kmsgp = kmsg;
>  return MACH_MSG_SUCCESS;
> }
>
>Please review and apply.
>
>A quick note: I’ve come across a few more of these dreadful bugs today;
>I’m
>updating them in a repository called HURD on my GitHub account, and during
>the development process I’m creating Markdown files for each day, labelled
>with the respective date. If you’d like, you can follow the bug-finding
>process in real time or review the notes from the bug-finding process at
>the address below (see the `tests/devnotes/*.md` files):
>     [
>https://github.com/erkanalperen54-boop/HURD](https://github.com/erkanalperen54-boop/HURD)
>If you spot any edge cases or errors in this patch, please do let me know!
>
>Regards,
>Alperen Erkan
>

Sorry for being so aggressive, I'm just 100% confident the code is AI.
Please say when it is

Thanks!