RE: [hackers] [dwm][PATCH] move config data to read-only sections

From: <Joachim.Henke_AT_t-systems.com>
Date: Wed, 6 Sep 2017 19:04:47 +0000

From: Anselm R Garbe [garbeam_AT_gmail.com]
Sent: Wednesday, September 6, 2017 7:38 PM
To: hackers mail list
Subject: Re: [hackers] [dwm][PATCH] move config data to read-only sections

On 6 September 2017 at 19:03, <Joachim.Henke_AT_t-systems.com> wrote:
> From: Hiltjo Posthuma [hiltjo_AT_codemadness.org]
> Sent: Wednesday, September 6, 2017 5:32 PM
> To: hackers mail list
> Subject: Re: [hackers] [dwm][PATCH] move config data to read-only sections
>
> On Wed, Sep 06, 2017 at 05:07:06PM +0200, Anselm R Garbe wrote:
>> Hi Joachim,
>>
>> On 6 September 2017 at 17:02, <Joachim.Henke_AT_t-systems.com> wrote:
>> > commit 6a5056d4c919bb5ae0222b2fde0ed787d50092cf
>> > Author: Joachim Henke <joachim.henke_AT_t-systems.com>
>> > AuthorDate: Wed, 6 Sep 2017 16:26:42 +0200
>> >
>> > The configuration data is just used read-only. So making it immutable
>> > might improve security. Testing on x86_64 showed that the .data section
>> > shrunk considerably: by ~2500 bytes.
>> >
>> > diff --git a/config.def.h b/config.def.h
>> > index a9ac303..a43a03c 100644
>> > --- a/config.def.h
>> > +++ b/config.def.h
>> > _AT_@ -5,14 +5,14 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
>> > static const unsigned int snap = 32; /* snap pixel */
>> > static const int showbar = 1; /* 0 means no bar */
>> > static const int topbar = 1; /* 0 means bottom bar */
>> > -static const char *fonts[] = { "monospace:size=10" };
>> > +static const char *const fonts[] = { "monospace:size=10" };
>> > static const char dmenufont[] = "monospace:size=10";
>> > static const char col_gray1[] = "#222222";
>> > static const char col_gray2[] = "#444444";
>> > static const char col_gray3[] = "#bbbbbb";
>> > static const char col_gray4[] = "#eeeeee";
>> > static const char col_cyan[] = "#005577";
>> > -static const char *colors[][3] = {
>> > +static const char *const colors[][3] = {
>> > /* fg bg border */
>> > [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
>> > [SchemeSel] = { col_gray4, col_cyan, col_cyan },
>> > _AT_@ -56,10 +56,10 @@ static const Layout layouts[] = {
>> >
>> > /* commands */
>> > static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
>> > -static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
>> > -static const char *termcmd[] = { "st", NULL };
>> > +static const char *const dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
>> > +static const char *const termcmd[] = { "st", NULL };
>> >
>> > -static Key keys[] = {
>> > +static const Key keys[] = {
>> > /* modifier key function argument */
>> > { MODKEY, XK_p, spawn, {.v = dmenucmd } },
>> > { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
>> > _AT_@ -98,7 +98,7 @@ static Key keys[] = {
>> >
>> > /* button definitions */
>> > /* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
>> > -static Button buttons[] = {
>> > +static const Button buttons[] = {
>> > /* click event mask button function argument */
>> > { ClkLtSymbol, 0, Button1, setlayout, {0} },
>> > { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
>> > diff --git a/drw.c b/drw.c
>> > index 319eb6b..902976f 100644
>> > --- a/drw.c
>> > +++ b/drw.c
>> > _AT_@ -153,7 +153,7 @@ xfont_free(Fnt *font)
>> > }
>> >
>> > Fnt*
>> > -drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
>> > +drw_fontset_create(Drw* drw, const char *const fonts[], size_t fontcount)
>> > {
>> > Fnt *cur, *ret = NULL;
>> > size_t i;
>> > _AT_@ -194,7 +194,7 @@ drw_clr_create(Drw *drw, XftColor *dest, const char *clrname)
>> > /* Wrapper to create color schemes. The caller has to call free(3) on the
>> > * returned color scheme when done using it. */
>> > Scm
>> > -drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
>> > +drw_scm_create(Drw *drw, const char *const clrnames[], size_t clrcount)
>> > {
>> > size_t i;
>> > Scm ret;
>> > diff --git a/drw.h b/drw.h
>> > index ff4355b..2de6a6f 100644
>> > --- a/drw.h
>> > +++ b/drw.h
>> > _AT_@ -32,14 +32,14 @@ void drw_resize(Drw *drw, unsigned int w, unsigned int h);
>> > void drw_free(Drw *drw);
>> >
>> > /* Fnt abstraction */
>> > -Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
>> > +Fnt *drw_fontset_create(Drw* drw, const char *const fonts[], size_t fontcount);
>> > void drw_fontset_free(Fnt* set);
>> > unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
>> > void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
>> >
>> > /* Colorscheme abstraction */
>> > void drw_clr_create(Drw *drw, XftColor *dest, const char *clrname);
>> > -Scm drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
>> > +Scm drw_scm_create(Drw *drw, const char *const clrnames[], size_t clrcount);
>> >
>> > /* Cursor abstraction */
>> > Cur *drw_cur_create(Drw *drw, int shape);
>>
>> I like your patch, at first glance it makes config.h more consistent
>> with the other const declarations, however I need to browse through
>> the patches if there were any places, where the non-const declaration
>> was on purpose for some reason prior to accepting this upstream.
>
> Please no const char *const. I'm ok with the other const changes though.

Nice spot! I only glanced at it and didn't notice the pointer
qualifiers. This syntax really sucks from a readability point of view.

> Well, C might not have the most beautiful syntax in this regard, but I see no other way to make a pointer itself read-only (and especially the ...cmd[] pointer arrays really should be). Would using a typedef for that be more comfortable to you?

Are you suggesting to typedef const char *const coChar; or something
similar and then using coChar in those places? I would still prefer
the old way for readability reasons. There is no real impact either
imho.

BR,
Anselm



In information security, it is good practice to use the principle of least privilege. Setting data 'const' could not only help to spot future programming errors, but essentially keeps this data in a read-only memory page during run-time! While I agree that the C syntax for read-only pointers is not that readable, I don't understand, that you're seriously trading this against security.

Regarding 'typedef' I had something like the following in mind (you might want to use another name):

 typedef const char *stringPtr;

Then a declaration could look like this:

 static const stringPtr termcmd[] = { "st", NULL };

Maybe not the most beautiful, but IMHO it makes clear that this is an array of constant string pointers. Both, gcc and clang, then properly put this in read-only ELF sections.

Regards,
Jo.
Received on Wed Sep 06 2017 - 21:04:47 CEST

This archive was generated by hypermail 2.3.0 : Wed Sep 06 2017 - 21:12:22 CEST