http://www.securityfocus.com/archive/82/488980/30/0/threaded Stack based overflow which is confirmed to be exploitable on FreeBSD 7.0. Fix: while (*from != '\0') { + if (to >= endto) { + *endto = '\0'; + return from; + } switch (*from) { case '"': instring = !instring; @@ -97,6 +101,10 @@ InterpretArg(const char *from, char *to) *to++ = '\\'; /* Pass the escapes on, maybe skipping \# */ break; } + if (to >= endto) { + *endto = '\0'; + return from; + } *to++ = *from++; break; case '$': @@ -127,6 +135,10 @@ InterpretArg(const char *from, char *to) *ptr++ = *from; *ptr = '\0'; } + if (to >= endto) { + *endto = '\0'; + return from; + } if (*to == '\0') *to++ = '$'; else if ((env = getenv(to)) != NULL) { @@ -142,6 +154,10 @@ InterpretArg(const char *from, char *to) if (len == 0) pwd = getpwuid(ID0realuid()); else { + if (to + len >= endto) { + *to = '\0'; + return from; + } strncpy(to, from, len); to[len] = '\0'; pwd = getpwnam(to); Submitted by Eygene Ryabinkin (rea-sec@codelabs.ru)--oGfy3gwDPofJxGxjgqjEpS7KzQKLTajKfAzDJhZ2Vw7AuxMg Content-Type: text/plain; name="file.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="file.diff" diff --git a/usr.sbin/ppp/systems.c b/usr.sbin/ppp/systems.c index 77f06a1..0cf01d1 100644 --- a/usr.sbin/ppp/systems.c +++ b/usr.sbin/ppp/systems.c @@ -82,6 +82,10 @@ InterpretArg(const char *from, char *to) from++; How-To-Repeat: 1. Run ppp 2. type the following (or atleat some variation of) ~/~/~/~/~/~/~/~/~/~/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxx
Responsible Changed From-To: freebsd-bugs->freebsd-net Over to maintainer(s).
Try the following patch (ported from OpenBSD): Index: systems.c =================================================================== --- systems.c (revision 224489) +++ systems.c (working copy) @@ -64,9 +64,12 @@ fclose(fp); } -/* Move string from ``from'' to ``to'', interpreting ``~'' and $.... */ +/* + * Move string from ``from'' to ``to'', interpreting ``~'' and $.... + * Returns NULL if string expansion failed due to lack of buffer space. + */ const char * -InterpretArg(const char *from, char *to) +InterpretArg(const char *from, char *to, size_t tosiz) { char *ptr, *startto, *endto; struct passwd *pwd; @@ -76,12 +79,14 @@ instring = 0; startto = to; - endto = to + LINE_LEN - 1; + endto = to + tosiz - 1; while(issep(*from)) from++; while (*from != '\0') { + if (to >= endto) + return NULL; switch (*from) { case '"': instring = !instring; @@ -97,6 +102,8 @@ *to++ = '\\'; /* Pass the escapes on, maybe skipping \# */ break; } + if (to >= endto) + return NULL; *to++ = *from++; break; case '$': @@ -108,7 +115,7 @@ if (ptr) { len = ptr - from - 2; if (endto - to < (int)len ) - len = endto - to; + return NULL; if (len) { strncpy(to, from+2, len); to[len] = '\0'; @@ -127,9 +134,13 @@ *ptr++ = *from; *ptr = '\0'; } + if (to >= endto) + return NULL; if (*to == '\0') *to++ = '$'; else if ((env = getenv(to)) != NULL) { + if (endto - to < (int)strlen(env)) + return NULL; strncpy(to, env, endto - to); *endto = '\0'; to += strlen(to); @@ -142,19 +153,24 @@ if (len == 0) pwd = getpwuid(ID0realuid()); else { + if (endto - to < (int)len) + return NULL; strncpy(to, from, len); to[len] = '\0'; pwd = getpwnam(to); } + if (to >= endto) + return NULL; if (pwd == NULL) *to++ = '~'; else { + if (endto - to < (int)strlen(pwd->pw_dir)) + return NULL; strncpy(to, pwd->pw_dir, endto - to); *endto = '\0'; to += strlen(to); from += len; } - endpwent(); break; default: @@ -179,12 +195,16 @@ #define CTRL_INCLUDE (1) static int -DecodeCtrlCommand(char *line, char *arg) +DecodeCtrlCommand(char *line, char *arg, size_t argsiz) { const char *end; if (!strncasecmp(line, "include", 7) && issep(line[7])) { - end = InterpretArg(line+8, arg); + end = InterpretArg(line+8, arg, argsiz); + if (end == NULL) { + log_Printf(LogWARN, "Failed to expand command '%s': too long for the destination buffer\n", line); + return CTRL_UNKNOWN; + } if (*end && *end != '#') log_Printf(LogWARN, "usage: !include filename\n"); else @@ -218,7 +238,6 @@ userok = 1; break; } - endpwent(); return 0; } @@ -353,7 +372,7 @@ break; case '!': - switch (DecodeCtrlCommand(cp+1, arg)) { + switch (DecodeCtrlCommand(cp+1, arg, LINE_LEN)) { case CTRL_INCLUDE: log_Printf(LogCOMMAND, "%s: Including \"%s\"\n", filename, arg); n = ReadSystem(bundle, name, arg, prompt, cx, how); Index: systems.h =================================================================== --- systems.h (revision 224489) +++ systems.h (working copy) @@ -40,4 +40,4 @@ extern void CloseSecret(FILE *); extern int AllowUsers(struct cmdargs const *); extern int AllowModes(struct cmdargs const *); -extern const char *InterpretArg(const char *, char *); +extern const char *InterpretArg(const char *, char *, size_t); Index: command.c =================================================================== --- command.c (revision 224489) +++ command.c (working copy) @@ -1139,7 +1134,11 @@ { char buff2[LINE_LEN-offset]; - InterpretArg(buff, buff2); + if (InterpretArg(buff, buff2, sizeof buff2) == NULL) { + log_Printf(LogWARN, "Failed to expand command '%s': too long for the destination buffer\n", buff); + return -1; + } + strncpy(buff, buff2, LINE_LEN - offset - 1); buff[LINE_LEN - offset - 1] = '\0'; %%% -- Maxim Konovalov
Responsible Changed From-To: freebsd-net->maxim Maxim has a patch, so assign this to him.
For bugs matching the following criteria: Status: In Progress Changed: (is less than) 2014-06-01 Reset to default assignee and clear in-progress tags. Mail being skipped
Keyword: patch or patch-ready – in lieu of summary line prefix: [patch] * bulk change for the keyword * summary lines may be edited manually (not in bulk). Keyword descriptions and search interface: <https://bugs.freebsd.org/bugzilla/describekeywords.cgi>