1 /* Copyright (C) 2005 Red Hat, Inc. */ 2 3 #include <stdlib.h> 4 #include "policy.h" 5 #include "handle.h" 6 #include "database.h" 7 #include "modules.h" 8 #include "debug.h" 9 10 /* Powers of two only */ 11 #define MODE_SET 1 12 #define MODE_MODIFY 2 13 #define MODE_SORT 4 14 15 static int clear_obsolete(semanage_handle_t * handle, 16 record_t ** records, 17 unsigned int nrecords, 18 dbase_config_t * src, dbase_config_t * dst) 19 { 20 21 record_key_t *key = NULL; 22 unsigned int i; 23 24 dbase_table_t *src_dtable = src->dtable; 25 dbase_table_t *dst_dtable = dst->dtable; 26 record_table_t *rtable = src_dtable->get_rtable(src->dbase); 27 28 for (i = 0; i < nrecords; i++) { 29 int exists; 30 31 if (rtable->key_extract(handle, records[i], &key) < 0) 32 goto err; 33 34 if (dst_dtable->exists(handle, dst->dbase, key, &exists) < 0) 35 goto err; 36 37 if (!exists) { 38 if (src_dtable->del(handle, src->dbase, key) < 0) 39 goto err; 40 41 rtable->free(records[i]); 42 records[i] = NULL; 43 44 /* FIXME: notice to user */ 45 /* INFO(handle, "boolean %s is obsolete, unsetting configured value..."); */ 46 } 47 48 rtable->key_free(key); 49 } 50 51 return STATUS_SUCCESS; 52 53 err: 54 /* FIXME: handle error */ 55 rtable->key_free(key); 56 return STATUS_ERR; 57 } 58 59 static int load_records(semanage_handle_t * handle, 60 dbase_config_t * dst, 61 record_t ** records, unsigned int nrecords, int mode) 62 { 63 64 unsigned int i; 65 record_key_t *rkey = NULL; 66 67 dbase_t *dbase = dst->dbase; 68 dbase_table_t *dtable = dst->dtable; 69 record_table_t *rtable = dtable->get_rtable(dbase); 70 71 for (i = 0; i < nrecords; i++) { 72 73 /* Possibly obsoleted */ 74 if (!records[i]) 75 continue; 76 77 if (rtable->key_extract(handle, records[i], &rkey) < 0) 78 goto err; 79 80 if (mode & MODE_SET && 81 dtable->set(handle, dbase, rkey, records[i]) < 0) 82 goto err; 83 84 else if (mode & MODE_MODIFY && 85 dtable->modify(handle, dbase, rkey, records[i]) < 0) 86 goto err; 87 88 rtable->key_free(rkey); 89 } 90 91 return STATUS_SUCCESS; 92 93 err: 94 /* FIXME: handle error */ 95 rtable->key_free(rkey); 96 return STATUS_ERR; 97 } 98 99 typedef struct load_table { 100 dbase_config_t *src; 101 dbase_config_t *dst; 102 int mode; 103 } load_table_t; 104 105 /* This function must be called AFTER all modules are loaded. 106 * Modules could be represented as a database, in which case 107 * they should be loaded at the beginning of this function */ 108 109 int semanage_base_merge_components(semanage_handle_t * handle) 110 { 111 112 unsigned int i, j; 113 int rc = STATUS_SUCCESS; 114 115 /* Order is important here - change things carefully. 116 * System components first, local next. Verify runs with 117 * mutual dependencies are ran after everything is merged */ 118 load_table_t components[] = { 119 120 {semanage_user_base_dbase_local(handle), 121 semanage_user_base_dbase_policy(handle), MODE_MODIFY}, 122 123 {semanage_user_extra_dbase_local(handle), 124 semanage_user_extra_dbase_policy(handle), MODE_MODIFY}, 125 126 {semanage_port_dbase_local(handle), 127 semanage_port_dbase_policy(handle), MODE_MODIFY}, 128 129 {semanage_iface_dbase_local(handle), 130 semanage_iface_dbase_policy(handle), MODE_MODIFY}, 131 132 {semanage_bool_dbase_local(handle), 133 semanage_bool_dbase_policy(handle), MODE_SET}, 134 135 {semanage_seuser_dbase_local(handle), 136 semanage_seuser_dbase_policy(handle), MODE_MODIFY}, 137 138 {semanage_node_dbase_local(handle), 139 semanage_node_dbase_policy(handle), MODE_MODIFY | MODE_SORT}, 140 }; 141 const unsigned int CCOUNT = sizeof(components) / sizeof(components[0]); 142 143 /* Merge components into policy (and validate) */ 144 for (i = 0; i < CCOUNT; i++) { 145 146 record_t **records = NULL; 147 unsigned int nrecords = 0; 148 149 dbase_config_t *src = components[i].src; 150 dbase_config_t *dst = components[i].dst; 151 int mode = components[i].mode; 152 record_table_t *rtable = src->dtable->get_rtable(src->dbase); 153 154 /* Must invoke cache function first */ 155 if (src->dtable->cache(handle, src->dbase) < 0) 156 goto err; 157 if (dst->dtable->cache(handle, dst->dbase) < 0) 158 goto err; 159 160 /* List all records */ 161 if (src->dtable->list(handle, src->dbase, 162 &records, &nrecords) < 0) 163 goto err; 164 165 /* Sort records on MODE_SORT */ 166 if (mode & MODE_SORT) { 167 qsort(records, nrecords, sizeof(record_t *), 168 (int (*)(const void *, const void *))rtable-> 169 compare2_qsort); 170 } 171 172 /* Clear obsolete ones for MODE_SET */ 173 if (mode & MODE_SET && 174 clear_obsolete(handle, records, nrecords, src, dst) < 0) { 175 rc = STATUS_ERR; 176 goto dbase_exit; 177 } 178 179 /* Load records */ 180 if (load_records(handle, dst, records, nrecords, mode) < 0) { 181 182 rc = STATUS_ERR; 183 goto dbase_exit; 184 } 185 186 /* Cleanup */ 187 dbase_exit: 188 for (j = 0; j < nrecords; j++) 189 rtable->free(records[j]); 190 free(records); 191 192 /* Abort on error */ 193 if (rc < 0) 194 goto err; 195 } 196 197 return rc; 198 199 err: 200 ERR(handle, "could not merge local modifications into policy"); 201 return STATUS_ERR; 202 } 203 204 int semanage_commit_components(semanage_handle_t * handle) 205 { 206 207 int i; 208 dbase_config_t *components[] = { 209 semanage_iface_dbase_local(handle), 210 semanage_bool_dbase_local(handle), 211 semanage_user_base_dbase_local(handle), 212 semanage_user_extra_dbase_local(handle), 213 semanage_user_extra_dbase_policy(handle), 214 semanage_port_dbase_local(handle), 215 semanage_fcontext_dbase_local(handle), 216 semanage_fcontext_dbase_policy(handle), 217 semanage_seuser_dbase_local(handle), 218 semanage_seuser_dbase_policy(handle), 219 semanage_bool_dbase_active(handle), 220 semanage_node_dbase_local(handle), 221 }; 222 const int CCOUNT = sizeof(components) / sizeof(components[0]); 223 224 for (i = 0; i < CCOUNT; i++) { 225 /* Flush to disk */ 226 if (components[i]->dtable->flush(handle, components[i]->dbase) < 227 0) 228 goto err; 229 } 230 231 return STATUS_SUCCESS; 232 233 err: 234 ERR(handle, "could not commit local/active modifications"); 235 236 for (i = 0; i < CCOUNT; i++) 237 components[i]->dtable->drop_cache(components[i]->dbase); 238 return STATUS_ERR; 239 } 240