LCOV - code coverage report
Current view: directory - src/trusted/validator - validation_cache.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 155 120 77.4 %
Date: 2014-10-23 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2013 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #include "native_client/src/trusted/validator/validation_cache.h"
       8                 : 
       9                 : #include <string.h>
      10                 : #include <sys/stat.h>
      11                 : 
      12                 : #include "native_client/src/public/desc_metadata_types.h"
      13                 : #include "native_client/src/shared/platform/nacl_check.h"
      14                 : #include "native_client/src/shared/platform/nacl_host_desc.h"
      15                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      16                 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
      17                 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
      18                 : #include "native_client/src/trusted/validator/rich_file_info.h"
      19                 : #include "native_client/src/trusted/validator/validation_cache_internal.h"
      20                 : #include "native_client/src/trusted/validator/validation_metadata.h"
      21                 : 
      22                 : #if NACL_WINDOWS
      23                 : #include <Windows.h>
      24                 : #include <io.h>
      25                 : #endif
      26                 : 
      27                 : #define ADD_LITERAL(cache, query, data) \
      28                 :   ((cache)->AddData((query), (uint8_t*)&(data), sizeof(data)))
      29                 : 
      30              11 : int NaClCachingIsInexpensive(struct NaClValidationCache *cache,
      31                 :                              const struct NaClValidationMetadata *metadata) {
      32              11 :   if (cache->CachingIsInexpensive != NULL) {
      33              11 :     return cache->CachingIsInexpensive(metadata);
      34                 :   } else {
      35               0 :     return NULL != metadata && metadata->identity_type == NaClCodeIdentityFile;
      36                 :   }
      37                 : }
      38                 : 
      39               7 : void NaClMetadataFromFDCtor(struct NaClValidationMetadata *metadata,
      40                 :                             int file_desc,
      41                 :                             const char* file_name,
      42                 :                             size_t file_name_length) {
      43                 :   struct NaClHostDesc wrapper;
      44                 :   nacl_host_stat_t stat;
      45                 : #if NACL_WINDOWS
      46                 :   BY_HANDLE_FILE_INFORMATION file_info;
      47                 : #endif
      48                 : 
      49               7 :   memset(metadata, 0, sizeof(*metadata));
      50                 :   /* If we early out, identity_type will be 0 / NaClCodeIdentityData. */
      51                 : 
      52               7 :   wrapper.d = file_desc;
      53               7 :   if(NaClHostDescFstat(&wrapper, &stat))
      54               7 :     return;
      55                 : 
      56                 : #if NACL_WINDOWS
      57                 :   /*
      58                 :    * This will not get us the complete file ID on ReFS, but doing the correct
      59                 :    * thing (calling GetFileInformationByHandleEx) causes linkage issues on
      60                 :    * Windows XP.  We aren't relying on the file ID for security, just collision
      61                 :    * resistance, so we don't need all of it.
      62                 :    * In many cases (including on NTFS) we're also getting the 32 least
      63                 :    * significant bits of a 64-bit volume serial number - but again, since it's
      64                 :    * random we can live with it.
      65                 :    */
      66                 :   if (!GetFileInformationByHandle((HANDLE) _get_osfhandle(file_desc),
      67                 :                                   &file_info))
      68                 :     return;
      69                 :   metadata->device_id = file_info.dwVolumeSerialNumber;
      70                 :   metadata->file_id = ((((uint64_t)file_info.nFileIndexHigh) << 32) |
      71                 :                        file_info.nFileIndexLow);
      72                 : #else
      73                 :   /* st_dev is not actually a property of the device, so skip it. */
      74               7 :   metadata->file_id = stat.st_ino;
      75                 : #endif
      76                 : 
      77               7 :   metadata->file_size = stat.st_size;
      78               7 :   metadata->mtime = stat.st_mtime;
      79               7 :   metadata->ctime = stat.st_ctime;
      80                 : 
      81               7 :   CHECK(0 < file_name_length);
      82               7 :   metadata->file_name = malloc(file_name_length);
      83               7 :   CHECK(NULL != metadata->file_name);
      84               7 :   memcpy(metadata->file_name, file_name, file_name_length);
      85               7 :   metadata->file_name_length = file_name_length;
      86                 : 
      87                 :   /* We have all the identity information we need. */
      88               7 :   metadata->identity_type = NaClCodeIdentityFile;
      89                 : }
      90                 : 
      91              12 : void NaClMetadataDtor(struct NaClValidationMetadata *metadata) {
      92              12 :   free(metadata->file_name);
      93                 :   /* Prevent use after free. */
      94              12 :   memset(metadata, 0, sizeof(*metadata));
      95              12 : }
      96                 : 
      97              66 : static void Serialize(uint8_t *buffer, const void *value, size_t size,
      98                 :                       uint32_t *offset) {
      99              66 :   if (buffer != NULL)
     100              33 :     memcpy(&buffer[*offset], value, size);
     101              66 :   *offset += (uint32_t) size;
     102              66 : }
     103                 : 
     104              26 : static void SerializeNaClDescMetadataInternal(
     105                 :     const struct NaClRichFileInfo *info,
     106                 :     uint8_t *buffer,
     107                 :     uint32_t *offset) {
     108              26 :   *offset = 0;
     109              26 :   Serialize(buffer, &info->known_file, sizeof(info->known_file), offset);
     110              26 :   if (info->known_file) {
     111              20 :     Serialize(buffer, &info->file_path_length, sizeof(info->file_path_length),
     112                 :               offset);
     113              20 :     Serialize(buffer, info->file_path, info->file_path_length, offset);
     114                 :   }
     115              26 : }
     116                 : 
     117              13 : int NaClSerializeNaClDescMetadata(
     118                 :     const struct NaClRichFileInfo *info,
     119                 :     uint8_t **buffer,
     120                 :     uint32_t *buffer_length) {
     121                 : 
     122              13 :   *buffer = NULL;
     123                 : 
     124                 :   /* Calculate the buffer size. */
     125              13 :   SerializeNaClDescMetadataInternal(info, NULL, buffer_length);
     126                 : 
     127                 :   /* Allocate the buffer. */
     128              13 :   *buffer = malloc(*buffer_length);
     129              13 :   if (NULL == *buffer)
     130               0 :     return 1;
     131                 : 
     132                 :   /* Fill the buffer. */
     133              13 :   SerializeNaClDescMetadataInternal(info, *buffer, buffer_length);
     134              13 :   return 0;
     135                 : }
     136                 : 
     137               9 : int NaClSetFileOriginInfo(struct NaClDesc *desc,
     138                 :                           struct NaClRichFileInfo *info) {
     139               9 :   uint8_t *buffer = NULL;
     140               9 :   uint32_t buffer_length = 0;
     141                 :   int status;
     142               9 :   if (NaClSerializeNaClDescMetadata(info, &buffer, &buffer_length)) {
     143               0 :     return 1;
     144                 :   }
     145               9 :   status = NACL_VTBL(NaClDesc, desc)->SetMetadata(
     146                 :       desc,
     147                 :       NACL_DESC_METADATA_ORIGIN_INFO_TYPE,
     148                 :       buffer_length,
     149                 :       (uint8_t *) buffer);
     150               9 :   free(buffer);
     151               9 :   return status;
     152                 : }
     153                 : 
     154              29 : static int Deserialize(const uint8_t *buffer, uint32_t buffer_length,
     155                 :                        void *value, size_t size, uint32_t *offset) {
     156              29 :   if (*offset + size > buffer_length)
     157               0 :     return 1;
     158              29 :   memcpy(value, &buffer[*offset], size);
     159              29 :   *offset += (uint32_t) size;
     160              29 :   return 0;
     161                 : }
     162                 : 
     163              11 : int NaClDeserializeNaClDescMetadata(
     164                 :     const uint8_t *buffer,
     165                 :     uint32_t buffer_length,
     166                 :     struct NaClRichFileInfo *info) {
     167                 :   /* Work around const issues. */
     168              11 :   char *file_path = NULL;
     169              11 :   uint32_t offset = 0;
     170              11 :   NaClRichFileInfoCtor(info);
     171                 : 
     172              11 :   if (Deserialize(buffer, buffer_length, &info->known_file,
     173                 :                   sizeof(info->known_file), &offset))
     174               0 :     goto on_error;
     175                 : 
     176              11 :   if (info->known_file) {
     177               9 :     if (Deserialize(buffer, buffer_length, &info->file_path_length,
     178                 :                     sizeof(info->file_path_length), &offset))
     179               0 :       goto on_error;
     180               9 :     file_path = malloc(info->file_path_length);
     181               9 :     if (NULL == file_path)
     182               0 :       goto on_error;
     183               9 :     if (Deserialize(buffer, buffer_length, file_path, info->file_path_length,
     184                 :                     &offset))
     185               0 :       goto on_error;
     186               9 :     info->file_path = file_path;
     187               9 :     file_path = NULL;
     188                 :   }
     189                 : 
     190                 :   /* Entire buffer consumed? */
     191              11 :   if (offset != buffer_length)
     192               0 :     goto on_error;
     193              11 :   return 0;
     194                 : 
     195                 :  on_error:
     196               0 :   free(file_path);
     197               0 :   NaClRichFileInfoDtor(info);
     198               0 :   return 1;
     199                 : }
     200                 : 
     201              44 : void NaClRichFileInfoCtor(struct NaClRichFileInfo *info) {
     202              44 :   memset(info, 0, sizeof(*info));
     203              44 : }
     204                 : 
     205              21 : void NaClRichFileInfoDtor(struct NaClRichFileInfo *info) {
     206                 :   /*
     207                 :    * file_path is "const" to express intent, we need to cast away the const to
     208                 :    * dallocate it.
     209                 :    */
     210              21 :   free((void *) info->file_path);
     211                 :   /* Prevent use after Dtor. */
     212              21 :   memset(info, 0, sizeof(*info));
     213              21 : }
     214                 : 
     215              15 : int NaClGetFileOriginInfo(struct NaClDesc *desc,
     216                 :                           struct NaClRichFileInfo *info) {
     217                 :   int32_t metadata_type;
     218              15 :   uint8_t *buffer = NULL;
     219              15 :   uint32_t buffer_length = 0;
     220                 :   int status;
     221                 : 
     222                 :   /* Get the buffer length. */
     223              15 :   metadata_type = NACL_VTBL(NaClDesc, desc)->GetMetadata(
     224                 :       desc,
     225                 :       &buffer_length,
     226                 :       NULL);
     227              15 :   if (metadata_type != NACL_DESC_METADATA_ORIGIN_INFO_TYPE)
     228               6 :     return 1;
     229                 : 
     230               9 :   buffer = (uint8_t *) malloc(buffer_length);
     231               9 :   if (NULL == buffer)
     232               0 :     return 1;
     233                 : 
     234               9 :   metadata_type = NACL_VTBL(NaClDesc, desc)->GetMetadata(
     235                 :       desc,
     236                 :       &buffer_length,
     237                 :       buffer);
     238               9 :   if (metadata_type != NACL_DESC_METADATA_ORIGIN_INFO_TYPE)
     239               0 :     return 1;
     240                 : 
     241               9 :   status = NaClDeserializeNaClDescMetadata(buffer, buffer_length, info);
     242               9 :   free(buffer);
     243               9 :   return status;
     244                 : }
     245                 : 
     246              12 : void NaClMetadataFromNaClDescCtor(struct NaClValidationMetadata *metadata,
     247                 :                                   struct NaClDesc *desc) {
     248                 :   struct NaClRichFileInfo info;
     249              12 :   int32_t fd = -1;
     250                 : 
     251              12 :   NaClRichFileInfoCtor(&info);
     252              12 :   memset(metadata, 0, sizeof(*metadata));
     253                 : 
     254              12 :   if (NACL_VTBL(NaClDesc, desc)->typeTag != NACL_DESC_HOST_IO)
     255               0 :     goto done;
     256              12 :   fd = ((struct NaClDescIoDesc *) desc)->hd->d;
     257              12 :   if (NaClGetFileOriginInfo(desc, &info))
     258               5 :     goto done;
     259               7 :   if (!info.known_file || info.file_path == NULL || info.file_path_length <= 0)
     260                 :     goto done;
     261               7 :   NaClMetadataFromFDCtor(metadata, fd, info.file_path, info.file_path_length);
     262                 :  done:
     263              12 :   NaClRichFileInfoDtor(&info);
     264              12 : }
     265                 : 
     266              11 : void NaClAddCodeIdentity(uint8_t *data,
     267                 :                          size_t size,
     268                 :                          const struct NaClValidationMetadata *metadata,
     269                 :                          struct NaClValidationCache *cache,
     270                 :                          void *query) {
     271                 :   NaClCodeIdentityType identity_type;
     272              11 :   if (NULL != metadata) {
     273               5 :     identity_type = metadata->identity_type;
     274                 :   } else {
     275                 :     /* Fallback: identity unknown, treat it as anonymous data. */
     276               6 :     identity_type = NaClCodeIdentityData;
     277                 :   }
     278              11 :   CHECK(identity_type < NaClCodeIdentityMax);
     279                 : 
     280                 :   /*
     281                 :    * Explicitly record the type of identity being used to prevent attacks
     282                 :    * that confuse the payload of different identity types.
     283                 :    */
     284              11 :   ADD_LITERAL(cache, query, identity_type);
     285                 : 
     286              11 :   if (identity_type == NaClCodeIdentityFile) {
     287                 :     /* Sanity checks. */
     288               5 :     CHECK(metadata->file_name);
     289               5 :     CHECK(metadata->file_name_length);
     290               5 :     CHECK(metadata->code_offset + (int64_t) size <= metadata->file_size);
     291                 : 
     292                 :     /* The location of the code in the file. */
     293               5 :     ADD_LITERAL(cache, query, metadata->code_offset);
     294               5 :     ADD_LITERAL(cache, query, size);
     295                 : 
     296                 :     /* The identity of the file. */
     297               5 :     ADD_LITERAL(cache, query, metadata->file_name_length);
     298               5 :     cache->AddData(query, (uint8_t *) metadata->file_name,
     299                 :                    metadata->file_name_length);
     300               5 :     ADD_LITERAL(cache, query, metadata->device_id);
     301               5 :     ADD_LITERAL(cache, query, metadata->file_id);
     302               5 :     ADD_LITERAL(cache, query, metadata->file_size);
     303               5 :     ADD_LITERAL(cache, query, metadata->mtime);
     304               5 :     ADD_LITERAL(cache, query, metadata->ctime);
     305                 :   } else {
     306                 :     /* Hash all the code. */
     307               6 :     cache->AddData(query, data, size);
     308                 :   }
     309              11 : }
     310                 : 
     311               0 : struct NaClDesc *NaClDescCreateWithFilePathMetadata(NaClHandle handle,
     312                 :                                                     const char *file_path) {
     313               0 :   struct NaClDesc *desc = NaClDescIoDescFromHandleAllocCtor(handle,
     314                 :                                                             NACL_ABI_O_RDONLY);
     315                 :   char *alloc_file_path;
     316               0 :   size_t file_path_length = strlen(file_path);
     317                 : 
     318                 :   struct NaClRichFileInfo info;
     319                 : 
     320               0 :   if (desc == NULL)
     321               0 :     return NULL;
     322                 : 
     323                 :   /*
     324                 :    * If there is no file path metadata, just return the created NaClDesc
     325                 :    * without adding rich file info.
     326                 :    */
     327               0 :   if (file_path_length == 0)
     328               0 :     return desc;
     329                 : 
     330                 :   /* Mark the desc as OK for mmapping. */
     331               0 :   NaClDescMarkSafeForMmap(desc);
     332                 : 
     333               0 :   alloc_file_path = (char *) malloc(file_path_length + 1);
     334               0 :   if (alloc_file_path == NULL) {
     335               0 :     NaClDescUnref(desc);
     336               0 :     return NULL;
     337                 :   }
     338               0 :   memcpy(alloc_file_path, file_path, file_path_length + 1);
     339                 : 
     340                 :   /* Provide metadata for validation. */
     341               0 :   NaClRichFileInfoCtor(&info);
     342               0 :   info.known_file = 1;
     343               0 :   info.file_path = alloc_file_path;  /* Takes ownership. */
     344               0 :   info.file_path_length = (uint32_t) file_path_length;
     345               0 :   NaClSetFileOriginInfo(desc, &info);
     346               0 :   NaClRichFileInfoDtor(&info);
     347               0 :   return desc;
     348                 : }

Generated by: LCOV version 1.7