Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 May 1997 08:04:50 -0700 (PDT)
From:      mflatt@cs.rice.edu
To:        freebsd-gnats-submit@FreeBSD.ORG
Subject:   bin/3516: getcwd() fails to close a DIR* when the path buffer is too small
Message-ID:  <199705061504.IAA15277@hub.freebsd.org>
Resent-Message-ID: <199705061510.IAA15604@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         3516
>Category:       bin
>Synopsis:       getcwd() fails to close a DIR* when the path buffer is too small
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue May  6 08:10:01 PDT 1997
>Last-Modified:
>Originator:     Matthew Flatt
>Organization:
Rice PLT
>Release:        2.1.7
>Environment:
FreeBSD new-world.cs.rice.edu 2.1.7-RELEASE FreeBSD 2.1.7-RELEASE #0: Wed Feb 12 00:01:51 CST 1997     root@new-world.cs.rice.edu:/usr/src/sys/compile/NEWORLD  i386

>Description:
getcwd() takes a buffer and the buffer's size as the first
two arguments. If this buffer is large enough that getcwd()
opens a directory using opendir(), but too small to hold the
directory's name, it returns ERANGE (correct) but does not
close the directory with closedir() (incorrect) resulting
in a file descriptor leak.
>How-To-Repeat:

#include <unistd.h>
#include <errno.h>
#include <stdio.h>

#define SIZE 20

int main(int argc, char **argv)
{
  char small[SIZE];
  int count = 0;

  /* Should loop forever */  
  while (1) {
    count++;
    if (!getcwd(small, SIZE)) {
      if (errno != ERANGE) {
        printf("bad getcwd error (%d) at attempt %d\n", errno, count);
        return -1;
      }
    }
  }

  return 0;
}

>Fix:
*** /usr/src/lib/libc/gen/getcwd.c      Mon May  5 22:08:40 1997
--- /home/mflatt/tmp/getcwd.c   Tue May  6 10:00:20 1997
***************
*** 55,61 ****
        size_t size;
  {
        register struct dirent *dp;
!       register DIR *dir;
        register dev_t dev;
        register ino_t ino;
        register int first;
--- 55,61 ----
        size_t size;
  {
        register struct dirent *dp;
!       register DIR *dir = NULL;
        register dev_t dev;
        register ino_t ino;
        register int first;
***************
*** 213,218 ****
--- 213,219 ----
                bpt -= dp->d_namlen;
                bcopy(dp->d_name, bpt, dp->d_namlen);
                (void)closedir(dir);
+               dir = NULL;
  
                /* Truncate any file name. */
                *bup = '\0';
***************
*** 230,235 ****
--- 231,237 ----
  err:
        if (ptsize)
                free(pt);
+       if (dir) (void)closedir(dir);
        free(up);
        return (NULL);
  }

>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199705061504.IAA15277>