Compare commits

..

8 Commits

Author SHA1 Message Date
3a30a7329d Add my configs/customizations, point to upstream repo in README.md 2026-02-11 16:35:55 -06:00
redacted
f31f24c7ae [APPLY PATCH] added noborder patch 2026-01-14 15:58:17 -06:00
Jack Bird
76e4761e00 [APPLY PATCH] xresources updated for 138b405 2026-01-14 15:58:06 -06:00
thjbbvlt
477d33baa0 [APPLY PATCH] stacker updated for version 6.6 2026-01-14 15:57:54 -06:00
Tom Schwindl
574b69eb37 [APPLY PATCH] 6.3 swallow patch 2026-01-14 15:57:38 -06:00
Niki Yoshiuchi
8888121330 [APPLY PATCH] Adding the fibonacci layout patch 2026-01-14 15:57:03 -06:00
Hiltjo Posthuma
85fe518c1a bump version to 6.7
Put the maintainer at the top and bump years (time flies).
2026-01-10 11:31:44 +01:00
Chris Down
244fa852fe 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 <X11/Xlib.h>
    #include <X11/Xatom.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    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.
2026-01-10 11:27:23 +01:00
8 changed files with 184 additions and 17 deletions

View File

@@ -1,5 +1,6 @@
MIT/X Consortium License
© 2010-2026 Hiltjo Posthuma <hiltjo@codemadness.org>
© 2006-2019 Anselm R Garbe <anselm@garbe.ca>
© 2006-2009 Jukka Salmi <jukka at salmi dot ch>
© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
@@ -11,7 +12,6 @@ MIT/X Consortium License
© 2008 Martin Hurton <martin dot hurton at gmail dot com>
© 2008 Neale Pickett <neale dot woozle dot org>
© 2009 Mate Nagy <mnagy at port70 dot net>
© 2010-2016 Hiltjo Posthuma <hiltjo@codemadness.org>
© 2010-2012 Connor Lane Smith <cls@lubutu.com>
© 2011 Christoph Lohmann <20h@r-36.net>
© 2015-2016 Quentin Rameau <quinq@fifth.space>

View File

@@ -13,9 +13,6 @@ all: dwm
${OBJ}: config.h config.mk
config.h:
cp config.def.h $@
dwm: ${OBJ}
${CC} -o $@ ${OBJ} ${LDFLAGS}
@@ -24,8 +21,8 @@ clean:
dist: clean
mkdir -p dwm-${VERSION}
cp -R LICENSE Makefile README config.def.h config.mk\
dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION}
cp -R LICENSE Makefile README config.mk\
dwm.1 drw.h util.h ${SRC} transient.c dwm-${VERSION}
tar -cf dwm-${VERSION}.tar dwm-${VERSION}
gzip dwm-${VERSION}.tar
rm -rf dwm-${VERSION}

View File

