From 244fa852fe2775cf52a3901966cd6d8700df8227 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Wed, 7 Jan 2026 22:02:00 +0800 Subject: [PATCH 1/3] dwm: Fix heap buffer overflow in getatomprop When getatomprop() is called, it invokes XGetWindowProperty() to retrieve an Atom. If the property exists but has zero elements (length 0), Xlib returns Success and sets p to a valid, non-NULL memory address containing a single null byte. However, dl (that is, the number of items) is 0. dwm blindly casts p to Atom* and dereferences it. While Xlib guarantees that p is safe to read as a string (that is, it is null-terminated), it does _not_ guarantee it is safe to read as an Atom (an unsigned long). The Atom type is a typedef for unsigned long. Reading an Atom (which thus will either likely be 4 or 8 bytes) from a 1-byte allocated buffer results in a heap buffer overflow. Since property content is user controlled, this allows any client to trigger an out of bounds read simply by setting a property with format 32 and length 0. An example client which reliably crashes dwm under ASAN: #include #include #include #include #include int main(void) { Display *d; Window root, w; Atom net_wm_state; d = XOpenDisplay(NULL); if (!d) return 1; root = DefaultRootWindow(d); w = XCreateSimpleWindow(d, root, 10, 10, 200, 200, 1, 0, 0); net_wm_state = XInternAtom(d, "_NET_WM_STATE", False); if (net_wm_state == None) return 1; XChangeProperty(d, w, net_wm_state, XA_ATOM, 32, PropModeReplace, NULL, 0); XMapWindow(d, w); XSync(d, False); sleep(1); XCloseDisplay(d); return 0; } In order to avoid this, check that the number of items returned is greater than zero before dereferencing the pointer. --- dwm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 4f345ee..8f4fa75 100644 --- a/dwm.c +++ b/dwm.c @@ -870,7 +870,8 @@ getatomprop(Client *c, Atom prop) if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, &da, &di, &dl, &dl, &p) == Success && p) { - atom = *(Atom *)p; + if (dl > 0) + atom = *(Atom *)p; XFree(p); } return atom; From 85fe518c1af5eb43f222f4d8579e4814ed769f3b Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sat, 10 Jan 2026 11:31:44 +0100 Subject: [PATCH 2/3] bump version to 6.7 Put the maintainer at the top and bump years (time flies). --- LICENSE | 2 +- config.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index 995172f..596e6cd 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,6 @@ MIT/X Consortium License +© 2010-2026 Hiltjo Posthuma © 2006-2019 Anselm R Garbe © 2006-2009 Jukka Salmi © 2006-2007 Sander van Dijk @@ -11,7 +12,6 @@ MIT/X Consortium License © 2008 Martin Hurton © 2008 Neale Pickett © 2009 Mate Nagy -© 2010-2016 Hiltjo Posthuma © 2010-2012 Connor Lane Smith © 2011 Christoph Lohmann <20h@r-36.net> © 2015-2016 Quentin Rameau diff --git a/config.mk b/config.mk index b469a2b..6e875f1 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.6 +VERSION = 6.7 # Customize below to fit your system From a9aa0d8ffbb548b0b1f9f755557aef2482c0f820 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Wed, 14 Jan 2026 14:58:05 +0800 Subject: [PATCH 3/3] dwm: Fix getatomprop regression from heap overflow fix Commit 244fa852fe27 ("dwm: Fix heap buffer overflow in getatomprop") introduced a check for dl > 0 before dereferencing the property pointer. However, I missed that the variable dl is passed to XGetWindowProperty for both nitems_return and bytes_after_return parameters: XGetWindowProperty(..., &dl, &dl, &p) The final value in dl is bytes_after_return, not nitems_return. For a successfully read property, bytes_after is typically 0 (indicating all data was retrieved), so the check `dl > 0` is always false and dwm never reads any atom properties. So this is safe, but not very helpful :-) dl is probably just a dummy variable anyway, so fix by using a separate variable for nitems, and check nitems > 0 as originally intended. --- dwm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index 8f4fa75..53b393e 100644 --- a/dwm.c +++ b/dwm.c @@ -864,13 +864,13 @@ Atom getatomprop(Client *c, Atom prop) { int di; - unsigned long dl; + unsigned long nitems, dl; unsigned char *p = NULL; Atom da, atom = None; if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, - &da, &di, &dl, &dl, &p) == Success && p) { - if (dl > 0) + &da, &di, &nitems, &dl, &p) == Success && p) { + if (nitems > 0) atom = *(Atom *)p; XFree(p); }