(unknown)
Alperen Erkan <[email protected]> Fri, 24 Jul 2026 13:01:16 +0300
| Newsgroups | gmane.os.hurd.bugs,gmane.os.hurd.general |
|---|---|
| Message-ID | <CAB6ChQ7G_WFMsMnfUEqxyX89FcmEj4ezu5EhHfdtq=aY31hP4A@mail.gmail.com> |
--000000000000c548d70657587450
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
[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 =3D 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.
2. Zone Cache Corruption on Allocation Failures:
When `copyinmsg()` fails, `ikm_free(kmsg)` is invoked
unconditionally=E2=80=94even if the message buffer was allocated from the z=
one
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.
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.
The full patch and engineering post-mortem notes are available here:
https://github.com/erkanalperen54-boop/HURD/blob/main/test/devnotes/24-07-2=
026.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 =3D=3D IKM_NULL))
+ return;
size =3D kmsg->ikm_size;
if (size =3D=3D IKM_SIZE_NETWORK) {
net_kmsg_put(kmsg);
return;
}
+ /* Sanity check: Size bounds validation before kfree */
+ if (unlikely(size =3D=3D 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 =3D size * IKM_EXPAND_FACTOR;
/* 3. Buffer allocation */
if (ksize <=3D IKM_SAVED_MSG_SIZE) {
kmsg =3D ikm_cache_alloc();
if (unlikely(kmsg =3D=3D IKM_NULL))
return MACH_SEND_NO_BUFFER;
} else {
kmsg =3D ikm_alloc(ksize);
if (unlikely(kmsg =3D=3D 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 =3D kmsg;
return MACH_MSG_SUCCESS;
}
Please review and apply.
A quick note: I=E2=80=99ve come across a few more of these dreadful bugs to=
day; I=E2=80=99m
updating them in a repository called HURD on my GitHub account, and during
the development process I=E2=80=99m creating Markdown files for each day, l=
abelled
with the respective date. If you=E2=80=99d like, you can follow the bug-fin=
ding
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/erkanalpere=
n54-boop/HURD)
If you spot any edge cases or errors in this patch, please do let me know!
Regards,
Alperen Erkan
--000000000000c548d70657587450
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><p>[BUG / PATCH] Critical Mach IPC Memory Corruption, Inte=
ger Overflow, and Deadlock Under Load in <code>gnumach/ipc/ipc_kmsg.c</code=
></p><span class=3D"gmail-no-md"><span class=3D"gmail-ng-tns-c3586008462-36=
5 enable-luminous-code-block gmail-ng-star-inserted"><div class=3D"gmail-co=
de-block gmail-ng-tns-c3586008462-365 gmail-ng-animate-disabled gmail-ng-tr=
igger gmail-ng-trigger-codeBlockRevealAnimation" style=3D"display:block"><d=
iv class=3D"gmail-formatted-code-block-internal-container gmail-ng-tns-c358=
6008462-365"><div class=3D"gmail-animated-opacity gmail-ng-tns-c3586008462-=
365"><div class=3D"gmail-code-block-decoration gmail-header-formatted gmail=
-gds-emphasized-body-m gmail-ng-tns-c3586008462-365 gmail-ng-star-inserted"=
><span class=3D"gmail-ng-tns-c3586008462-365">Hello GNU Hurd Maintainers an=
d Developers,<br><br>During low-level stress testing and static/dynamic ana=
lysis of GNU Mach under realistic workloads (e.g., continuous socket traffi=
c, heavy package management operations), the Mach IPC subsystem repeatedly =
enters circular deadlocks and kernel panics.<br><br>An audit of `gnumach/ip=
c/ipc_kmsg.c` reveals several fundamental memory safety violations and a co=
mplete absence of basic defensive C programming bounds checks:<br><br>1. In=
teger Multiplication Overflow (`ipc_kmsg_get`):<br>=C2=A0 =C2=A0`mach_msg_s=
ize_t ksize =3D size * IKM_EXPAND_FACTOR;`<br>=C2=A0 =C2=A0There is no uppe=
r-bounds validation on user-controlled `size`. Large allocations wrap aroun=
d `mach_msg_size_t`, allocating a truncated buffer via `ikm_alloc()`, follo=
wed immediately by an out-of-bounds copy in `copyinmsg()`. This leads direc=
tly to Heap Buffer Overflows and Kernel Memory Corruption.<br><br>2. Zone C=
ache Corruption on Allocation Failures:<br>=C2=A0 =C2=A0When `copyinmsg()` =
fails, `ikm_free(kmsg)` is invoked unconditionally=E2=80=94even if the mess=
age buffer was allocated from the zone cache via `ikm_cache_alloc()`. Retur=
ning a cached object to the general zone allocator corrupts the kernel memo=
ry zone structure, causing cascading deadlocks under high IPC contention.<b=
r><br>3. Unchecked Dereference & Bounds Violation (`ipc_kmsg_free`):<br=
>=C2=A0 =C2=A0`ipc_kmsg_free()` dereferences `kmsg->ikm_size` directly w=
ithout validating against `IKM_NULL`. Furthermore, it lacks upper-bound che=
cks prior to calling `kfree()`, allowing corrupt message headers to destabi=
lize the kernel memory pool.<br><br>To resolve these vulnerabilities and st=
abilize IPC message queues under load, I have implemented defensive guard c=
lauses, branch prediction hints (`unlikely()`), and strict bounds validatio=
n.<br><br>The full patch and engineering post-mortem notes are available he=
re:<br><a href=3D"https://github.com/erkanalperen54-boop/HURD/blob/main/tes=
t/devnotes/24-07-2026.md">https://github.com/erkanalperen54-boop/HURD/blob/=
main/test/devnotes/24-07-2026.md</a><br><br>Below is the inline diff for re=
view:<br><br>--- gnumach/ipc/ipc_kmsg.c<br>+++ gnumach/ipc/ipc_kmsg.c<br>@@=
-449,12 +449,20 @@ ipc_kmsg_free(ipc_kmsg_t kmsg)<br>=C2=A0{<br>=C2=A0 vm_=
size_t size;<br><br>+ /* Early exit: NULL kmsg protection */<br>+ if (unlik=
ely(kmsg =3D=3D IKM_NULL))<br>+ return;<br><br>=C2=A0 size =3D kmsg->ik=
m_size;<br><br>=C2=A0 if (size =3D=3D IKM_SIZE_NETWORK) {<br>=C2=A0 net_km=
sg_put(kmsg);<br>=C2=A0 return;<br>=C2=A0 }<br><br>+ /* Sanity check: Size=
bounds validation before kfree */<br>+ if (unlikely(size =3D=3D 0 || size =
> IKM_SAVED_MAX)) {<br>+ printf("ipc_kmsg_free: corrupt kmsg size =
(%lu), leaking to prevent crash\n",<br>+ =C2=A0 =C2=A0 =C2=A0 (unsig=
ned long)size);<br>+ return;<br>+ }<br><br>=C2=A0 kfree((vm_offset_t) kmsg=
, size);<br>=C2=A0}<br><br>=C2=A0mach_msg_return_t<br>=C2=A0ipc_kmsg_get(<b=
r>=C2=A0 mach_msg_user_header_t *msg,<br>=C2=A0 mach_msg_size_t size,<br>=
=C2=A0 ipc_kmsg_t *kmsgp)<br>=C2=A0{<br>=C2=A0 ipc_kmsg_t kmsg;<br>=C2=
=A0 mach_msg_size_t ksize;<br><br>=C2=A0 /* 1. Lower bound and alignment ch=
eck */<br>=C2=A0 if (unlikely((size < sizeof(mach_msg_user_header_t)) ||=
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 mach_msg_user_is_misa=
ligned(size)))<br>=C2=A0 return MACH_SEND_MSG_TOO_SMALL;<br><br>=C2=A0 /* =
2. Upper bound and integer overflow protection */<br>=C2=A0 if (unlikely(si=
ze > IKM_SAVED_MAX ||<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 size > (MACH_MSG_SIZE_MAX / IKM_EXPAND_FACTOR)))<br>=C2=A0 return M=
ACH_SEND_NO_BUFFER;<br><br>=C2=A0 ksize =3D size * IKM_EXPAND_FACTOR;<br><b=
r>=C2=A0 /* 3. Buffer allocation */<br>=C2=A0 if (ksize <=3D IKM_SAVED_M=
SG_SIZE) {<br>=C2=A0 kmsg =3D ikm_cache_alloc();<br>=C2=A0 if (unlikely(k=
msg =3D=3D IKM_NULL))<br>=C2=A0 return MACH_SEND_NO_BUFFER;<br>=C2=A0 } e=
lse {<br>=C2=A0 kmsg =3D ikm_alloc(ksize);<br>=C2=A0 if (unlikely(kmsg =
=3D=3D IKM_NULL))<br>=C2=A0 return MACH_SEND_NO_BUFFER;<br>=C2=A0 ikm_in=
it(kmsg, ksize);<br>=C2=A0 }<br><br>=C2=A0 /* 4. Safe copyin and proper cle=
anup on failure */<br>=C2=A0 if (unlikely(copyinmsg(msg, &kmsg->ikm_=
header, size, kmsg->ikm_size))) {<br>=C2=A0 ipc_kmsg_free(kmsg);<br>=C2=
=A0 return MACH_SEND_INVALID_DATA;<br>=C2=A0 }<br><br>=C2=A0 *kmsgp =3D km=
sg;<br>=C2=A0 return MACH_MSG_SUCCESS;<br>=C2=A0}<br><br>Please review and =
apply.</span></div><div class=3D"gmail-code-block-decoration gmail-header-f=
ormatted gmail-gds-emphasized-body-m gmail-ng-tns-c3586008462-365 gmail-ng-=
star-inserted"><p>A quick note: I=E2=80=99ve come across a few more of thes=
e dreadful bugs today; I=E2=80=99m updating them in a repository called HUR=
D on my GitHub account, and during the development process I=E2=80=99m crea=
ting Markdown files for each day, labelled with the respective date. If you=
=E2=80=99d like, you can follow the bug-finding process in real time or rev=
iew the notes from the bug-finding process at the address below (see the `t=
ests/devnotes/*.md` files):<br>=C2=A0 =C2=A0 =C2=A0[<a href=3D"https://gith=
ub.com/erkanalperen54-boop/HURD](https://github.com/erkanalperen54-boop/HUR=
D)">https://github.com/erkanalperen54-boop/HURD](https://github.com/erkanal=
peren54-boop/HURD)</a></p>If you spot any edge cases or errors in this patc=
h, please do let me know!</div><div class=3D"gmail-code-block-decoration gm=
ail-header-formatted gmail-gds-emphasized-body-m gmail-ng-tns-c3586008462-3=
65 gmail-ng-star-inserted"><br><span class=3D"gmail-ng-tns-c3586008462-365"=
>Regards,<br>Alperen Erkan</span></div></div></div></div></span></span><br>=
</div>
--000000000000c548d70657587450--