This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/17897] New: Multiple 'Dynamic Stack Allocations' in security point of view


https://sourceware.org/bugzilla/show_bug.cgi?id=17897

            Bug ID: 17897
           Summary: Multiple 'Dynamic Stack Allocations' in security point
                    of view
           Product: glibc
           Version: 2.20
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
          Assignee: unassigned at sourceware dot org
          Reporter: max at cxib dot net
                CC: drepper.fsp at gmail dot com

Hi,

In response to

https://www.securecoding.cert.org/confluence/display/seccode/MEM05-C.+Avoid+large+stack+allocations

I would like to share the result of static code analysis. A few examples of
dynamical memory allocation on the stack in glibc 2.20 for further analysis
(false/positive)

====================================================
nis/nss_nisplus/nisplus-service.c
enum nss_status
_nss_nisplus_getservbyname_r (const char *name, const char *protocol,
                  struct servent *serv,
                  char *buffer, size_t buflen, int *errnop)
{
  if (tablename_val == NULL)
    {
      __libc_lock_lock (lock);

      enum nss_status status = _nss_create_tablename (errnop);

      __libc_lock_unlock (lock);

      if (status != NSS_STATUS_SUCCESS)
    return status;
    }

  if (name == NULL || protocol == NULL)
    {
      *errnop = EINVAL;
      return NSS_STATUS_NOTFOUND;
    }

  size_t protocol_len = strlen (protocol);
  char buf[strlen (name) + protocol_len + 17 + tablename_len];
<================================
  int olderr = errno;
...
      /* We need to allocate a new buffer since there is no
         guarantee the returned name has a length limit.  */
      const char *entryval = NISENTRYVAL(0, 0, result);
      size_t buflen = (strlen (entryval) + protocol_len + 17
               + tablename_len);
      bufptr = alloca (buflen); <================================
      snprintf (bufptr, buflen, "[cname=%s,proto=%s],%s",
            entryval, protocol, tablename_val);


====================================================
nscd/servicescache.c

static time_t
cache_addserv (struct database_dyn *db, int fd, request_header *req,
           const void *key, struct servent *serv, uid_t owner,
           struct hashentry *const he, struct datahead *dh, int errval)
{
...
 else
    {
      /* Determine the I/O structure.  */
      size_t s_name_len = strlen (serv->s_name) + 1;
      size_t s_proto_len = strlen (serv->s_proto) + 1;
      uint32_t *s_aliases_len;
      size_t s_aliases_cnt;
      char *aliases;
      char *cp;
      size_t cnt;

      /* Determine the number of aliases.  */
      s_aliases_cnt = 0;
      for (cnt = 0; serv->s_aliases[cnt] != NULL; ++cnt)
    ++s_aliases_cnt;
      /* Determine the length of all aliases.  */
      s_aliases_len = (uint32_t *) alloca (s_aliases_cnt * sizeof (uint32_t));
<========

====================================================
sysdeps/mach/hurd/chroot.c

int
chroot (const char *path)
{
  const char *lookup;
  size_t len;
  file_t dir, root;
  error_t err;

  /* Append trailing "/." to directory name to force ENOTDIR if it's not a
     directory and EACCES if we don't have search permission.  */
  len = strlen (path);
  if (len >= 2 && path[len - 2] == '/' && path[len - 1] == '.')
    lookup = path;
  else if (len == 0)
    /* Special-case empty file name according to POSIX.  */
    return __hurd_fail (ENOENT);
  else
    {
      char *n = alloca (len + 3); <============
      memcpy (n, path, len);
====================================================

locale/programs/locfile.c

int
locfile_read (struct localedef_t *result, const struct charmap_t *charmap)
{
  const char *filename = result->name;
  const char *repertoire_name = result->repertoire_name;
  int locale_mask = result->needed & ~result->avail;
  struct linereader *ldfile;
  int not_here = ALL_LOCALES;

  /* If no repertoire name was specified use the global one.  */
  if (repertoire_name == NULL)
    repertoire_name = repertoire_global;

  /* Open the locale definition file.  */
  ldfile = lr_open (filename, locfile_hash);
  if (ldfile == NULL)
    {
      if (filename != NULL && filename[0] != '/')
    {
      char *i18npath = getenv ("I18NPATH");
      if (i18npath != NULL && *i18npath != '\0')
        {
          const size_t pathlen = strlen (i18npath);
          char i18npathbuf[pathlen + 1];
<======================================

====================================================
locale/programs/locarchive.c


/* Check the content of the archive for duplicates.  Add the content
   of the files if necessary.  Returns the locrec_offset.  */
static uint32_t
add_locale (struct locarhandle *ah,
        const char *name, locale_data_t data, bool replace)
{
  /* First look for the name.  If it already exists and we are not
     supposed to replace it don't do anything.  If it does not exist
     we have to allocate a new locale record.  */
  size_t name_len = strlen (name);
  uint32_t file_offsets[__LC_LAST];

...
  /* Copy the data for all the small categories into the LC_ALL
     pseudo-category.  */

  data[LC_ALL].addr = alloca (data[LC_ALL].size);
<======================================
  memset (data[LC_ALL].addr, 0, data[LC_ALL].size);
...
    /* If block of small categories would cross page boundary,
       align it unless it immediately follows a large category.  */
    if (cnt == LC_ALL && lastoffset != lastpos
        && ((((lastpos & (pagesz - 1)) + data[cnt].size + pagesz - 1)
         & -pagesz)
        > ((data[cnt].size + pagesz - 1) & -pagesz)))
      {
        size_t sz = pagesz - (lastpos & (pagesz - 1));
        char *zeros = alloca (sz);

        memset (zeros, 0, sz);
====================================================
posix/annexc.c

static int
check_header (const struct header *header, const char **except)
{
  char line[BUFSIZ], command[sizeof fmt + strlen (header->name)
                 + 2 * strlen (CC)
                 + strlen (INC) + strlen (macrofile)];
<======================================
====================================================
catgets/catgets.c

/* Open the catalog and return a descriptor for the catalog.  */
nl_catd
catopen (const char *cat_name, int flag)
<====================================== cat_name on the stack
{
====================================================

Maksymilian Arciemowicz
http://cxsecurity.com/
http://cifrex.org/

-- 
You are receiving this mail because:
You are on the CC list for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]