1d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig#include <getopt.h> 2ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts#include <stdbool.h> 301a58af19494420bb259505bc5404790a21fdd64Stephen Smalley#include <stdio.h> 401a58af19494420bb259505bc5404790a21fdd64Stephen Smalley#include <stdlib.h> 5ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts#include <string.h> 6922b4e95220de78f18335a79de6188dd4f4f9911William Roberts#include <unistd.h> 7ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts#include <sepol/module.h> 8ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts#include <sepol/policydb/policydb.h> 901a58af19494420bb259505bc5404790a21fdd64Stephen Smalley#include <sepol/sepol.h> 1001a58af19494420bb259505bc5404790a21fdd64Stephen Smalley#include <selinux/selinux.h> 1101a58af19494420bb259505bc5404790a21fdd64Stephen Smalley#include <selinux/label.h> 12922b4e95220de78f18335a79de6188dd4f4f9911William Roberts#include <sys/stat.h> 13922b4e95220de78f18335a79de6188dd4f4f9911William Roberts#include <sys/types.h> 1401a58af19494420bb259505bc5404790a21fdd64Stephen Smalley 15ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic const char * const CHECK_FC_ASSERT_ATTRS[] = { "fs_type", "dev_type", "file_type", NULL }; 16ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic const char * const CHECK_PC_ASSERT_ATTRS[] = { "property_type", NULL }; 17ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic const char * const CHECK_SC_ASSERT_ATTRS[] = { "service_manager_type", NULL }; 18d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenenstatic const char * const CHECK_HW_SC_ASSERT_ATTRS[] = { "hwservice_manager_type", NULL }; 19d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenenstatic const char * const CHECK_VND_SC_ASSERT_ATTRS[] = { "vndservice_manager_type", NULL }; 20ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 21ad3cb39e54040e5a03328d8006f428579d1654e0William Robertstypedef enum filemode filemode; 22ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsenum filemode { 23ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts filemode_file_contexts = 0, 24ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts filemode_property_contexts, 25d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen filemode_service_contexts, 26d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen filemode_hw_service_contexts, 27d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen filemode_vendor_service_contexts 28ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts}; 29ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 30ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic struct { 31ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* policy */ 32ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts struct { 33ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts union { 34ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* Union these so we don't have to cast */ 35ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_policydb_t *sdb; 36ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts policydb_t *pdb; 37ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts }; 38ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_policy_file_t *pf; 39ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_handle_t *handle; 40ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts FILE *file; 41ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts#define SEHANDLE_CNT 2 42ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts struct selabel_handle *sehnd[SEHANDLE_CNT]; 43ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } sepolicy; 44ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 45ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* assertions */ 46ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts struct { 47ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts const char * const *attrs; /* for the original set to print on error */ 48ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts ebitmap_t set; /* the ebitmap representation of the attrs */ 49ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } assert; 50ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 51ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} global_state; 52ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 53ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic const char * const *filemode_to_assert_attrs(filemode mode) 54ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 55ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts switch (mode) { 56ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts case filemode_file_contexts: 57ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return CHECK_FC_ASSERT_ATTRS; 58ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts case filemode_property_contexts: 59ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return CHECK_PC_ASSERT_ATTRS; 60ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts case filemode_service_contexts: 61ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return CHECK_SC_ASSERT_ATTRS; 62d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen case filemode_hw_service_contexts: 63d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen return CHECK_HW_SC_ASSERT_ATTRS; 64d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen case filemode_vendor_service_contexts: 65d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen return CHECK_VND_SC_ASSERT_ATTRS; 66ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 67ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* die on invalid parameters */ 68ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: Invalid mode of operation: %d\n", mode); 69ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 70ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 71ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 72ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic int get_attr_bit(policydb_t *policydb, const char *attr_name) 73ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 74ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts struct type_datum *attr = hashtab_search(policydb->p_types.table, (char *)attr_name); 75ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!attr) { 76ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: \"%s\" is not defined in this policy.\n", attr_name); 77ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return -1; 78ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 79ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 80ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (attr->flavor != TYPE_ATTRIB) { 81ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: \"%s\" is not an attribute in this policy.\n", attr_name); 82ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return -1; 83ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 84ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 85ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return attr->s.value - 1; 86ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 87ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 88ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic bool ebitmap_attribute_assertion_init(ebitmap_t *assertions, const char * const attributes[]) 89ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 90ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 91ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts while (*attributes) { 92ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 93ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int bit_pos = get_attr_bit(global_state.sepolicy.pdb, *attributes); 94ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (bit_pos < 0) { 95ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* get_attr_bit() logs error */ 96ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return false; 97ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 98ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 99ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int err = ebitmap_set_bit(assertions, bit_pos, 1); 100ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (err) { 101ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: setting bit on assertion ebitmap!\n"); 102ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return false; 103ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 104ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts attributes++; 105ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 106ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return true; 107ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 108ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 109ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic bool is_type_of_attribute_set(policydb_t *policydb, const char *type_name, 110ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts ebitmap_t *attr_set) 111ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 112ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts struct type_datum *type = hashtab_search(policydb->p_types.table, (char *)type_name); 113ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!type) { 114ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: \"%s\" is not defined in this policy.\n", type_name); 115ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return false; 116ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 117ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 118ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (type->flavor != TYPE_TYPE) { 119ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: \"%s\" is not a type in this policy.\n", type_name); 120ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return false; 121ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 122ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 123ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts ebitmap_t dst; 124ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts ebitmap_init(&dst); 125ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 126ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* Take the intersection, if the set is empty, then its a failure */ 127ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int rc = ebitmap_and(&dst, attr_set, &policydb->type_attr_map[type->s.value - 1]); 128ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (rc) { 129ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: Could not perform ebitmap_and: %d\n", rc); 130ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 131ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 132ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 133ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts bool res = (bool)ebitmap_length(&dst); 134ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 135ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts ebitmap_destroy(&dst); 136ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return res; 137ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 138ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 139ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic void dump_char_array(FILE *stream, const char * const *strings) 140ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 141ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 142ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts const char * const *p = strings; 143ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 144ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stream, "\""); 145ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 146ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts while (*p) { 147ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts const char *s = *p++; 148ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts const char *fmt = *p ? "%s, " : "%s\""; 149ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stream, fmt, s); 150ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 151ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 15201a58af19494420bb259505bc5404790a21fdd64Stephen Smalley 15301a58af19494420bb259505bc5404790a21fdd64Stephen Smalleystatic int validate(char **contextp) 15401a58af19494420bb259505bc5404790a21fdd64Stephen Smalley{ 155ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts bool res; 156ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts char *context = *contextp; 157ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 158ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_context_t *ctx; 159ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int rc = sepol_context_from_string(global_state.sepolicy.handle, context, 160ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts &ctx); 161ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (rc < 0) { 162ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: Could not allocate context from string"); 163ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 164ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 165ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 166ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts rc = sepol_context_check(global_state.sepolicy.handle, 167ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts global_state.sepolicy.sdb, ctx); 168ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (rc < 0) { 169ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts goto out; 170ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 171ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 172ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts const char *type_name = sepol_context_get_type(ctx); 173ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 174ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts uint32_t len = ebitmap_length(&global_state.assert.set); 175ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (len > 0) { 176ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts res = !is_type_of_attribute_set(global_state.sepolicy.pdb, type_name, 177ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts &global_state.assert.set); 178ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (res) { 179ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: type \"%s\" is not of set: ", type_name); 180ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts dump_char_array(stderr, global_state.assert.attrs); 181ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "\n"); 182ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* The calls above did not affect rc, so set error before going to out */ 183ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts rc = -1; 184ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts goto out; 185ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 186ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 187ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* Success: Although it should be 0, we explicitly set rc to 0 for clarity */ 188ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts rc = 0; 189ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 190ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts out: 191ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_context_free(ctx); 192ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return rc; 19301a58af19494420bb259505bc5404790a21fdd64Stephen Smalley} 19401a58af19494420bb259505bc5404790a21fdd64Stephen Smalley 195d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craigstatic void usage(char *name) { 196d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen fprintf(stderr, "usage1: %s [-l|-p|-s|-v] [-e] sepolicy context_file\n\n" 197ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts "Parses a context file and checks for syntax errors.\n" 198d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen "If -p is specified, the property backend is used.\n" 199d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen "If -s is specified, the service backend is used to verify binder services.\n" 200d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen "If -l is specified, the service backend is used to verify hwbinder services.\n" 201d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen "If -v is specified, the service backend is used to verify vndbinder services.\n" 202d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen "Otherwise, context_file is assumed to be a file_contexts file\n" 203922b4e95220de78f18335a79de6188dd4f4f9911William Roberts "If -e is specified, then the context_file is allowed to be empty.\n\n" 204ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 205ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts "usage2: %s -c file_contexts1 file_contexts2\n\n" 206ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts "Compares two file contexts files and reports one of subset, equal, superset, or incomparable.\n\n", 207ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts name, name); 208d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig exit(1); 209d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig} 210d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig 211ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic void cleanup(void) { 212ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 213ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (global_state.sepolicy.file) { 214ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fclose(global_state.sepolicy.file); 215ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 216ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 217ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (global_state.sepolicy.sdb) { 218ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_policydb_free(global_state.sepolicy.sdb); 219ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 220ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 221ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (global_state.sepolicy.pf) { 222ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_policy_file_free(global_state.sepolicy.pf); 223ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 224ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 225ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (global_state.sepolicy.handle) { 226ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_handle_destroy(global_state.sepolicy.handle); 227ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 228ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 229ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts ebitmap_destroy(&global_state.assert.set); 230ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 231ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int i; 232ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts for (i = 0; i < SEHANDLE_CNT; i++) { 233ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts struct selabel_handle *sehnd = global_state.sepolicy.sehnd[i]; 234ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (sehnd) { 235ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts selabel_close(sehnd); 236ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 237ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 238ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 239ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 240ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic void do_compare_and_die_on_error(struct selinux_opt opts[], unsigned int backend, char *paths[]) 241ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 242ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts enum selabel_cmp_result result; 243ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts char *result_str[] = { "subset", "equal", "superset", "incomparable" }; 244ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int i; 245ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 246ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts opts[0].value = NULL; /* not validating against a policy when comparing */ 247ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 248ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts for (i = 0; i < SEHANDLE_CNT; i++) { 249ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts opts[1].value = paths[i]; 250ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts global_state.sepolicy.sehnd[i] = selabel_open(backend, opts, 2); 251ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!global_state.sepolicy.sehnd[i]) { 252ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: could not load context file from %s\n", paths[i]); 253ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 254ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 255ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 256ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 257ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts result = selabel_cmp(global_state.sepolicy.sehnd[0], global_state.sepolicy.sehnd[1]); 258ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts printf("%s\n", result_str[result]); 259ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 260ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 261ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic void do_fc_check_and_die_on_error(struct selinux_opt opts[], unsigned int backend, filemode mode, 262922b4e95220de78f18335a79de6188dd4f4f9911William Roberts const char *sepolicy_file, const char *context_file, bool allow_empty) 263ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 264922b4e95220de78f18335a79de6188dd4f4f9911William Roberts struct stat sb; 265922b4e95220de78f18335a79de6188dd4f4f9911William Roberts if (stat(context_file, &sb) < 0) { 266922b4e95220de78f18335a79de6188dd4f4f9911William Roberts perror("Error: could not get stat on file contexts file"); 267922b4e95220de78f18335a79de6188dd4f4f9911William Roberts exit(1); 268922b4e95220de78f18335a79de6188dd4f4f9911William Roberts } 269922b4e95220de78f18335a79de6188dd4f4f9911William Roberts 270922b4e95220de78f18335a79de6188dd4f4f9911William Roberts if (sb.st_size == 0) { 271922b4e95220de78f18335a79de6188dd4f4f9911William Roberts /* Nothing to check on empty file_contexts file if allowed*/ 272922b4e95220de78f18335a79de6188dd4f4f9911William Roberts if (allow_empty) { 273922b4e95220de78f18335a79de6188dd4f4f9911William Roberts return; 274922b4e95220de78f18335a79de6188dd4f4f9911William Roberts } 275922b4e95220de78f18335a79de6188dd4f4f9911William Roberts /* else: We could throw the error here, but libselinux backend will catch it */ 276922b4e95220de78f18335a79de6188dd4f4f9911William Roberts } 277922b4e95220de78f18335a79de6188dd4f4f9911William Roberts 278ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts global_state.sepolicy.file = fopen(sepolicy_file, "r"); 279ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!global_state.sepolicy.file) { 280ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts perror("Error: could not open policy file"); 281ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 282ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 283ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 284ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts global_state.sepolicy.handle = sepol_handle_create(); 285ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!global_state.sepolicy.handle) { 286ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: could not create policy handle: %s\n", strerror(errno)); 287ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 288ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 289ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 290ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (sepol_policy_file_create(&global_state.sepolicy.pf) < 0) { 291ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts perror("Error: could not create policy handle"); 292ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 293ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 294ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 295ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_policy_file_set_fp(global_state.sepolicy.pf, global_state.sepolicy.file); 296ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_policy_file_set_handle(global_state.sepolicy.pf, global_state.sepolicy.handle); 297ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 298ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int rc = sepol_policydb_create(&global_state.sepolicy.sdb); 299ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (rc < 0) { 300ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts perror("Error: could not create policy db"); 301ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 302ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 303ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 304ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts rc = sepol_policydb_read(global_state.sepolicy.sdb, global_state.sepolicy.pf); 305ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (rc < 0) { 306ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts perror("Error: could not read file into policy db"); 307ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 308ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 309ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 310ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts global_state.assert.attrs = filemode_to_assert_attrs(mode); 311ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 312ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts bool ret = ebitmap_attribute_assertion_init(&global_state.assert.set, global_state.assert.attrs); 313ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!ret) { 314ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* error messages logged by ebitmap_attribute_assertion_init() */ 315ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 316ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 317ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 318ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts selinux_set_callback(SELINUX_CB_VALIDATE, 319ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts (union selinux_callback)&validate); 320ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 321ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts opts[1].value = context_file; 322ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 323ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts global_state.sepolicy.sehnd[0] = selabel_open(backend, opts, 2); 324ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!global_state.sepolicy.sehnd[0]) { 325ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: could not load context file from %s\n", context_file); 326ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 327ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 328ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 329ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 33001a58af19494420bb259505bc5404790a21fdd64Stephen Smalleyint main(int argc, char **argv) 33101a58af19494420bb259505bc5404790a21fdd64Stephen Smalley{ 33201a58af19494420bb259505bc5404790a21fdd64Stephen Smalley struct selinux_opt opts[] = { 33301a58af19494420bb259505bc5404790a21fdd64Stephen Smalley { SELABEL_OPT_VALIDATE, (void*)1 }, 33401a58af19494420bb259505bc5404790a21fdd64Stephen Smalley { SELABEL_OPT_PATH, NULL } 33501a58af19494420bb259505bc5404790a21fdd64Stephen Smalley }; 336d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig 337d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig // Default backend unless changed by input argument. 338d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig unsigned int backend = SELABEL_CTX_FILE; 339d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig 340922b4e95220de78f18335a79de6188dd4f4f9911William Roberts bool allow_empty = false; 34113b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley bool compare = false; 342d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig char c; 34301a58af19494420bb259505bc5404790a21fdd64Stephen Smalley 344ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts filemode mode = filemode_file_contexts; 345ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 346d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen while ((c = getopt(argc, argv, "clpsve")) != -1) { 347d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig switch (c) { 34813b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley case 'c': 34913b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley compare = true; 35013b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley break; 351922b4e95220de78f18335a79de6188dd4f4f9911William Roberts case 'e': 352922b4e95220de78f18335a79de6188dd4f4f9911William Roberts allow_empty = true; 353922b4e95220de78f18335a79de6188dd4f4f9911William Roberts break; 354d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig case 'p': 355ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts mode = filemode_property_contexts; 356ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts backend = SELABEL_CTX_ANDROID_PROP; 357ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts break; 358ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts case 's': 359ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts mode = filemode_service_contexts; 3603e4632943de29dc99a239a99da9b45527c8d9ae9Janis Danisevskis backend = SELABEL_CTX_ANDROID_SERVICE; 361d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig break; 362d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen case 'l': 363d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen mode = filemode_hw_service_contexts; 364d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen backend = SELABEL_CTX_ANDROID_SERVICE; 365d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen break; 366d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen case 'v': 367d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen mode = filemode_vendor_service_contexts; 368d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen backend = SELABEL_CTX_ANDROID_SERVICE; 369d48d54a3a103a001301c9decc4ba3a09cb9c2d12Martijn Coenen break; 370d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig case 'h': 371d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig default: 372d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig usage(argv[0]); 373d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig break; 374d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig } 375d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig } 376d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig 377d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig int index = optind; 378d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig if (argc - optind != 2) { 379d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig usage(argv[0]); 38001a58af19494420bb259505bc5404790a21fdd64Stephen Smalley } 38101a58af19494420bb259505bc5404790a21fdd64Stephen Smalley 38213b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley if (compare && backend != SELABEL_CTX_FILE) { 38313b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley usage(argv[0]); 38413b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley } 38513b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley 386ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts atexit(cleanup); 387d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig 388ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (compare) { 389ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts do_compare_and_die_on_error(opts, backend, &(argv[index])); 390ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } else { 391ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* remaining args are sepolicy file and context file */ 392ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts char *sepolicy_file = argv[index]; 393ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts char *context_file = argv[index + 1]; 39401a58af19494420bb259505bc5404790a21fdd64Stephen Smalley 395922b4e95220de78f18335a79de6188dd4f4f9911William Roberts do_fc_check_and_die_on_error(opts, backend, mode, sepolicy_file, context_file, allow_empty); 39601a58af19494420bb259505bc5404790a21fdd64Stephen Smalley } 39701a58af19494420bb259505bc5404790a21fdd64Stephen Smalley exit(0); 39801a58af19494420bb259505bc5404790a21fdd64Stephen Smalley} 399