/** * Compare two qpol_level_datum_t objects. * This function is meant to be passed to apol_vector_compare * as the callback for performing comparisons. * * @param datum1 Reference to a qpol_level_datum_t object * @param datum2 Reference to a qpol_level_datum_t object * @param data Reference to a policy * @return Greater than 0 if the first argument is less than the second argument, * less than 0 if the first argument is greater than the second argument, * 0 if the arguments are equal */ static int qpol_level_datum_compare(const void *datum1, const void *datum2, void *data) { const qpol_level_t *lvl_datum1 = NULL, *lvl_datum2 = NULL; apol_policy_t *policydb = NULL; qpol_policy_t *q; uint32_t val1, val2; policydb = (apol_policy_t *) data; assert(policydb); q = apol_policy_get_qpol(policydb); if (!datum1 || !datum2) goto exit_err; lvl_datum1 = datum1; lvl_datum2 = datum2; if (qpol_level_get_value(q, lvl_datum1, &val1)) goto exit_err; if (qpol_level_get_value(q, lvl_datum2, &val2)) goto exit_err; return (val1 > val2) ? 1 : ((val1 == val2) ? 0 : -1); exit_err: assert(0); return 0; }
static int mls_range_comp(const void *a, const void *b, void *data) { const apol_mls_level_t *l1 = a; const apol_mls_level_t *l2 = b; qpol_policy_t *q = (qpol_policy_t *) data; const qpol_level_t *l; uint32_t low_value, high_value; qpol_policy_get_level_by_name(q, apol_mls_level_get_sens(l1), &l); qpol_level_get_value(q, l, &low_value); qpol_policy_get_level_by_name(q, apol_mls_level_get_sens(l2), &l); qpol_level_get_value(q, l, &high_value); assert(low_value != 0 && high_value != 0); return low_value - high_value; }
apol_vector_t *apol_mls_range_get_levels(const apol_policy_t * p, const apol_mls_range_t * range) { qpol_policy_t *q = apol_policy_get_qpol(p); apol_vector_t *v = NULL, *catv = NULL; const qpol_level_t *l; uint32_t low_value, high_value, value; int error = 0; qpol_iterator_t *iter = NULL, *catiter = NULL; if (p == NULL || range == NULL || range->low == NULL) { error = EINVAL; ERR(p, "%s", strerror(error)); goto err; } apol_mls_level_t *low_level, *high_level; low_level = range->low; if (range->high == NULL) { high_level = low_level; } else { high_level = range->high; } if (qpol_policy_get_level_by_name(q, apol_mls_level_get_sens(low_level), &l) < 0 || qpol_level_get_value(q, l, &low_value) < 0) { error = errno; goto err; } if (qpol_policy_get_level_by_name(q, apol_mls_level_get_sens(high_level), &l) < 0 || qpol_level_get_value(q, l, &high_value) < 0) { error = errno; goto err; } assert(low_value <= high_value); if ((v = apol_vector_create(mls_level_free)) == NULL) { error = errno; ERR(p, "%s", strerror(error)); goto err; } if (qpol_policy_get_level_iter(q, &iter) < 0) { error = errno; goto err; } for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { const char *name; apol_mls_level_t *ml; if (qpol_iterator_get_item(iter, (void **)&l) < 0 || qpol_level_get_value(q, l, &value) < 0 || qpol_level_get_name(q, l, &name) < 0) { error = errno; goto err; } if (value < low_value || value > high_value) { continue; } if ((ml = apol_mls_level_create()) == NULL || (apol_mls_level_set_sens(p, ml, name) < 0)) { error = errno; apol_mls_level_destroy(&ml); ERR(p, "%s", strerror(error)); goto err; } if (qpol_level_get_cat_iter(q, l, &catiter) < 0 || (catv = apol_vector_create_from_iter(catiter, NULL)) == NULL) { error = errno; goto err; } const apol_vector_t *high_cats = apol_mls_level_get_cats(high_level); for (size_t i = 0; i < apol_vector_get_size(high_cats); i++) { char *cat_name = apol_vector_get_element(high_cats, i); size_t j; /* do not add categories that are not members of the level */ if (apol_vector_get_index(catv, cat_name, mls_level_name_to_cat_comp, q, &j) < 0) { /* this category is not legal under the given policy */ continue; } if (apol_mls_level_append_cats(p, ml, cat_name) < 0) { error = errno; apol_mls_level_destroy(&ml); ERR(p, "%s", strerror(error)); goto err; } } qpol_iterator_destroy(&catiter); apol_vector_destroy(&catv); if (apol_vector_append(v, ml) < 0) { error = errno; apol_mls_level_destroy(&ml); ERR(p, "%s", strerror(error)); goto err; } } apol_vector_sort(v, mls_range_comp, q); qpol_iterator_destroy(&iter); qpol_iterator_destroy(&catiter); apol_vector_destroy(&catv); return v; err: qpol_iterator_destroy(&iter); qpol_iterator_destroy(&catiter); apol_vector_destroy(&v); apol_vector_destroy(&catv); errno = error; return NULL; }