github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/make/tools/fs_config/fs_config.c (about)

     1  /*
     2   * Copyright (C) 2008 The Android Open Source Project
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *      http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  #include <stdio.h>
    18  #include <stdlib.h>
    19  #include <sys/stat.h>
    20  #include <errno.h>
    21  #include <unistd.h>
    22  #include <string.h>
    23  #include <inttypes.h>
    24  
    25  #include <selinux/selinux.h>
    26  #include <selinux/label.h>
    27  
    28  #include "private/android_filesystem_config.h"
    29  
    30  // This program takes a list of files and directories (indicated by a
    31  // trailing slash) on the stdin, and prints to stdout each input
    32  // filename along with its desired uid, gid, and mode (in octal).
    33  // The leading slash should be stripped from the input.
    34  //
    35  // After the first 4 columns, optional key=value pairs are emitted
    36  // for each file.  Currently, the following keys are supported:
    37  // * -S: selabel=[selinux_label]
    38  // * -C: capabilities=[hex capabilities value]
    39  //
    40  // Example input:
    41  //
    42  //      system/etc/dbus.conf
    43  //      data/app/
    44  //
    45  // Output:
    46  //
    47  //      system/etc/dbus.conf 1002 1002 440
    48  //      data/app 1000 1000 771
    49  //
    50  //   or if, for example, -S is used:
    51  //
    52  //      system/etc/dbus.conf 1002 1002 440 selabel=u:object_r:system_file:s0
    53  //      data/app 1000 1000 771 selabel=u:object_r:apk_data_file:s0
    54  //
    55  // Note that the output will omit the trailing slash from
    56  // directories.
    57  
    58  static struct selabel_handle* get_sehnd(const char* context_file) {
    59    struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, context_file } };
    60    struct selabel_handle* sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1);
    61  
    62    if (!sehnd) {
    63      perror("error running selabel_open");
    64      exit(EXIT_FAILURE);
    65    }
    66    return sehnd;
    67  }
    68  
    69  static void usage() {
    70    fprintf(stderr, "Usage: fs_config [-D product_out_path] [-S context_file] [-R root] [-C]\n");
    71  }
    72  
    73  int main(int argc, char** argv) {
    74    char buffer[1024];
    75    const char* context_file = NULL;
    76    const char* product_out_path = NULL;
    77    char* root_path = NULL;
    78    struct selabel_handle* sehnd = NULL;
    79    int print_capabilities = 0;
    80    int opt;
    81    while((opt = getopt(argc, argv, "CS:R:D:")) != -1) {
    82      switch(opt) {
    83      case 'C':
    84        print_capabilities = 1;
    85        break;
    86      case 'S':
    87        context_file = optarg;
    88        break;
    89      case 'R':
    90        root_path = optarg;
    91        break;
    92      case 'D':
    93        product_out_path = optarg;
    94        break;
    95      default:
    96        usage();
    97        exit(EXIT_FAILURE);
    98      }
    99    }
   100  
   101    if (context_file != NULL) {
   102      sehnd = get_sehnd(context_file);
   103    }
   104  
   105    if (root_path != NULL) {
   106      size_t root_len = strlen(root_path);
   107      /* Trim any trailing slashes from the root path. */
   108      while (root_len && root_path[--root_len] == '/') {
   109        root_path[root_len] = '\0';
   110      }
   111    }
   112  
   113    while (fgets(buffer, 1023, stdin) != NULL) {
   114      int is_dir = 0;
   115      int i;
   116      for (i = 0; i < 1024 && buffer[i]; ++i) {
   117        switch (buffer[i]) {
   118          case '\n':
   119            buffer[i-is_dir] = '\0';
   120            if (i == 0) {
   121              is_dir = 1; // empty line is considered as root directory
   122            }
   123            i = 1025;
   124            break;
   125          case '/':
   126            is_dir = 1;
   127            break;
   128          default:
   129            is_dir = 0;
   130            break;
   131        }
   132      }
   133  
   134      unsigned uid = 0, gid = 0, mode = 0;
   135      uint64_t capabilities;
   136      fs_config(buffer, is_dir, product_out_path, &uid, &gid, &mode, &capabilities);
   137      if (root_path != NULL && strcmp(buffer, root_path) == 0) {
   138        /* The root of the filesystem needs to be an empty string. */
   139        strcpy(buffer, "");
   140      }
   141      printf("%s %d %d %o", buffer, uid, gid, mode);
   142  
   143      if (sehnd != NULL) {
   144        size_t buffer_strlen = strnlen(buffer, sizeof(buffer));
   145        if (buffer_strlen >= sizeof(buffer)) {
   146          fprintf(stderr, "non null terminated buffer, aborting\n");
   147          exit(EXIT_FAILURE);
   148        }
   149        size_t full_name_size = buffer_strlen + 2;
   150        char* full_name = (char*) malloc(full_name_size);
   151        if (full_name == NULL) {
   152          perror("malloc");
   153          exit(EXIT_FAILURE);
   154        }
   155  
   156        full_name[0] = '/';
   157        strncpy(full_name + 1, buffer, full_name_size - 1);
   158        full_name[full_name_size - 1] = '\0';
   159  
   160        char* secontext;
   161        if (selabel_lookup(sehnd, &secontext, full_name, ( mode | (is_dir ? S_IFDIR : S_IFREG)))) {
   162          secontext = strdup("u:object_r:unlabeled:s0");
   163        }
   164  
   165        printf(" selabel=%s", secontext);
   166        free(full_name);
   167        freecon(secontext);
   168      }
   169  
   170      if (print_capabilities) {
   171        printf(" capabilities=0x%" PRIx64, capabilities);
   172      }
   173  
   174      printf("\n");
   175    }
   176    return 0;
   177  }