From 642002409a9795305818a29d7f923b3cbe7297eb Mon Sep 17 00:00:00 2001 From: Matthias Hopf Date: Wed, 6 Apr 2011 01:22:03 +0200 Subject: [PATCH] xrdb: Create shell-escape-safe cpp options in the non-pathetic-cpp case. Fixes CVE-2011-0465. Signed-off-by: Matthias Hopf Reviewed-by: Adam Jackson --- xrdb/xrdb.c | 79 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 16 deletions(-) diff --git a/xrdb/xrdb.c b/xrdb/xrdb.c index 8811120..a5ec0ba 100644 --- a/xrdb/xrdb.c +++ b/xrdb/xrdb.c @@ -145,6 +145,8 @@ static Entries newDB; static void fatal(char *, ...); static void addstring ( String *arg, const char *s ); +static void addescapedstring ( String *arg, const char *s ); +static void addtokstring ( String *arg, const char *s ); static void FormatEntries ( Buffer *buffer, Entries *entries ); static void StoreProperty ( Display *dpy, Window root, Atom res_prop ); static void Process ( int scrno, Bool doScreen, Bool execute ); @@ -394,13 +396,19 @@ AddDef(String *buff, char *title, char *value) addstring(buff, " -D"); } else addstring(buff, "-D"); - addstring(buff, title); + addtokstring(buff, title); if (value && (value[0] != '\0')) { addstring(buff, "="); - addstring(buff, value); + addescapedstring(buff, value); } } +static void +AddSimpleDef(String *buff, char *title) +{ + AddDef(buff, title, (char *)NULL); +} + static void AddDefQ(String *buff, char *title, char *value) { @@ -410,8 +418,9 @@ AddDefQ(String *buff, char *title, char *value) else #endif if (value && (value[0] != '\0')) { - AddDef(buff, title, "\""); - addstring(buff, value); + AddSimpleDef(buff, title); + addstring(buff, "=\""); + addescapedstring(buff, value); addstring(buff, "\""); } else AddDef(buff, title, NULL); @@ -426,24 +435,28 @@ AddNum(String *buff, char *title, int value) } static void -AddSimpleDef(String *buff, char *title) +AddDefTok(String *buff, char *prefix, char *title) { - AddDef(buff, title, (char *)NULL); + char name[512]; + + snprintf(name, sizeof(name), "%s%s", prefix, title); + AddSimpleDef(buff, name); } static void -AddDefTok(String *buff, char *prefix, char *title) +AddDefHostname(String *buff, char *title, char *value) { char *s; char name[512]; char c; - snprintf(name, sizeof(name), "%s%s", prefix, title); + strncpy (name, value, sizeof(name)-1); + name[sizeof(name)-1] = '\0'; for (s = name; (c = *s); s++) { - if (!isalpha(c) && !isdigit(c) && c != '_') + if (!isalpha(c) && !isdigit(c) && c != '_' && c != '.' && c != ':' && c != '-') *s = '_'; } - AddSimpleDef(buff, name); + AddDef(buff, title, name); } static void @@ -463,7 +476,7 @@ AddUndef(String *buff, char *title) addstring(buff, " -U"); } else addstring(buff, "-U"); - addstring(buff, title); + addtokstring(buff, title); } static void @@ -526,11 +539,11 @@ DoDisplayDefines(Display *display, String *defs, char *host) } if (!*server || !strcmp(server, "unix") || !strcmp(server, "localhost")) strcpy(server, client); - AddDef(defs, "HOST", server); /* R3 compatibility */ - AddDef(defs, "SERVERHOST", server); + AddDefHostname(defs, "HOST", server); /* R3 compatibility */ + AddDefHostname(defs, "SERVERHOST", server); AddDefTok(defs, "SRVR_", server); AddNum(defs, "DISPLAY_NUM", n); - AddDef(defs, "CLIENTHOST", client); + AddDefHostname(defs, "CLIENTHOST", client); AddDefTok(defs, "CLNT_", client); AddNum(defs, "VERSION", ProtocolVersion(display)); AddNum(defs, "REVISION", ProtocolRevision(display)); @@ -573,7 +586,7 @@ DoScreenDefines(Display *display, int scrno, String *defs) AddNum(defs, "Y_RESOLUTION", Resolution(screen->height,screen->mheight)); AddNum(defs, "PLANES", DisplayPlanes(display, scrno)); AddNum(defs, "BITS_PER_RGB", visual->bits_per_rgb); - AddDef(defs, "CLASS", ClassNames[visual->class]); + AddDefQ(defs, "CLASS", ClassNames[visual->class]); snprintf(name, sizeof(name), "CLASS_%s", ClassNames[visual->class]); AddNum(defs, name, (int)visual->visualid); switch(visual->class) { @@ -766,6 +779,40 @@ addstring(String *arg, const char *s) arg->used += strlen(s); } +static void +addescapedstring(String *arg, const char *s) +{ + char copy[512], *c; + + for (c = copy; *s && c < ©[sizeof(copy)-1]; s++) { + switch (*s) { + case '"': case '\'': case '`': + case '$': case '\\': + *c++ = '_'; + break; + default: + *c++ = *s; + } + } + *c = 0; + addstring (arg, copy); +} + +static void +addtokstring(String *arg, const char *s) +{ + char copy[512], *c; + + for (c = copy; *s && c < ©[sizeof(copy)-1]; s++) { + if (!isalpha(*s) && !isdigit(*s) && *s != '_') + *c++ = '_'; + else + *c++ = *s; + } + *c = 0; + addstring (arg, copy); +} + int main(int argc, char *argv[]) @@ -861,7 +908,7 @@ main(int argc, char *argv[]) continue; } else if (arg[1] == 'I') { addstring(&includes, " "); - addstring(&includes, arg); + addescapedstring(&includes, arg); continue; } else if (arg[1] == 'U' || arg[1] == 'D') { if (num_cmd_defines < MAX_CMD_DEFINES) {