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 }; 18ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 19ad3cb39e54040e5a03328d8006f428579d1654e0William Robertstypedef enum filemode filemode; 20ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsenum filemode { 21ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts filemode_file_contexts = 0, 22ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts filemode_property_contexts, 23ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts filemode_service_contexts 24ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts}; 25ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 26ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic struct { 27ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* policy */ 28ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts struct { 29ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts union { 30ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* Union these so we don't have to cast */ 31ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_policydb_t *sdb; 32ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts policydb_t *pdb; 33ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts }; 34ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_policy_file_t *pf; 35ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_handle_t *handle; 36ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts FILE *file; 37ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts#define SEHANDLE_CNT 2 38ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts struct selabel_handle *sehnd[SEHANDLE_CNT]; 39ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } sepolicy; 40ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 41ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* assertions */ 42ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts struct { 43ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts const char * const *attrs; /* for the original set to print on error */ 44ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts ebitmap_t set; /* the ebitmap representation of the attrs */ 45ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } assert; 46ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 47ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} global_state; 48ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 49ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic const char * const *filemode_to_assert_attrs(filemode mode) 50ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 51ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts switch (mode) { 52ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts case filemode_file_contexts: 53ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return CHECK_FC_ASSERT_ATTRS; 54ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts case filemode_property_contexts: 55ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return CHECK_PC_ASSERT_ATTRS; 56ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts case filemode_service_contexts: 57ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return CHECK_SC_ASSERT_ATTRS; 58ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 59ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* die on invalid parameters */ 60ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: Invalid mode of operation: %d\n", mode); 61ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 62ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 63ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 64ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic int get_attr_bit(policydb_t *policydb, const char *attr_name) 65ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 66ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts struct type_datum *attr = hashtab_search(policydb->p_types.table, (char *)attr_name); 67ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!attr) { 68ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: \"%s\" is not defined in this policy.\n", attr_name); 69ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return -1; 70ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 71ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 72ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (attr->flavor != TYPE_ATTRIB) { 73ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: \"%s\" is not an attribute in this policy.\n", attr_name); 74ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return -1; 75ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 76ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 77ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return attr->s.value - 1; 78ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 79ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 80ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic bool ebitmap_attribute_assertion_init(ebitmap_t *assertions, const char * const attributes[]) 81ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 82ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 83ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts while (*attributes) { 84ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 85ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int bit_pos = get_attr_bit(global_state.sepolicy.pdb, *attributes); 86ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (bit_pos < 0) { 87ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* get_attr_bit() logs error */ 88ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return false; 89ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 90ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 91ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int err = ebitmap_set_bit(assertions, bit_pos, 1); 92ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (err) { 93ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: setting bit on assertion ebitmap!\n"); 94ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return false; 95ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 96ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts attributes++; 97ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 98ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return true; 99ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 100ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 101ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic bool is_type_of_attribute_set(policydb_t *policydb, const char *type_name, 102ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts ebitmap_t *attr_set) 103ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 104ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts struct type_datum *type = hashtab_search(policydb->p_types.table, (char *)type_name); 105ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!type) { 106ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: \"%s\" is not defined in this policy.\n", type_name); 107ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return false; 108ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 109ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 110ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (type->flavor != TYPE_TYPE) { 111ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: \"%s\" is not a type in this policy.\n", type_name); 112ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return false; 113ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 114ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 115ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts ebitmap_t dst; 116ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts ebitmap_init(&dst); 117ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 118ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* Take the intersection, if the set is empty, then its a failure */ 119ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int rc = ebitmap_and(&dst, attr_set, &policydb->type_attr_map[type->s.value - 1]); 120ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (rc) { 121ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: Could not perform ebitmap_and: %d\n", rc); 122ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 123ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 124ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 125ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts bool res = (bool)ebitmap_length(&dst); 126ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 127ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts ebitmap_destroy(&dst); 128ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return res; 129ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 130ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 131ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic void dump_char_array(FILE *stream, const char * const *strings) 132ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 133ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 134ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts const char * const *p = strings; 135ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 136ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stream, "\""); 137ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 138ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts while (*p) { 139ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts const char *s = *p++; 140ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts const char *fmt = *p ? "%s, " : "%s\""; 141ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stream, fmt, s); 142ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 143ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 14401a58af19494420bb259505bc5404790a21fdd64Stephen Smalley 14501a58af19494420bb259505bc5404790a21fdd64Stephen Smalleystatic int validate(char **contextp) 14601a58af19494420bb259505bc5404790a21fdd64Stephen Smalley{ 147ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts bool res; 148ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts char *context = *contextp; 149ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 150ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_context_t *ctx; 151ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int rc = sepol_context_from_string(global_state.sepolicy.handle, context, 152ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts &ctx); 153ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (rc < 0) { 154ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: Could not allocate context from string"); 155ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 156ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 157ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 158ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts rc = sepol_context_check(global_state.sepolicy.handle, 159ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts global_state.sepolicy.sdb, ctx); 160ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (rc < 0) { 161ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts goto out; 162ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 163ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 164ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts const char *type_name = sepol_context_get_type(ctx); 165ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 166ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts uint32_t len = ebitmap_length(&global_state.assert.set); 167ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (len > 0) { 168ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts res = !is_type_of_attribute_set(global_state.sepolicy.pdb, type_name, 169ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts &global_state.assert.set); 170ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (res) { 171ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: type \"%s\" is not of set: ", type_name); 172ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts dump_char_array(stderr, global_state.assert.attrs); 173ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "\n"); 174ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* The calls above did not affect rc, so set error before going to out */ 175ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts rc = -1; 176ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts goto out; 177ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 178ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 179ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* Success: Although it should be 0, we explicitly set rc to 0 for clarity */ 180ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts rc = 0; 181ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 182ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts out: 183ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_context_free(ctx); 184ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts return rc; 18501a58af19494420bb259505bc5404790a21fdd64Stephen Smalley} 18601a58af19494420bb259505bc5404790a21fdd64Stephen Smalley 187d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craigstatic void usage(char *name) { 188922b4e95220de78f18335a79de6188dd4f4f9911William Roberts fprintf(stderr, "usage1: %s [-p|-s] [-e] sepolicy context_file\n\n" 189ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts "Parses a context file and checks for syntax errors.\n" 190ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts "The context_file is assumed to be a file_contexts file\n" 191922b4e95220de78f18335a79de6188dd4f4f9911William Roberts "unless the -p or -s option is used to indicate the property or service backend respectively.\n" 192922b4e95220de78f18335a79de6188dd4f4f9911William Roberts "If -e is specified, then the context_file is allowed to be empty.\n\n" 193ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 194ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts "usage2: %s -c file_contexts1 file_contexts2\n\n" 195ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts "Compares two file contexts files and reports one of subset, equal, superset, or incomparable.\n\n", 196ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts name, name); 197d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig exit(1); 198d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig} 199d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig 200ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic void cleanup(void) { 201ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 202ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (global_state.sepolicy.file) { 203ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fclose(global_state.sepolicy.file); 204ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 205ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 206ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (global_state.sepolicy.sdb) { 207ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_policydb_free(global_state.sepolicy.sdb); 208ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 209ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 210ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (global_state.sepolicy.pf) { 211ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_policy_file_free(global_state.sepolicy.pf); 212ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 213ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 214ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (global_state.sepolicy.handle) { 215ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_handle_destroy(global_state.sepolicy.handle); 216ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 217ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 218ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts ebitmap_destroy(&global_state.assert.set); 219ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 220ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int i; 221ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts for (i = 0; i < SEHANDLE_CNT; i++) { 222ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts struct selabel_handle *sehnd = global_state.sepolicy.sehnd[i]; 223ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (sehnd) { 224ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts selabel_close(sehnd); 225ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 226ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 227ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 228ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 229ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic void do_compare_and_die_on_error(struct selinux_opt opts[], unsigned int backend, char *paths[]) 230ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 231ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts enum selabel_cmp_result result; 232ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts char *result_str[] = { "subset", "equal", "superset", "incomparable" }; 233ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int i; 234ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 235ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts opts[0].value = NULL; /* not validating against a policy when comparing */ 236ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 237ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts for (i = 0; i < SEHANDLE_CNT; i++) { 238ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts opts[1].value = paths[i]; 239ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts global_state.sepolicy.sehnd[i] = selabel_open(backend, opts, 2); 240ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!global_state.sepolicy.sehnd[i]) { 241ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: could not load context file from %s\n", paths[i]); 242ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 243ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 244ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 245ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 246ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts result = selabel_cmp(global_state.sepolicy.sehnd[0], global_state.sepolicy.sehnd[1]); 247ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts printf("%s\n", result_str[result]); 248ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 249ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 250ad3cb39e54040e5a03328d8006f428579d1654e0William Robertsstatic void do_fc_check_and_die_on_error(struct selinux_opt opts[], unsigned int backend, filemode mode, 251922b4e95220de78f18335a79de6188dd4f4f9911William Roberts const char *sepolicy_file, const char *context_file, bool allow_empty) 252ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts{ 253922b4e95220de78f18335a79de6188dd4f4f9911William Roberts struct stat sb; 254922b4e95220de78f18335a79de6188dd4f4f9911William Roberts if (stat(context_file, &sb) < 0) { 255922b4e95220de78f18335a79de6188dd4f4f9911William Roberts perror("Error: could not get stat on file contexts file"); 256922b4e95220de78f18335a79de6188dd4f4f9911William Roberts exit(1); 257922b4e95220de78f18335a79de6188dd4f4f9911William Roberts } 258922b4e95220de78f18335a79de6188dd4f4f9911William Roberts 259922b4e95220de78f18335a79de6188dd4f4f9911William Roberts if (sb.st_size == 0) { 260922b4e95220de78f18335a79de6188dd4f4f9911William Roberts /* Nothing to check on empty file_contexts file if allowed*/ 261922b4e95220de78f18335a79de6188dd4f4f9911William Roberts if (allow_empty) { 262922b4e95220de78f18335a79de6188dd4f4f9911William Roberts return; 263922b4e95220de78f18335a79de6188dd4f4f9911William Roberts } 264922b4e95220de78f18335a79de6188dd4f4f9911William Roberts /* else: We could throw the error here, but libselinux backend will catch it */ 265922b4e95220de78f18335a79de6188dd4f4f9911William Roberts } 266922b4e95220de78f18335a79de6188dd4f4f9911William Roberts 267ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts global_state.sepolicy.file = fopen(sepolicy_file, "r"); 268ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!global_state.sepolicy.file) { 269ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts perror("Error: could not open policy file"); 270ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 271ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 272ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 273ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts global_state.sepolicy.handle = sepol_handle_create(); 274ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!global_state.sepolicy.handle) { 275ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: could not create policy handle: %s\n", strerror(errno)); 276ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 277ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 278ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 279ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (sepol_policy_file_create(&global_state.sepolicy.pf) < 0) { 280ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts perror("Error: could not create policy handle"); 281ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 282ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 283ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 284ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_policy_file_set_fp(global_state.sepolicy.pf, global_state.sepolicy.file); 285ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts sepol_policy_file_set_handle(global_state.sepolicy.pf, global_state.sepolicy.handle); 286ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 287ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts int rc = sepol_policydb_create(&global_state.sepolicy.sdb); 288ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (rc < 0) { 289ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts perror("Error: could not create policy db"); 290ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 291ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 292ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 293ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts rc = sepol_policydb_read(global_state.sepolicy.sdb, global_state.sepolicy.pf); 294ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (rc < 0) { 295ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts perror("Error: could not read file into policy db"); 296ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 297ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 298ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 299ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts global_state.assert.attrs = filemode_to_assert_attrs(mode); 300ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 301ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts bool ret = ebitmap_attribute_assertion_init(&global_state.assert.set, global_state.assert.attrs); 302ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!ret) { 303ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* error messages logged by ebitmap_attribute_assertion_init() */ 304ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 305ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 306ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 307ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts selinux_set_callback(SELINUX_CB_VALIDATE, 308ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts (union selinux_callback)&validate); 309ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 310ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts opts[1].value = context_file; 311ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 312ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts global_state.sepolicy.sehnd[0] = selabel_open(backend, opts, 2); 313ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (!global_state.sepolicy.sehnd[0]) { 314ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts fprintf(stderr, "Error: could not load context file from %s\n", context_file); 315ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts exit(1); 316ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } 317ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts} 318ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 31901a58af19494420bb259505bc5404790a21fdd64Stephen Smalleyint main(int argc, char **argv) 32001a58af19494420bb259505bc5404790a21fdd64Stephen Smalley{ 32101a58af19494420bb259505bc5404790a21fdd64Stephen Smalley struct selinux_opt opts[] = { 32201a58af19494420bb259505bc5404790a21fdd64Stephen Smalley { SELABEL_OPT_VALIDATE, (void*)1 }, 32301a58af19494420bb259505bc5404790a21fdd64Stephen Smalley { SELABEL_OPT_PATH, NULL } 32401a58af19494420bb259505bc5404790a21fdd64Stephen Smalley }; 325d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig 326d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig // Default backend unless changed by input argument. 327d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig unsigned int backend = SELABEL_CTX_FILE; 328d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig 329922b4e95220de78f18335a79de6188dd4f4f9911William Roberts bool allow_empty = false; 33013b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley bool compare = false; 331d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig char c; 33201a58af19494420bb259505bc5404790a21fdd64Stephen Smalley 333ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts filemode mode = filemode_file_contexts; 334ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts 335922b4e95220de78f18335a79de6188dd4f4f9911William Roberts while ((c = getopt(argc, argv, "cpse")) != -1) { 336d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig switch (c) { 33713b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley case 'c': 33813b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley compare = true; 33913b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley break; 340922b4e95220de78f18335a79de6188dd4f4f9911William Roberts case 'e': 341922b4e95220de78f18335a79de6188dd4f4f9911William Roberts allow_empty = true; 342922b4e95220de78f18335a79de6188dd4f4f9911William Roberts break; 343d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig case 'p': 344ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts mode = filemode_property_contexts; 345ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts backend = SELABEL_CTX_ANDROID_PROP; 346ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts break; 347ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts case 's': 348ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts mode = filemode_service_contexts; 349d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig backend = SELABEL_CTX_ANDROID_PROP; 350d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig break; 351d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig case 'h': 352d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig default: 353d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig usage(argv[0]); 354d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig break; 355d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig } 356d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig } 357d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig 358d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig int index = optind; 359d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig if (argc - optind != 2) { 360d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig usage(argv[0]); 36101a58af19494420bb259505bc5404790a21fdd64Stephen Smalley } 36201a58af19494420bb259505bc5404790a21fdd64Stephen Smalley 36313b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley if (compare && backend != SELABEL_CTX_FILE) { 36413b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley usage(argv[0]); 36513b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley } 36613b6b7e88f6ac006b53764b33348a73343742148Stephen Smalley 367ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts atexit(cleanup); 368d98d26ef3c1fe9b44497ed4e2a1fcf66505092baRobert Craig 369ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts if (compare) { 370ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts do_compare_and_die_on_error(opts, backend, &(argv[index])); 371ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts } else { 372ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts /* remaining args are sepolicy file and context file */ 373ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts char *sepolicy_file = argv[index]; 374ad3cb39e54040e5a03328d8006f428579d1654e0William Roberts char *context_file = argv[index + 1]; 37501a58af19494420bb259505bc5404790a21fdd64Stephen Smalley 376922b4e95220de78f18335a79de6188dd4f4f9911William Roberts do_fc_check_and_die_on_error(opts, backend, mode, sepolicy_file, context_file, allow_empty); 37701a58af19494420bb259505bc5404790a21fdd64Stephen Smalley } 37801a58af19494420bb259505bc5404790a21fdd64Stephen Smalley exit(0); 37901a58af19494420bb259505bc5404790a21fdd64Stephen Smalley} 380