From owner-freebsd-net@FreeBSD.ORG Fri Jul 29 09:00:27 2011 Return-Path: Delivered-To: freebsd-net@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 378D8106564A for ; Fri, 29 Jul 2011 09:00:27 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 1E2978FC15 for ; Fri, 29 Jul 2011 09:00:27 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id p6T90QvK091149 for ; Fri, 29 Jul 2011 09:00:26 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id p6T90QPo091148; Fri, 29 Jul 2011 09:00:26 GMT (envelope-from gnats) Date: Fri, 29 Jul 2011 09:00:26 GMT Message-Id: <201107290900.p6T90QPo091148@freefall.freebsd.org> To: freebsd-net@FreeBSD.org From: Maxim Konovalov Cc: Subject: bin/121359 X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Maxim Konovalov List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 29 Jul 2011 09:00:27 -0000 The following reply was made to PR bin/121359; it has been noted by GNATS. From: Maxim Konovalov To: bug-followup@freebsd.org Cc: Subject: bin/121359 Date: Fri, 29 Jul 2011 12:53:19 +0400 (MSD) 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