bin/121359

Maxim Konovalov maxim.konovalov at gmail.com
Fri Jul 29 09:00:27 UTC 2011


The following reply was made to PR bin/121359; it has been noted by GNATS.

From: Maxim Konovalov <maxim.konovalov at gmail.com>
To: bug-followup at 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


More information about the freebsd-net mailing list