BVB Source Codes

rkt Show diagnostic-util.c Source code

Return Download rkt: download diagnostic-util.c Source code - Download rkt Source code - Type:.c
  1. // Copyright 2014-2016 The rkt Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. //     http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14.  
  15. #define _GNU_SOURCE
  16. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <grp.h>
  19. #include <inttypes.h>
  20. #include <limits.h>
  21. #include <stdint.h>
  22. #include <sys/mman.h>
  23. #include <sys/stat.h>
  24. #include <sys/types.h>
  25. #include <unistd.h>
  26.  
  27. #include "diagnostic-util.h"
  28. #include "elf.h"
  29.  
  30.  
  31. static void map_file(const char *path, int prot, int flags, struct stat *st, void **map)
  32. {
  33.     int fd;
  34.  
  35.     pexit_if((fd = open(path, O_RDONLY)) == -1,
  36.              "Unable to open \"%s\"", path);
  37.     pexit_if(fstat(fd, st) == -1,
  38.              "Cannot stat \"%s\"", path);
  39.     exit_if(!S_ISREG(st->st_mode), "\"%s\" is not a regular file", path);
  40.     pexit_if(!(*map = mmap(NULL, st->st_size, prot, flags, fd, 0)),
  41.              "Mmap of \"%s\" failed", path);
  42.     pexit_if(close(fd) == -1,
  43.              "Close of %i [%s] failed", fd, path);
  44. }
  45.  
  46. void diag(const char *exe)
  47. {
  48.     static const uint8_t        elf[] = {0x7f, 'E', 'L', 'F'};
  49.     static const uint8_t        shebang[] = {'#','!'};
  50.     static int                  diag_depth;
  51.     struct stat                 st;
  52.     const uint8_t               *mm;
  53.     const char                  *itrp = NULL;
  54.  
  55.     map_file(exe, PROT_READ, MAP_SHARED, &st, (void **)&mm);
  56.     exit_if(!((S_IXUSR|S_IXGRP|S_IXOTH) & st.st_mode),
  57.             "\"%s\" is not executable", exe)
  58.  
  59.     if(st.st_size >= sizeof(shebang) &&
  60.        !memcmp(mm, shebang, sizeof(shebang))) {
  61.         const uint8_t   *nl;
  62.         int             maxlen = MIN(PATH_MAX, st.st_size - sizeof(shebang));
  63.         /* TODO(vc): EOF-terminated shebang lines are technically possible */
  64.         exit_if(!(nl = memchr(&mm[sizeof(shebang)], '\n', maxlen)),
  65.                 "Shebang line too long");
  66.         pexit_if(!(itrp = strndup((char *)&mm[sizeof(shebang)], (nl - mm) - 2)),
  67.                  "Failed to dup interpreter path");
  68.     } else if(st.st_size >= sizeof(elf) &&
  69.               !memcmp(mm, elf, sizeof(elf))) {
  70.         uint64_t        (*lget)(const uint8_t *) = NULL;
  71.         uint32_t        (*iget)(const uint8_t *) = NULL;
  72.         uint16_t        (*sget)(const uint8_t *) = NULL;
  73.         const void      *phoff = NULL, *phesz = NULL, *phecnt = NULL;
  74.         const uint8_t   *ph = NULL;
  75.         int             i, phreloff, phrelsz;
  76.  
  77.         exit_if(mm[ELF_VERSION] != 1,
  78.                 "Unsupported ELF version: %hhx", mm[ELF_VERSION]);
  79.  
  80.         /* determine which accessors to use and where */
  81.         if(mm[ELF_BITS] == ELF_BITS_32) {
  82.             if(mm[ELF_ENDIAN] == ELF_ENDIAN_LITL) {
  83.                 lget = le32_lget;
  84.                 sget = le_sget;
  85.                 iget = le_iget;
  86.             } else if(mm[ELF_ENDIAN] == ELF_ENDIAN_BIG) {
  87.                 lget = be32_lget;
  88.                 sget = be_sget;
  89.                 iget = be_iget;
  90.             }
  91.             phoff = &mm[ELF32_PHT_OFF];
  92.             phesz = &mm[ELF32_PHTE_SIZE];
  93.             phecnt = &mm[ELF32_PHTE_CNT];
  94.             phreloff = ELF32_PHE_OFF;
  95.             phrelsz = ELF32_PHE_SIZE;
  96.         } else if(mm[ELF_BITS] == ELF_BITS_64) {
  97.             if(mm[ELF_ENDIAN] == ELF_ENDIAN_LITL) {
  98.                 lget = le64_lget;
  99.                 sget = le_sget;
  100.                 iget = le_iget;
  101.             } else if(mm[ELF_ENDIAN] == ELF_ENDIAN_BIG) {
  102.                 lget = be64_lget;
  103.                 sget = be_sget;
  104.                 iget = be_iget;
  105.             }
  106.             phoff = &mm[ELF64_PHT_OFF];
  107.             phesz = &mm[ELF64_PHTE_SIZE];
  108.             phecnt = &mm[ELF64_PHTE_CNT];
  109.             phreloff = ELF64_PHE_OFF;
  110.             phrelsz = ELF64_PHE_SIZE;
  111.         }
  112.  
  113.         exit_if(!lget, "Unsupported ELF format");
  114.  
  115.         if(!phoff) /* program header may be absent, don't make it an error */
  116.             return;
  117.  
  118.         /* TODO(vc): sanity checks on values before using them */
  119.         for(ph = &mm[lget(phoff)], i = 0; i < sget(phecnt); i++, ph += sget(phesz)) {
  120.             if(iget(ph) == ELF_PT_INTERP) {
  121.                 itrp = strndup((char *)&mm[lget(&ph[phreloff])], lget(&ph[phrelsz]));
  122.                 break;
  123.             }
  124.         }
  125.     } else {
  126.         exit_if(1, "Unsupported file type");
  127.     }
  128.  
  129.     exit_if(!itrp, "Unable to determine interpreter for \"%s\"", exe);
  130.     exit_if(*itrp != '/', "Path must be absolute: \"%s\"", itrp);
  131.     exit_if(++diag_depth > MAX_DIAG_DEPTH,
  132.             "Excessive interpreter recursion, giving up");
  133.     diag(itrp);
  134. }
  135.  
downloaddiagnostic-util.c Source code - Download rkt Source code
Related Source Codes/Software:
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
postal - 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
angular-starter - 2017-06-10

 Back to top