Changeset 58c34961 in rtems


Ignore:
Timestamp:
Aug 12, 2016, 8:02:52 AM (3 years ago)
Author:
Chris Johns <chrisj@…>
Branches:
master
Children:
97d395b
Parents:
75386e1
git-author:
Chris Johns <chrisj@…> (08/12/16 08:02:52)
git-committer:
Chris Johns <chrisj@…> (08/15/16 05:44:38)
Message:

libdl: Fix cache corruption bugs.

This patch fixes a number of bugs in the cache when requests are
made to read close to the end of the file and the data is copied
from the top of the cache buffer to the bottom of the buffer. This
was compounded by attempting to read past the end of the file.

Closes #2754.

Location:
cpukit/libdl
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libdl/rtl-obj-cache.c

    r75386e1 r58c34961  
    2020
    2121#include <errno.h>
     22#include <stdio.h>
    2223#include <string.h>
    2324#include <unistd.h>
     
    2627#include "rtl-obj-cache.h"
    2728#include "rtl-error.h"
     29#include "rtl-trace.h"
    2830
    2931bool
     
    4749rtems_rtl_obj_cache_close (rtems_rtl_obj_cache_t* cache)
    4850{
     51  if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
     52    printf ("rtl: cache: %2d: close\n", cache->fd);
    4953  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, cache->buffer);
     54  cache->buffer    = NULL;
    5055  cache->fd        = -1;
    5156  cache->file_size = 0;
     
    5661rtems_rtl_obj_cache_flush (rtems_rtl_obj_cache_t* cache)
    5762{
     63  if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
     64    printf ("rtl: cache: %2d: flush\n", cache->fd);
    5865  cache->fd        = -1;
    5966  cache->file_size = 0;
     67  cache->offset    = 0;
    6068  cache->level     = 0;
    6169}
     
    7078  struct stat sb;
    7179
     80  if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
     81    printf ("rtl: cache: %2d: fd=%d offset=%d length=%d area=[%d,%d] cache=[%d,%d] size=%d\n",
     82            fd, cache->fd, (int) offset, (int) *length,
     83            (int) offset, (int) offset + *length,
     84            (int) cache->offset, (int) cache->offset + cache->level,
     85            (int) cache->file_size);
     86
    7287  if (*length > cache->size)
    7388  {
     
    85100    }
    86101
     102    /*
     103     * We sometimes are asked to read strings of a length we do not know.
     104     */
    87105    if ((offset + *length) > cache->file_size)
     106    {
    88107      *length = cache->file_size - offset;
     108      if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
     109        printf ("rtl: cache: %2d: truncate length=%d\n", fd, (int) *length);
     110    }
    89111  }
    90112
     
    99121    if (fd == cache->fd)
    100122    {
     123      /*
     124       * Do not read past the end of the file.
     125       */
     126      if ((offset + buffer_read) > cache->file_size)
     127        buffer_read = cache->file_size - offset;
     128
    101129      /*
    102130       * Is any part of the data in the cache ?
     
    105133          (offset < (cache->offset + cache->level)))
    106134      {
     135        size_t size;
     136
    107137        buffer_offset = offset - cache->offset;
     138        size          = cache->level - buffer_offset;
    108139
    109140        /*
     
    115146         * Is all the data in the cache or just a part ?
    116147         */
    117         if (*length <= (cache->level - buffer_offset))
    118         {
     148        if (*length <= size)
    119149          return true;
    120         }
    121 
    122         /*
    123          * Copy down the data in the buffer and then fill the remaining
    124          * space with as much data we are able to read.
    125          */
    126         memmove (cache->buffer,
    127                  cache->buffer + buffer_offset,
    128                  cache->size - buffer_offset);
    129 
    130         buffer_read   = buffer_offset;
    131         buffer_offset = cache->size - buffer_offset;
    132       }
    133     }
     150
     151        if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
     152          printf ("rtl: cache: %2d: copy-down: buffer_offset=%d size=%d level=%d\n",
     153                  fd, (int) buffer_offset, (int) size, (int) cache->level);
     154
     155        /*
     156         * Copy down the data in the buffer and then fill the remaining space
     157         * with as much data we are able to read.
     158         */
     159        memmove (cache->buffer, cache->buffer + buffer_offset, size);
     160
     161        cache->offset = offset;
     162        cache->level  = size;
     163        buffer_read   = cache->size - cache->level;
     164        buffer_offset = size;
     165
     166        /*
     167         * Do not read past the end of the file.
     168         */
     169        if ((offset + buffer_offset + buffer_read) > cache->file_size)
     170          buffer_read = cache->file_size - (offset + buffer_offset);
     171      }
     172    }
     173
     174    if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
     175      printf ("rtl: cache: %2d: seek: offset=%d buffer_offset=%d read=%d cache=[%d,%d] dist=%d\n",
     176              fd, (int) offset + buffer_offset, (int) buffer_offset, (int) buffer_read,
     177              (int) offset, (int) offset + buffer_read,
     178              (int) (cache->file_size - offset));
    134179
    135180    if (lseek (fd, offset + buffer_offset, SEEK_SET) < 0)
     
    144189     * want. If not it is an error. A POSIX read can read data in fragments.
    145190     */
    146     cache->level = buffer_read;
     191
     192    cache->level = buffer_offset + buffer_read;
     193
    147194    while (buffer_read)
    148195    {
     
    155202      if ((r == 0) && buffer_read)
    156203      {
     204        if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
     205          printf ("rtl: cache: %2d: read: past end by=%d\n", fd, (int) buffer_read);
    157206        cache->level = cache->level - buffer_read;
    158207        buffer_read = 0;
     
    165214    }
    166215
    167     cache->fd = fd;
    168216    cache->offset = offset;
    169217
    170     if (fstat (cache->fd, &sb) < 0)
    171     {
    172       rtems_rtl_set_error (errno, "file stat failed");
    173       return false;
    174     }
    175 
    176     cache->file_size = sb.st_size;
     218    if (cache->fd != fd)
     219    {
     220      cache->fd = fd;
     221
     222      if (fstat (cache->fd, &sb) < 0)
     223      {
     224        rtems_rtl_set_error (errno, "file stat failed");
     225        return false;
     226      }
     227
     228      cache->file_size = sb.st_size;
     229    }
    177230  }
    178231
  • cpukit/libdl/rtl-trace.c

    r75386e1 r58c34961  
    5959  const char* table[] =
    6060  {
     61    "detail",
     62    "warning",
    6163    "load",
    6264    "unload",
     
    6870    "allocator",
    6971    "unresolved",
    70     "detail"
     72    "cache"
    7173  };
    7274
  • cpukit/libdl/rtl-trace.h

    r75386e1 r58c34961  
    3737 * List of tracing bits for the various parts of the link editor.
    3838 */
    39 #define RTEMS_RTL_TRACE_ALL                    (0xffffffffUL)
    40 #define RTEMS_RTL_TRACE_LOAD                   (1UL << 0)
    41 #define RTEMS_RTL_TRACE_UNLOAD                 (1UL << 1)
    42 #define RTEMS_RTL_TRACE_SECTION                (1UL << 2)
    43 #define RTEMS_RTL_TRACE_SYMBOL                 (1UL << 3)
    44 #define RTEMS_RTL_TRACE_RELOC                  (1UL << 4)
    45 #define RTEMS_RTL_TRACE_GLOBAL_SYM             (1UL << 5)
    46 #define RTEMS_RTL_TRACE_LOAD_SECT              (1UL << 6)
    47 #define RTEMS_RTL_TRACE_ALLOCATOR              (1UL << 7)
    48 #define RTEMS_RTL_TRACE_UNRESOLVED             (1UL << 8)
    49 #define RTEMS_RTL_TRACE_DETAIL                 (1UL << 9)
    50 #define RTEMS_RTL_TRACE_WARNING                (1UL << 10)
     39#define RTEMS_RTL_TRACE_DETAIL                 (1UL << 0)
     40#define RTEMS_RTL_TRACE_WARNING                (1UL << 1)
     41#define RTEMS_RTL_TRACE_LOAD                   (1UL << 2)
     42#define RTEMS_RTL_TRACE_UNLOAD                 (1UL << 3)
     43#define RTEMS_RTL_TRACE_SECTION                (1UL << 4)
     44#define RTEMS_RTL_TRACE_SYMBOL                 (1UL << 5)
     45#define RTEMS_RTL_TRACE_RELOC                  (1UL << 6)
     46#define RTEMS_RTL_TRACE_GLOBAL_SYM             (1UL << 7)
     47#define RTEMS_RTL_TRACE_LOAD_SECT              (1UL << 8)
     48#define RTEMS_RTL_TRACE_ALLOCATOR              (1UL << 9)
     49#define RTEMS_RTL_TRACE_UNRESOLVED             (1UL << 10)
     50#define RTEMS_RTL_TRACE_CACHE                  (1UL << 11)
     51#define RTEMS_RTL_TRACE_ALL                    (0xffffffffUL & ~(RTEMS_RTL_TRACE_CACHE))
    5152
    5253/**
Note: See TracChangeset for help on using the changeset viewer.