@@ -2,13 +2,6 @@
This is my fork of suckless's dwm, for my customizations/configurations.
**Upstream:** `https://git.suckless.org/dwm/` or `git://git.suckless.org/dwm`
## TODO
- use patches i added:
- fibonacci (for spiral layout)
- stacker (for moving windows up and down stack)
- swallow (the replace-windows-in-place feature)
- xresources (maybe? for my theme-changing logic)
**Upstream:** [https://git.suckless.org/dwm/](https://git.suckless.org/dwm/)
or [git://git.suckless.org/dwm](git://git.suckless.org/dwm)

View File

@@ -1,5 +1,11 @@
/* See LICENSE file for copyright and license details. */
/* NOTE: config.h replaces this file, but I'm keeping this one to help distinguish
* between others' patches (published via suckless.org) and my own additions.
* - to see others' patches, diff config.def.h against upstream's config.def.h
* - to see my additional changes, diff config.h against config.def.h
*/
/* appearance */
static unsigned int borderpx = 1; /* border pixel of windows */
static unsigned int snap = 32; /* snap pixel */

163
config.h Normal file
View File

@@ -0,0 +1,163 @@
/* Copied from config.dev.h file. */
/* See LICENSE file for copyright and license details. */
#define BROWSER_CMD "qutebrowser"
// define BROWSER_CMD "brave"
#define SYSTEM_MONITOR "htop"
// define TERMINAL_CLASS "St"
// define TERMINAL_CMD "st"
#define TERMINAL_CLASS "Kitty"
#define TERMINAL_CMD "kitty"
/* appearance */
static unsigned int borderpx = 1; /* border pixel of windows */
static unsigned int snap = 32; /* snap pixel */
static int showbar = 1; /* 0 means no bar */
static int topbar = 1; /* 0 means bottom bar */
static char font[] = "monospace:size=10";
static char dmenufont[] = "monospace:size=10";
static const char *fonts[] = { font };
static char normbgcolor[] = "#222222";
static char normbordercolor[] = "#444444";
static char normfgcolor[] = "#bbbbbb";
static char selfgcolor[] = "#eeeeee";
static char selbordercolor[] = "#005577";
static char selbgcolor[] = "#005577";
static char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor },
[SchemeSel] = { selfgcolor, selbgcolor, selbordercolor },
};
/* window replacement */
static const int swallowfloating = 0;
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask isfloating isterminal noswallow monitor */
{ TERMINAL_CLASS, NULL, NULL, 0, 0, 1, 0, -1 },
{ "Gimp", NULL, NULL, 0, 0, 0, 0, -1 },
{ NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */
};
/* layout(s) */
static float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static int nmaster = 1; /* number of clients in master area */
static int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
static const int refreshrate = 120; /* refresh rate (per second) for client move/resize */
#include "fibonacci.c"
static const Layout layouts[] = {
/* symbol arrange function, (first entry is default) */
{ "[M]", monocle },
{ "[@]", spiral },
{ "[]=", tile },
{ "><>", NULL }, /* floating */
};
/* key definitions */
#define MODKEY Mod4Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
#define STACKKEYS(MOD,ACTION) \
{ MOD, XK_j, ACTION##stack, {.i = INC(+1) } }, \
{ MOD, XK_k, ACTION##stack, {.i = INC(-1) } },
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
/* commands */
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL };
static const char *termcmd[] = { TERMINAL_CMD, NULL };
/*
* Xresources preferences to load at startup
*/
ResourcePref resources[] = {
{ "font", STRING, &font },
{ "dmenufont", STRING, &dmenufont },
{ "normbgcolor", STRING, &normbgcolor },
{ "normbordercolor", STRING, &normbordercolor },
{ "normfgcolor", STRING, &normfgcolor },
{ "selbgcolor", STRING, &selbgcolor },
{ "selbordercolor", STRING, &selbordercolor },
{ "selfgcolor", STRING, &selfgcolor },
{ "borderpx", INTEGER, &borderpx },
{ "snap", INTEGER, &snap },
{ "showbar", INTEGER, &showbar },
{ "topbar", INTEGER, &topbar },
{ "nmaster", INTEGER, &nmaster },
{ "resizehints", INTEGER, &resizehints },
{ "mfact", FLOAT, &mfact },
};
static const Key keys[] = {
/* modifier key function argument */
{ MODKEY|ShiftMask, XK_f, togglebar, {0} },
STACKKEYS(MODKEY, focus)
STACKKEYS(MODKEY|ShiftMask, push)
/* { MODKEY, XK_h, zxcv, {.f = -0.05} }, */
/* { MODKEY, XK_l, zxcv, {.f = +0.05} }, */
{ MODKEY|ShiftMask, XK_h, setmfact, {.f = -0.05} }, // zxcv
{ MODKEY|ShiftMask, XK_l, setmfact, {.f = +0.05} }, // zxcv
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
{ MODKEY|ShiftMask, XK_Return, zoom, {0} }, /* swap current and master clients */
{ MODKEY, XK_comma, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_period, setlayout, {.v = &layouts[1]} },
{ MODKEY|ShiftMask, XK_period, setlayout, {.v = &layouts[2]} },
{ MODKEY, XK_slash, togglefloating, {0} }, /* float the curret window */
{ MODKEY|ShiftMask, XK_slash, setlayout, {.v = &layouts[3]} }, /* TODO: does this do anything? is it needed? */
{ MODKEY|ShiftMask, XK_m, focusmon, {.i = -1 } },
{ MODKEY, XK_m, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_t, tagmon, {.i = -1 } },
{ MODKEY, XK_t, tagmon, {.i = +1 } },
{ MODKEY, XK_grave, view, {.ui = ~0 } }, /* ` -> view all tags */
{ MODKEY|ShiftMask, XK_grave, tag, {.ui = ~0 } }, /* shift + ` -> apply all tags */
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
TAGKEYS( XK_4, 3)
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
TAGKEYS( XK_0, 9)
{ MODKEY, XK_q, killclient, {0} },
{ MODKEY|ShiftMask, XK_q, quit, {0} },
{ MODKEY, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_space, spawn, {.v = dmenucmd } },
{ MODKEY, XK_s, spawn, SHCMD(TERMINAL_CMD " -e " SYSTEM_MONITOR) },
{ MODKEY|ShiftMask, XK_b, spawn, {.v = (const char*[]){ BROWSER_CMD, NULL } } },
{ MODKEY, XK_b, spawn, SHCMD(TERMINAL_CMD " -e bookmark-find") },
};
/* button definitions */
/* click options: ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin */
static const Button buttons[] = {
/* click event mask button function argument */
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[0]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
};

View File

@@ -1,5 +1,5 @@
# dwm version
VERSION = 6.6
VERSION = 6.7
# Customize below to fit your system

10
dwm.c
View File

@@ -953,7 +953,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;
@@ -1401,6 +1402,13 @@ resizeclient(Client *c, int x, int y, int w, int h)
c->oldw = c->w; c->w = wc.width = w;
c->oldh = c->h; c->h = wc.height = h;
wc.border_width = c->bw;
if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next))
|| &monocle == c->mon->lt[c->mon->sellt]->arrange)
&& !c->isfullscreen && !c->isfloating) {
c->w = wc.width += c->bw * 2;
c->h = wc.height += c->bw * 2;
wc.border_width = 0;
}
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
configure(c);
XSync(dpy, False);

BIN
dwm.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 373 B