LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - sel_validate_image.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 75 61 81.3 %
Date: 2014-06-18 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 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/include/concurrency_ops.h"
       8                 : #include "native_client/src/shared/platform/nacl_log.h"
       9                 : #include "native_client/src/shared/utils/types.h"
      10                 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
      11                 : #include "native_client/src/trusted/validator/ncvalidate.h"
      12                 : 
      13                 : const size_t kMinimumCachedCodeSize = 40000;
      14                 : 
      15                 : /* Translate validation status to values wanted by sel_ldr. */
      16            1465 : static int NaClValidateStatus(NaClValidationStatus status) {
      17            1465 :   switch (status) {
      18                 :     case NaClValidationSucceeded:
      19            1379 :       return LOAD_OK;
      20                 :     case NaClValidationFailedOutOfMemory:
      21                 :       /* Note: this is confusing, but is what sel_ldr is expecting. */
      22              43 :       return LOAD_BAD_FILE;
      23                 :     case NaClValidationFailed:
      24                 :     case NaClValidationFailedNotImplemented:
      25                 :     case NaClValidationFailedCpuNotSupported:
      26                 :     case NaClValidationFailedSegmentationIssue:
      27                 :     default:
      28              43 :       return LOAD_VALIDATION_FAILED;
      29                 :   }
      30            1422 : }
      31                 : 
      32            1402 : int NaClValidateCode(struct NaClApp *nap, uintptr_t guest_addr,
      33            1402 :                      uint8_t *data, size_t size,
      34            1402 :                      const struct NaClValidationMetadata *metadata) {
      35            1402 :   NaClValidationStatus status = NaClValidationSucceeded;
      36            1402 :   struct NaClValidationCache *cache = nap->validation_cache;
      37            1402 :   const struct NaClValidatorInterface *validator = nap->validator;
      38                 : 
      39            1402 :   if (size < kMinimumCachedCodeSize) {
      40                 :     /*
      41                 :      * Don't cache the validation of small code chunks for three reasons:
      42                 :      * 1) The size of the validation cache will be bounded.  Cache entries are
      43                 :      *    better used for bigger code.
      44                 :      * 2) The per-transaction overhead of validation caching is more noticeable
      45                 :      *    for small code.
      46                 :      * 3) JITs tend to generate a lot of small code chunks, and JITed code may
      47                 :      *    never be seen again.  Currently code size is the best mechanism we
      48                 :      *    have for heuristically distinguishing between JIT and static code.
      49                 :      *    (In practice most Mono JIT blocks are less than 1k, and a quick look
      50                 :      *    didn't show any above 35k.)
      51                 :      * The choice of what constitutes "small" is arbitrary, and should be
      52                 :      * empirically tuned.
      53                 :      * TODO(ncbray) let the syscall specify if the code is cached or not.
      54                 :      */
      55            1058 :     metadata = NULL;
      56            1058 :     cache = NULL;
      57            1058 :   }
      58                 : 
      59                 :   /* As fixed feature mode implies the text should be readonly, and
      60                 :    * stubout mode implies updating the text, disallow their use together.
      61                 :    */
      62            1402 :   if (nap->validator_stub_out_mode && nap->fixed_feature_cpu_mode) {
      63               0 :     NaClLog(LOG_FATAL,
      64                 :             "stub_out_mode and fixed_feature_cpu_mode are incompatible\n");
      65               0 :     return LOAD_VALIDATION_FAILED;
      66                 :   }
      67            1402 :   if (nap->validator_stub_out_mode) {
      68                 :     /* Validation caching is currently incompatible with stubout. */
      69               0 :     metadata = NULL;
      70               0 :     cache = NULL;
      71                 :     /* In stub out mode, we do two passes.  The second pass acts as a
      72                 :        sanity check that bad instructions were indeed overwritten with
      73                 :        allowable HLTs. */
      74               0 :     status = validator->Validate(guest_addr, data, size,
      75                 :                                  TRUE, /* stub out */
      76                 :                                  FALSE, /* text is not read-only */
      77                 :                                  nap->cpu_features,
      78                 :                                  metadata,
      79                 :                                  cache);
      80               0 :   }
      81            1402 :   if (status == NaClValidationSucceeded) {
      82                 :     /* Fixed feature CPU mode implies read-only. */
      83            1402 :     int readonly_text = nap->fixed_feature_cpu_mode;
      84            1402 :     status = validator->Validate(guest_addr, data, size,
      85                 :                                  FALSE, /* do not stub out */
      86                 :                                  readonly_text,
      87                 :                                  nap->cpu_features,
      88                 :                                  metadata,
      89                 :                                  cache);
      90            1402 :   }
      91            1402 :   return NaClValidateStatus(status);
      92            1402 : }
      93                 : 
      94              13 : int NaClValidateCodeReplacement(struct NaClApp *nap, uintptr_t guest_addr,
      95              13 :                                 uint8_t *data_old, uint8_t *data_new,
      96              13 :                                 size_t size) {
      97              13 :   if (nap->validator_stub_out_mode) return LOAD_BAD_FILE;
      98              13 :   if (nap->fixed_feature_cpu_mode) return LOAD_BAD_FILE;
      99                 : 
     100              26 :   if ((guest_addr % nap->bundle_size) != 0 ||
     101                 :       (size % nap->bundle_size) != 0) {
     102               0 :     return LOAD_BAD_FILE;
     103                 :   }
     104                 : 
     105              13 :   return NaClValidateStatus(nap->validator->ValidateCodeReplacement(
     106                 :       guest_addr, data_old, data_new, size, nap->cpu_features));
     107              13 : }
     108                 : 
     109               7 : int NaClCopyCode(struct NaClApp *nap, uintptr_t guest_addr,
     110               7 :                  uint8_t *data_old, uint8_t *data_new,
     111               7 :                  size_t size) {
     112               7 :   int status;
     113                 :   /* Fixed-feature mode disables any code copying for now. Currently
     114                 :    * the only use of NaClCodeCopy() seems to be for dynamic code
     115                 :    * modification, which should fail in NaClValidateCodeReplacement()
     116                 :    * before reaching this.
     117                 :    */
     118               7 :   if (nap->fixed_feature_cpu_mode) {
     119               0 :     return LOAD_BAD_FILE;
     120                 :   }
     121               7 :   status = NaClValidateStatus(nap->validator->CopyCode(
     122                 :                               guest_addr, data_old, data_new, size,
     123                 :                               nap->cpu_features,
     124                 :                               NaClCopyInstruction));
     125                 :   /*
     126                 :    * Flush the processor's instruction cache.  This is not necessary
     127                 :    * for security, because any old cached instructions will just be
     128                 :    * safe halt instructions.  It is only necessary to ensure that
     129                 :    * untrusted code runs correctly when it tries to execute the
     130                 :    * dynamically-loaded code.
     131                 :    */
     132               7 :   NaClFlushCacheForDoublyMappedCode(data_old,
     133                 :                                     (uint8_t *) guest_addr,
     134                 :                                     size);
     135               7 :   return status;
     136               7 : }
     137                 : 
     138             263 : NaClErrorCode NaClValidateImage(struct NaClApp  *nap) {
     139             263 :   uintptr_t               memp;
     140             263 :   uintptr_t               endp;
     141             263 :   size_t                  regionsize;
     142             263 :   NaClErrorCode           rcode;
     143                 : 
     144             263 :   memp = nap->mem_start + NACL_TRAMPOLINE_END;
     145             263 :   endp = nap->mem_start + nap->static_text_end;
     146             263 :   regionsize = endp - memp;
     147             263 :   if (endp < memp) {
     148               0 :     return LOAD_NO_MEMORY;
     149                 :   }
     150                 : 
     151             263 :   if (nap->skip_validator) {
     152               0 :     NaClLog(LOG_ERROR, "VALIDATION SKIPPED.\n");
     153               0 :     return LOAD_OK;
     154                 :   } else {
     155                 :     /* TODO(ncbray) metadata for the main image. */
     156             263 :     rcode = NaClValidateCode(nap, NACL_TRAMPOLINE_END,
     157                 :                              (uint8_t *) memp, regionsize, NULL);
     158             263 :     if (LOAD_OK != rcode) {
     159               1 :       if (nap->ignore_validator_result) {
     160               0 :         NaClLog(LOG_ERROR, "VALIDATION FAILED: continuing anyway...\n");
     161               0 :         rcode = LOAD_OK;
     162               0 :       } else {
     163               1 :         NaClLog(LOG_ERROR, "VALIDATION FAILED.\n");
     164               1 :         NaClLog(LOG_ERROR,
     165                 :                 "Run sel_ldr in debug mode to ignore validation failure.\n");
     166               1 :         NaClLog(LOG_ERROR,
     167                 :                 "Run ncval <module-name> for validation error details.\n");
     168               1 :         rcode = LOAD_VALIDATION_FAILED;
     169                 :       }
     170               1 :     }
     171                 :   }
     172             263 :   return rcode;
     173             263 : }

Generated by: LCOV version 1.7