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

Generated by: LCOV version 1.7