1 /* 2 * Generalized labeling frontend for userspace object managers. 3 * 4 * Author : Eamon Walsh <ewalsh (at) epoch.ncsc.mil> 5 */ 6 7 #include <sys/types.h> 8 #include <ctype.h> 9 #include <errno.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <selinux/selinux.h> 14 #include "callbacks.h" 15 #include "label_internal.h" 16 17 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 18 19 typedef int (*selabel_initfunc)(struct selabel_handle *rec, 20 const struct selinux_opt *opts, 21 unsigned nopts); 22 23 static selabel_initfunc initfuncs[] = { 24 &selabel_file_init, 25 NULL, 26 NULL, 27 NULL, 28 &selabel_property_init, 29 }; 30 31 /* 32 * Validation functions 33 */ 34 35 static inline int selabel_is_validate_set(const struct selinux_opt *opts, 36 unsigned n) 37 { 38 while (n--) 39 if (opts[n].type == SELABEL_OPT_VALIDATE) 40 return !!opts[n].value; 41 42 return 0; 43 } 44 45 int selabel_validate(struct selabel_handle *rec, 46 struct selabel_lookup_rec *contexts) 47 { 48 int rc = 0; 49 50 if (!rec->validating || contexts->validated) 51 goto out; 52 53 rc = selinux_validate(&contexts->ctx_raw); 54 if (rc < 0) 55 goto out; 56 57 contexts->validated = 1; 58 out: 59 return rc; 60 } 61 62 /* 63 * Public API 64 */ 65 66 struct selabel_handle *selabel_open(unsigned int backend, 67 const struct selinux_opt *opts, 68 unsigned nopts) 69 { 70 struct selabel_handle *rec = NULL; 71 72 if (backend >= ARRAY_SIZE(initfuncs)) { 73 errno = EINVAL; 74 goto out; 75 } 76 77 if (initfuncs[backend] == NULL) 78 goto out; 79 80 rec = (struct selabel_handle *)malloc(sizeof(*rec)); 81 if (!rec) 82 goto out; 83 84 memset(rec, 0, sizeof(*rec)); 85 rec->backend = backend; 86 rec->validating = selabel_is_validate_set(opts, nopts); 87 88 if ((*initfuncs[backend])(rec, opts, nopts)) { 89 free(rec->spec_file); 90 free(rec); 91 rec = NULL; 92 } 93 94 out: 95 return rec; 96 } 97 98 static struct selabel_lookup_rec * 99 selabel_lookup_common(struct selabel_handle *rec, 100 const char *key, int type) 101 { 102 struct selabel_lookup_rec *lr; 103 lr = rec->func_lookup(rec, key, type); 104 if (!lr) 105 return NULL; 106 107 return lr; 108 } 109 110 int selabel_lookup(struct selabel_handle *rec, char **con, 111 const char *key, int type) 112 { 113 struct selabel_lookup_rec *lr; 114 115 lr = selabel_lookup_common(rec, key, type); 116 if (!lr) 117 return -1; 118 119 *con = strdup(lr->ctx_raw); 120 return *con ? 0 : -1; 121 } 122 123 bool selabel_partial_match(struct selabel_handle *rec, const char *key) 124 { 125 if (!rec->func_partial_match) { 126 /* 127 * If the label backend does not support partial matching, 128 * then assume a match is possible. 129 */ 130 return true; 131 } 132 return rec->func_partial_match(rec, key); 133 } 134 135 int selabel_lookup_best_match(struct selabel_handle *rec, char **con, 136 const char *key, const char **aliases, int type) 137 { 138 struct selabel_lookup_rec *lr; 139 140 if (!rec->func_lookup_best_match) { 141 errno = ENOTSUP; 142 return -1; 143 } 144 145 lr = rec->func_lookup_best_match(rec, key, aliases, type); 146 if (!lr) 147 return -1; 148 149 *con = strdup(lr->ctx_raw); 150 return *con ? 0 : -1; 151 } 152 153 enum selabel_cmp_result selabel_cmp(struct selabel_handle *h1, 154 struct selabel_handle *h2) 155 { 156 if (!h1->func_cmp || h1->func_cmp != h2->func_cmp) 157 return SELABEL_INCOMPARABLE; 158 159 return h1->func_cmp(h1, h2); 160 } 161 162 void selabel_close(struct selabel_handle *rec) 163 { 164 rec->func_close(rec); 165 free(rec->spec_file); 166 free(rec); 167 } 168 169 void selabel_stats(struct selabel_handle *rec) 170 { 171 rec->func_stats(rec); 172 } 173