diff --git a/0006-Changes-to-support-named-file_trans-rules.patch b/0006-Changes-to-support-named-file_trans-rules.patch new file mode 100644 index 0000000..39dbf4a --- /dev/null +++ b/0006-Changes-to-support-named-file_trans-rules.patch @@ -0,0 +1,1491 @@ +From 287f507657e162bc09b5c186bbd580901fbc942a Mon Sep 17 00:00:00 2001 +From: Dan Walsh +Date: Tue, 20 Sep 2011 15:47:28 -0400 +Subject: [PATCH 6/6] Changes to support named file_trans rules + +--- + libapol/include/apol/ftrule-query.h | 198 +++++++++++++++++++ + libapol/include/apol/policy-query.h | 1 + + libapol/src/Makefile.am | 1 + + libapol/src/ftrule-query.c | 363 +++++++++++++++++++++++++++++++++++ + libapol/src/libapol.map | 1 + + libqpol/include/qpol/ftrule_query.h | 116 +++++++++++ + libqpol/include/qpol/policy.h | 1 + + libqpol/src/Makefile.am | 1 + + libqpol/src/ftrule_query.c | 277 ++++++++++++++++++++++++++ + libqpol/src/libqpol.map | 1 + + libqpol/src/module_compiler.c | 12 ++ + libqpol/src/policy_define.c | 186 ++++++++++++++++++- + libqpol/src/policy_parse.y | 13 +- + libqpol/src/policy_scan.l | 1 + + secmds/sesearch.c | 101 ++++++++++ + 15 files changed, 1270 insertions(+), 3 deletions(-) + create mode 100644 libapol/include/apol/ftrule-query.h + create mode 100644 libapol/src/ftrule-query.c + create mode 100644 libqpol/include/qpol/ftrule_query.h + create mode 100644 libqpol/src/ftrule_query.c + +Index: setools-3.3.7/libapol/include/apol/ftrule-query.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ setools-3.3.7/libapol/include/apol/ftrule-query.h 2013-04-03 20:03:20.687277526 +0200 +@@ -0,0 +1,198 @@ ++/** ++ * @file ++ * ++ * Routines to query filename_transition rules of a ++ * policy. ++ * ++ * @author Jeremy A. Mowery jmowery@tresys.com ++ * @author Jason Tang jtang@tresys.com ++ * ++ * Copyright (C) 2006-2007 Tresys Technology, LLC ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef APOL_FILENAMERULE_QUERY_H ++#define APOL_FILENAMERULE_QUERY_H ++ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif ++ ++#include "policy.h" ++#include "vector.h" ++#include ++ ++ typedef struct apol_filename_trans_query apol_filename_trans_query_t; ++ ++ ++/******************** filename_transition queries ********************/ ++ ++/** ++ * Execute a query against all filename_transition rules within the ++ * policy. ++ * ++ * @param p Policy within which to look up filename_transition rules. ++ * @param r Structure containing parameters for query. If this is ++ * NULL then return all filename_transition rules. ++ * @param v Reference to a vector of qpol_filename_trans_t. The vector ++ * will be allocated by this function. The caller must call ++ * apol_vector_destroy() afterwards. This will be set to NULL upon no ++ * results or upon error. ++ * ++ * @return 0 on success (including none found), negative on error. ++ */ ++ extern int apol_filename_trans_get_by_query(const apol_policy_t * p, const apol_filename_trans_query_t * r, apol_vector_t ** v); ++ ++/** ++ * Allocate and return a new filename trans query structure. All fields ++ * are initialized, such that running this blank query results in ++ * returning all filename_transitions within the policy. The caller must ++ * call apol_filename_trans_query_destroy() upon the return value ++ * afterwards. ++ * ++ * @return An initialized filename trans query structure, or NULL upon ++ * error. ++ */ ++ extern apol_filename_trans_query_t *apol_filename_trans_query_create(void); ++ ++/** ++ * Deallocate all memory associated with the referenced filename trans ++ * query, and then set it to NULL. This function does nothing if the ++ * query is already NULL. ++ * ++ * @param r Reference to a filename trans query structure to destroy. ++ */ ++ extern void apol_filename_trans_query_destroy(apol_filename_trans_query_t ** r); ++ ++/** ++ * Set a filename_trans query to return rules whose source symbol matches ++ * symbol. Symbol may be a type or attribute; if it is an alias then ++ * the query will convert it to its primary prior to searching. If ++ * is_indirect is non-zero then the search will be done indirectly. ++ * If the symbol is a type, then the query matches rules with one of ++ * the type's attributes. If the symbol is an attribute, then it ++ * matches rule with any of the attribute's types. ++ * ++ * @param p Policy handler, to report errors. ++ * @param t TE rule query to set. ++ * @param symbol Limit query to rules with this symbol as their ++ * source, or NULL to unset this field. ++ * @param is_indirect If non-zero, perform indirect matching. ++ * ++ * @return 0 on success, negative on error. ++ */ ++ extern int apol_filename_trans_query_set_source(const apol_policy_t * p, apol_filename_trans_query_t * t, const char *symbol, ++ int is_indirect); ++ ++/** ++ * Set a filename trans query to return rules with a particular target ++ * symbol. Symbol may be a type or attribute; if it is an alias then ++ * the query will convert it to its primary prior to searching. If ++ * is_indirect is non-zero then the search will be done indirectly. ++ * If the symbol is a type, then the query matches rules with one of ++ * the type's attributes. If the symbol is an attribute, then it ++ * matches rule with any of the attribute's types. ++ * ++ * @param p Policy handler, to report errors. ++ * @param r Role trans query to set. ++ * @param symbol Limit query to rules with this type or attribute as ++ * their target, or NULL to unset this field. ++ * @param is_indirect If non-zero, perform indirect matching. ++ * ++ * @return 0 on success, negative on error. ++ */ ++ extern int apol_filename_trans_query_set_target(const apol_policy_t * p, apol_filename_trans_query_t * r, const char *symbol, ++ int is_indirect); ++ ++/** ++ * Set a filename trans query to return rules with a particular default ++ * filename. This field is ignored if ++ * apol_filename_trans_query_set_source_any() is set to non-zero. ++ * ++ * @param p Policy handler, to report errors. ++ * @param r Role trans query to set. ++ * @param filename Limit query to rules with this filename as their default, or ++ * NULL to unset this field. ++ * ++ * @return 0 on success, negative on error. ++ */ ++ extern int apol_filename_trans_query_set_default(const apol_policy_t * p, apol_filename_trans_query_t * r, const char *filename); ++ ++/** ++ * Set at filename_trans query to return rules with this object (non-common) ++ * class. If more than one class are appended to the query, the ++ * rule's class must be one of those appended. (I.e., the rule's ++ * class must be a member of the query's classes.) Pass a NULL to ++ * clear all classes. Note that this performs straight string ++ * comparison, ignoring the regex flag. ++ ++ * ++ * @param p Policy handler, to report errors. ++ * @param t TE rule query to set. ++ * @param obj_class Name of object class to add to search set. ++ * ++ * @return 0 on success, negative on error. ++ */ ++ extern int apol_filename_trans_query_append_class(const apol_policy_t * p, apol_filename_trans_query_t * t, const char *obj_class); ++ ++/** ++ * Set a filename trans query to treat the source filename as any. That is, ++ * use the same symbol for either source or default of a ++ * filename_transition rule. This flag does nothing if the source filename is ++ * not set. Note that a filename_transition's target is a type, so thus ++ * this flag does not affect its searching. ++ * ++ * @param p Policy handler, to report errors. ++ * @param r Role trans query to set. ++ * @param is_any Non-zero to use source symbol for source or default ++ * field, 0 to keep source as only source. ++ * ++ * @return Always 0. ++ */ ++ extern int apol_filename_trans_query_set_source_any(const apol_policy_t * p, apol_filename_trans_query_t * r, int is_any); ++ ++/** ++ * Set a filename trans query to use regular expression searching for ++ * source, target, and default fields. Strings will be treated as ++ * regexes instead of literals. For the target type, matching will ++ * occur against the type name or any of its aliases. ++ * ++ * @param p Policy handler, to report errors. ++ * @param r Role trans query to set. ++ * @param is_regex Non-zero to enable regex searching, 0 to disable. ++ * ++ * @return Always 0. ++ */ ++ extern int apol_filename_trans_query_set_regex(const apol_policy_t * p, apol_filename_trans_query_t * r, int is_regex); ++ ++/** ++ * Render a filename_transition rule to a string. ++ * ++ * @param policy Policy handler, to report errors. ++ * @param rule The rule to render. ++ * ++ * @return A newly malloc()'d string representation of the rule, or NULL on ++ * failure; if the call fails, errno will be set. The caller is responsible ++ * for calling free() on the returned string. ++ */ ++ extern char *apol_filename_trans_render(const apol_policy_t * policy, const qpol_filename_trans_t * rule); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +Index: setools-3.3.7/libapol/include/apol/policy-query.h +=================================================================== +--- setools-3.3.7.orig/libapol/include/apol/policy-query.h 2013-04-03 20:03:18.404208871 +0200 ++++ setools-3.3.7/libapol/include/apol/policy-query.h 2013-04-03 20:03:20.688277556 +0200 +@@ -71,6 +71,7 @@ extern "C" + #include "terule-query.h" + #include "condrule-query.h" + #include "rbacrule-query.h" ++#include "ftrule-query.h" + #include "range_trans-query.h" + #include "constraint-query.h" + +Index: setools-3.3.7/libapol/src/Makefile.am +=================================================================== +--- setools-3.3.7.orig/libapol/src/Makefile.am 2013-04-03 20:03:18.404208871 +0200 ++++ setools-3.3.7/libapol/src/Makefile.am 2013-04-03 20:03:20.688277556 +0200 +@@ -40,6 +40,7 @@ libapol_a_SOURCES = \ + render.c \ + role-query.c \ + terule-query.c \ ++ ftrule-query.c \ + type-query.c \ + types-relation-analysis.c \ + user-query.c \ +Index: setools-3.3.7/libapol/src/ftrule-query.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ setools-3.3.7/libapol/src/ftrule-query.c 2013-04-03 20:03:20.688277556 +0200 +@@ -0,0 +1,363 @@ ++/** ++ * @file ++ * ++ * Provides a way for setools to make queries about type enforcement ++ * filename_transs within a policy. The caller obtains a query object, fills in ++ * its parameters, and then runs the query; it obtains a vector of ++ * results. Searches are conjunctive -- all fields of the search ++ * query must match for a datum to be added to the results query. ++ * ++ * @author Jeremy A. Mowery jmowery@tresys.com ++ * @author Jason Tang jtang@tresys.com ++ * ++ * Copyright (C) 2006-2007 Tresys Technology, LLC ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "policy-query-internal.h" ++ ++#include ++#include ++ ++struct apol_filename_trans_query ++{ ++ char *source, *target, *default_type, *name; ++ apol_vector_t *classes; ++ unsigned int flags; ++}; ++ ++ ++/******************** filename_transition queries ********************/ ++ ++int apol_filename_trans_get_by_query(const apol_policy_t * p, const apol_filename_trans_query_t * t, apol_vector_t ** v) ++{ ++ apol_vector_t *source_list = NULL, *target_list = NULL, *class_list = NULL, *default_list = NULL; ++ int retval = -1, source_as_any = 0, is_regex = 0, append_filename_trans; ++ char *bool_name = NULL; ++ *v = NULL; ++ unsigned int flags = 0; ++ qpol_iterator_t *iter = NULL, *type_iter = NULL; ++ ++ if (t != NULL) { ++ flags = t->flags; ++ is_regex = t->flags & APOL_QUERY_REGEX; ++ if (t->source != NULL && ++ (source_list = ++ apol_query_create_candidate_type_list(p, t->source, is_regex, ++ t->flags & APOL_QUERY_SOURCE_INDIRECT, ++ ((t->flags & (APOL_QUERY_SOURCE_TYPE | APOL_QUERY_SOURCE_ATTRIBUTE)) / ++ APOL_QUERY_SOURCE_TYPE))) == NULL) { ++ goto cleanup; ++ } ++ ++ if ((t->flags & APOL_QUERY_SOURCE_AS_ANY) && t->source != NULL) { ++ default_list = target_list = source_list; ++ source_as_any = 1; ++ } else { ++ if (t->target != NULL && ++ (target_list = ++ apol_query_create_candidate_type_list(p, t->target, is_regex, ++ t->flags & APOL_QUERY_TARGET_INDIRECT, ++ ((t-> ++ flags & (APOL_QUERY_TARGET_TYPE | APOL_QUERY_TARGET_ATTRIBUTE)) ++ / APOL_QUERY_TARGET_TYPE))) == NULL) { ++ goto cleanup; ++ } ++ if (t->default_type != NULL && ++ (default_list = ++ apol_query_create_candidate_type_list(p, t->default_type, is_regex, 0, ++ APOL_QUERY_SYMBOL_IS_TYPE)) == NULL) { ++ goto cleanup; ++ } ++ } ++ if (t->classes != NULL && ++ apol_vector_get_size(t->classes) > 0 && ++ (class_list = apol_query_create_candidate_class_list(p, t->classes)) == NULL) { ++ goto cleanup; ++ } ++ } ++ ++ if (qpol_policy_get_filename_trans_iter(p->p, &iter) < 0) { ++ return -1; ++ } ++ ++ if ((*v = apol_vector_create(NULL)) == NULL) { ++ ERR(p, "%s", strerror(errno)); ++ goto cleanup; ++ } ++ ++ for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { ++ qpol_filename_trans_t *filename_trans; ++ if (qpol_iterator_get_item(iter, (void **)&filename_trans) < 0) { ++ goto cleanup; ++ } ++ int match_source = 0, match_target = 0, match_default = 0, match_bool = 0; ++ size_t i; ++ ++ if (source_list == NULL) { ++ match_source = 1; ++ } else { ++ const qpol_type_t *source_type; ++ if (qpol_filename_trans_get_source_type(p->p, filename_trans, &source_type) < 0) { ++ goto cleanup; ++ } ++ if (apol_vector_get_index(source_list, source_type, NULL, NULL, &i) == 0) { ++ match_source = 1; ++ } ++ } ++ ++ /* if source did not match, but treating source symbol ++ * as any field, then delay rejecting this filename_trans until ++ * the target and default have been checked */ ++ if (!source_as_any && !match_source) { ++ continue; ++ } ++ ++ if (target_list == NULL || (source_as_any && match_source)) { ++ match_target = 1; ++ } else { ++ const qpol_type_t *target_type; ++ if (qpol_filename_trans_get_target_type(p->p, filename_trans, &target_type) < 0) { ++ goto cleanup; ++ } ++ if (apol_vector_get_index(target_list, target_type, NULL, NULL, &i) == 0) { ++ match_target = 1; ++ } ++ } ++ ++ if (!source_as_any && !match_target) { ++ continue; ++ } ++ ++ if (default_list == NULL || (source_as_any && match_source) || (source_as_any && match_target)) { ++ match_default = 1; ++ } else { ++ const qpol_type_t *default_type; ++ if (qpol_filename_trans_get_default_type(p->p, filename_trans, &default_type) < 0) { ++ goto cleanup; ++ } ++ if (apol_vector_get_index(default_list, default_type, NULL, NULL, &i) == 0) { ++ match_default = 1; ++ } ++ } ++ ++ if (!source_as_any && !match_default) { ++ continue; ++ } ++ /* at least one thing must match if source_as_any was given */ ++ if (source_as_any && (!match_source && !match_target && !match_default)) { ++ continue; ++ } ++ ++ if (class_list != NULL) { ++ const qpol_class_t *obj_class; ++ if (qpol_filename_trans_get_object_class(p->p, filename_trans, &obj_class) < 0) { ++ goto cleanup; ++ } ++ if (apol_vector_get_index(class_list, obj_class, NULL, NULL, &i) < 0) { ++ continue; ++ } ++ } ++ ++ if (apol_vector_append(*v, filename_trans)) { ++ ERR(p, "%s", strerror(ENOMEM)); ++ goto cleanup; ++ } ++ } ++ ++ retval = 0; ++ cleanup: ++ if (retval != 0) { ++ apol_vector_destroy(v); ++ } ++ apol_vector_destroy(&source_list); ++ if (!source_as_any) { ++ apol_vector_destroy(&target_list); ++ apol_vector_destroy(&default_list); ++ } ++ apol_vector_destroy(&class_list); ++ return retval; ++} ++ ++apol_filename_trans_query_t *apol_filename_trans_query_create(void) ++{ ++ apol_filename_trans_query_t *t = calloc(1, sizeof(apol_filename_trans_query_t)); ++ if (t != NULL) { ++ t->flags = ++ (APOL_QUERY_SOURCE_TYPE | APOL_QUERY_SOURCE_ATTRIBUTE | APOL_QUERY_TARGET_TYPE | ++ APOL_QUERY_TARGET_ATTRIBUTE); ++ } ++ return t; ++} ++ ++void apol_filename_trans_query_destroy(apol_filename_trans_query_t ** r) ++{ ++ if (r != NULL && *r != NULL) { ++ free((*r)->source); ++ free((*r)->target); ++ free((*r)->default_type); ++ free((*r)->name); ++ free(*r); ++ *r = NULL; ++ } ++} ++ ++int apol_filename_trans_query_set_source(const apol_policy_t * p, apol_filename_trans_query_t * t, const char *filename, int is_indirect) ++{ ++ apol_query_set_flag(p, &t->flags, is_indirect, APOL_QUERY_TARGET_INDIRECT); ++ return apol_query_set(p, &t->source, NULL, filename); ++} ++ ++int apol_filename_trans_query_set_target(const apol_policy_t * p, apol_filename_trans_query_t * t, const char *type, int is_indirect) ++{ ++ apol_query_set_flag(p, &t->flags, is_indirect, APOL_QUERY_TARGET_INDIRECT); ++ return apol_query_set(p, &t->target, NULL, type); ++} ++ ++int apol_filename_trans_query_set_default(const apol_policy_t * p, apol_filename_trans_query_t * t, const char *symbol) ++{ ++ return apol_query_set(p, &t->default_type, NULL, symbol); ++} ++ ++int apol_filename_trans_query_append_class(const apol_policy_t * p, apol_filename_trans_query_t * t, const char *obj_class) ++{ ++ char *s = NULL; ++ if (obj_class == NULL) { ++ apol_vector_destroy(&t->classes); ++ } else if ((s = strdup(obj_class)) == NULL || (t->classes == NULL && (t->classes = apol_vector_create(free)) == NULL) ++ || apol_vector_append(t->classes, s) < 0) { ++ ERR(p, "%s", strerror(errno)); ++ free(s); ++ return -1; ++ } ++ return 0; ++} ++ ++int apol_filename_trans_query_set_name(const apol_policy_t * p, apol_filename_trans_query_t * t, const char *filename) ++{ ++ return apol_query_set(p, &t->name, NULL, filename); ++} ++ ++int apol_filename_trans_query_set_source_any(const apol_policy_t * p, apol_filename_trans_query_t * t, int is_any) ++{ ++ return apol_query_set_flag(p, &t->flags, is_any, APOL_QUERY_SOURCE_AS_ANY); ++} ++ ++int apol_filename_trans_query_set_regex(const apol_policy_t * p, apol_filename_trans_query_t * t, int is_regex) ++{ ++ return apol_query_set_regex(p, &t->flags, is_regex); ++} ++ ++char *apol_filename_trans_render(const apol_policy_t * policy, const qpol_filename_trans_t * filename_trans) ++{ ++ char *tmp = NULL; ++ const char *tmp_name = NULL; ++ const char *filename_trans_type_str; ++ int error = 0; ++ size_t tmp_sz = 0; ++ uint32_t filename_trans_type = 0; ++ const qpol_type_t *type = NULL; ++ const qpol_class_t *obj_class = NULL; ++ ++ if (!policy || !filename_trans) { ++ ERR(policy, "%s", strerror(EINVAL)); ++ errno = EINVAL; ++ return NULL; ++ } ++ ++ /* source type */ ++ if (qpol_filename_trans_get_source_type(policy->p, filename_trans, &type)) { ++ error = errno; ++ goto err; ++ } ++ if (qpol_type_get_name(policy->p, type, &tmp_name)) { ++ error = errno; ++ goto err; ++ } ++ if (apol_str_appendf(&tmp, &tmp_sz, "transition_type %s ", tmp_name)) { ++ error = errno; ++ ERR(policy, "%s", strerror(error)); ++ goto err; ++ } ++ ++ /* target type */ ++ if (qpol_filename_trans_get_target_type(policy->p, filename_trans, &type)) { ++ error = errno; ++ goto err; ++ } ++ if (qpol_type_get_name(policy->p, type, &tmp_name)) { ++ error = errno; ++ goto err; ++ } ++ if (apol_str_appendf(&tmp, &tmp_sz, "%s : ", tmp_name)) { ++ error = errno; ++ ERR(policy, "%s", strerror(error)); ++ goto err; ++ } ++ ++ /* object class */ ++ if (qpol_filename_trans_get_object_class(policy->p, filename_trans, &obj_class)) { ++ error = errno; ++ goto err; ++ } ++ if (qpol_class_get_name(policy->p, obj_class, &tmp_name)) { ++ error = errno; ++ goto err; ++ } ++ if (apol_str_appendf(&tmp, &tmp_sz, "%s ", tmp_name)) { ++ error = errno; ++ ERR(policy, "%s", strerror(error)); ++ goto err; ++ } ++ ++ /* default type */ ++ if (qpol_filename_trans_get_default_type(policy->p, filename_trans, &type)) { ++ error = errno; ++ goto err; ++ } ++ if (qpol_type_get_name(policy->p, type, &tmp_name)) { ++ error = errno; ++ goto err; ++ } ++ if (apol_str_appendf(&tmp, &tmp_sz, "%s", tmp_name)) { ++ error = errno; ++ ERR(policy, "%s", strerror(error)); ++ goto err; ++ } ++ ++ if (qpol_filename_trans_get_filename(policy->p, filename_trans, &tmp_name)) { ++ error = errno; ++ goto err; ++ } ++ ++ if (apol_str_appendf(&tmp, &tmp_sz, " %s", tmp_name)) { ++ error = errno; ++ ERR(policy, "%s", strerror(error)); ++ goto err; ++ } ++ ++ if (apol_str_appendf(&tmp, &tmp_sz, ";")) { ++ error = errno; ++ ERR(policy, "%s", strerror(error)); ++ goto err; ++ } ++ return tmp; ++ ++ err: ++ free(tmp); ++ errno = error; ++ return NULL; ++} +Index: setools-3.3.7/libapol/src/libapol.map +=================================================================== +--- setools-3.3.7.orig/libapol/src/libapol.map 2013-04-03 20:03:18.405208901 +0200 ++++ setools-3.3.7/libapol/src/libapol.map 2013-04-03 20:03:20.688277556 +0200 +@@ -34,6 +34,7 @@ VERS_4.0{ + apol_protocol_to_str; + apol_qpol_context_render; + apol_range_trans_*; ++ apol_filename_trans_*; + apol_relabel_*; + apol_role_*; + apol_role_allow_*; +Index: setools-3.3.7/libqpol/include/qpol/ftrule_query.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ setools-3.3.7/libqpol/include/qpol/ftrule_query.h 2013-04-03 20:03:20.689277586 +0200 +@@ -0,0 +1,116 @@ ++/** ++ * @file ++ * Defines public interface for iterating over FTRULE rules. ++ * ++ * @author Kevin Carr kcarr@tresys.com ++ * @author Jeremy A. Mowery jmowery@tresys.com ++ * @author Jason Tang jtang@tresys.com ++ * ++ * Copyright (C) 2006-2007 Tresys Technology, LLC ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef QPOL_FTRULERULE_QUERY ++#define QPOL_FTRULERULE_QUERY ++ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif ++ ++#include ++#include ++ ++ typedef struct qpol_filename_trans qpol_filename_trans_t; ++ ++/** ++ * Get an iterator over all filename transition rules in the policy. ++ * @param policy Policy from which to create the iterator. ++ * @param iter Iterator over items of type qpol_filename_trans_t returned. ++ * The caller is responsible for calling qpol_iterator_destroy() ++ * to free memory used by this iterator. ++ * It is important to note that this iterator is only valid as long as ++ * the policy is unmodifed. ++ * @returm 0 on success and < 0 on failure; if the call fails, ++ * errno will be set and *iter will be NULL. ++ */ ++ extern int qpol_policy_get_filename_trans_iter(const qpol_policy_t * policy, qpol_iterator_t ** iter); ++ ++/** ++ * Get the source type from a filename transition rule. ++ * @param policy The policy from which the rule comes. ++ * @param rule The rule from which to get the source type. ++ * @param source Pointer in which to store the source type. ++ * The caller should not free this pointer. ++ * @return 0 on success and < 0 on failure; if the call fails, ++ * errno will be set and *source will be NULL. ++ */ ++ extern int qpol_filename_trans_get_source_type(const qpol_policy_t * policy, const qpol_filename_trans_t * rule, ++ const qpol_type_t ** source); ++ ++/** ++ * Get the target type from a filename transition rule. ++ * @param policy The policy from which the rule comes. ++ * @param rule The rule from which to get the target type. ++ * @param target Pointer in which to store the target type. ++ * The caller should not free this pointer. ++ * @return 0 on success and < 0 on failure; if the call fails, ++ * errno will be set and *target will be NULL. ++ */ ++ extern int qpol_filename_trans_get_target_type(const qpol_policy_t * policy, const qpol_filename_trans_t * rule, ++ const qpol_type_t ** target); ++ ++/** ++ * Get the default type from a type rule. ++ * @param policy Policy from which the rule comes. ++ * @param rule The rule from which to get the default type. ++ * @param dflt Pointer in which to store the default type. ++ * The caller should not free this pointer. ++ * @returm 0 on success and < 0 on failure; if the call fails, ++ * errno will be set and *dflt will be NULL. ++ */ ++ extern int qpol_filename_trans_get_default_type(const qpol_policy_t * policy, const qpol_filename_trans_t * rule, ++ const qpol_type_t ** dflt); ++ ++/** ++ * Get the object class from a type rule. ++ * @param policy Policy from which the rule comes. ++ * @param rule The rule from which to get the object class. ++ * @param obj_class Pointer in which to store the object class. ++ * The caller should not free this pointer. ++ * @returm 0 on success and < 0 on failure; if the call fails, ++ * errno will be set and *obj_class will be NULL. ++ */ ++ extern int qpol_filename_trans_get_object_class(const qpol_policy_t * policy, const qpol_filename_trans_t * rule, ++ const qpol_class_t ** obj_class); ++ ++/** ++ * Get the transition filename type from a type rule. ++ * @param policy Policy from which the rule comes. ++ * @param rule The rule from which to get the transition filename. ++ * @param target Pointer in which to store the transition filename. ++ * The caller should not free this pointer. ++ * @returm 0 on success and < 0 on failure; if the call fails, ++ * errno will be set and *target will be NULL. ++ */ ++ extern int qpol_filename_trans_get_filename(const qpol_policy_t * policy, const qpol_filename_trans_t * rule, ++ const char ** name); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* QPOL_FTRULERULE_QUERY */ +Index: setools-3.3.7/libqpol/include/qpol/policy.h +=================================================================== +--- setools-3.3.7.orig/libqpol/include/qpol/policy.h 2013-04-03 20:03:18.406208931 +0200 ++++ setools-3.3.7/libqpol/include/qpol/policy.h 2013-04-03 20:03:20.689277586 +0200 +@@ -55,6 +55,7 @@ extern "C" + #include + #include + #include ++#include + #include + #include + #include +Index: setools-3.3.7/libqpol/src/Makefile.am +=================================================================== +--- setools-3.3.7.orig/libqpol/src/Makefile.am 2013-04-03 20:03:18.406208931 +0200 ++++ setools-3.3.7/libqpol/src/Makefile.am 2013-04-03 20:03:20.689277586 +0200 +@@ -48,6 +48,7 @@ libqpol_a_SOURCES = \ + syn_rule_internal.h \ + syn_rule_query.c \ + terule_query.c \ ++ ftrule_query.c \ + type_query.c \ + user_query.c \ + util.c \ +Index: setools-3.3.7/libqpol/src/ftrule_query.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ setools-3.3.7/libqpol/src/ftrule_query.c 2013-04-03 20:03:20.689277586 +0200 +@@ -0,0 +1,277 @@ ++/** ++ * @file ++ * Defines public interface for iterating over RBAC rules. ++ * ++ * @author Jeremy A. Mowery jmowery@tresys.com ++ * @author Jason Tang jtang@tresys.com ++ * ++ * Copyright (C) 2006-2007 Tresys Technology, LLC ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include "iterator_internal.h" ++#include "qpol_internal.h" ++#include ++ ++typedef struct filename_trans_state ++{ ++ filename_trans_t *head; ++ filename_trans_t *cur; ++} filename_trans_state_t; ++ ++static int filename_trans_state_end(const qpol_iterator_t * iter) ++{ ++ filename_trans_state_t *fts = NULL; ++ ++ if (!iter || !(fts = qpol_iterator_state(iter))) { ++ errno = EINVAL; ++ return STATUS_ERR; ++ } ++ ++ return fts->cur ? 0 : 1; ++} ++ ++static void *filename_trans_state_get_cur(const qpol_iterator_t * iter) ++{ ++ filename_trans_state_t *fts = NULL; ++ const policydb_t *db = NULL; ++ ++ if (!iter || !(fts = qpol_iterator_state(iter)) || !(db = qpol_iterator_policy(iter)) || filename_trans_state_end(iter)) { ++ errno = EINVAL; ++ return NULL; ++ } ++ ++ return fts->cur; ++} ++ ++static int filename_trans_state_next(qpol_iterator_t * iter) ++{ ++ filename_trans_state_t *fts = NULL; ++ const policydb_t *db = NULL; ++ ++ if (!iter || !(fts = qpol_iterator_state(iter)) || !(db = qpol_iterator_policy(iter))) { ++ errno = EINVAL; ++ return STATUS_ERR; ++ } ++ ++ if (filename_trans_state_end(iter)) { ++ errno = ERANGE; ++ return STATUS_ERR; ++ } ++ ++ fts->cur = fts->cur->next; ++ ++ return STATUS_SUCCESS; ++} ++ ++static size_t filename_trans_state_size(const qpol_iterator_t * iter) ++{ ++ filename_trans_state_t *fts = NULL; ++ const policydb_t *db = NULL; ++ filename_trans_t *tmp = NULL; ++ size_t count = 0; ++ ++ if (!iter || !(fts = qpol_iterator_state(iter)) || !(db = qpol_iterator_policy(iter))) { ++ errno = EINVAL; ++ return STATUS_ERR; ++ } ++ ++ for (tmp = fts->head; tmp; tmp = tmp->next) ++ count++; ++ ++ return count; ++} ++ ++int qpol_policy_get_filename_trans_iter(const qpol_policy_t * policy, qpol_iterator_t ** iter) ++{ ++ policydb_t *db = NULL; ++ filename_trans_state_t *fts = NULL; ++ int error = 0; ++ ++ if (iter) ++ *iter = NULL; ++ ++ if (!policy || !iter) { ++ ERR(policy, "%s", strerror(EINVAL)); ++ errno = EINVAL; ++ return STATUS_ERR; ++ } ++ ++ db = &policy->p->p; ++ ++ fts = calloc(1, sizeof(filename_trans_state_t)); ++ if (!fts) { ++ /* errno set by calloc */ ++ ERR(policy, "%s", strerror(errno)); ++ return STATUS_ERR; ++ } ++ fts->head = fts->cur = db->filename_trans; ++ ++ if (qpol_iterator_create ++ (policy, (void *)fts, filename_trans_state_get_cur, filename_trans_state_next, filename_trans_state_end, filename_trans_state_size, ++ free, iter)) { ++ error = errno; ++ free(fts); ++ errno = error; ++ return STATUS_ERR; ++ } ++ ++ return STATUS_SUCCESS; ++} ++ ++int qpol_filename_trans_get_source_type(const qpol_policy_t * policy, const qpol_filename_trans_t * rule, const qpol_type_t ** source) ++{ ++ policydb_t *db = NULL; ++ filename_trans_t *ft = NULL; ++ ++ if (source) { ++ *source = NULL; ++ } ++ ++ if (!policy || !rule || !source) { ++ ERR(policy, "%s", strerror(EINVAL)); ++ errno = EINVAL; ++ return STATUS_ERR; ++ } ++ ++ db = &policy->p->p; ++ ft = (filename_trans_t *) rule; ++ ++ *source = (qpol_type_t *) db->type_val_to_struct[ft->stype - 1]; ++ ++ return STATUS_SUCCESS; ++} ++ ++int qpol_filename_trans_get_target_type(const qpol_policy_t * policy, const qpol_filename_trans_t * rule, const qpol_type_t ** target) ++{ ++ policydb_t *db = NULL; ++ filename_trans_t *ft = NULL; ++ ++ if (target) { ++ *target = NULL; ++ } ++ ++ if (!policy || !rule || !target) { ++ ERR(policy, "%s", strerror(EINVAL)); ++ errno = EINVAL; ++ return STATUS_ERR; ++ } ++ ++ db = &policy->p->p; ++ ft = (filename_trans_t *) rule; ++ ++ *target = (qpol_type_t *) db->type_val_to_struct[ft->ttype - 1]; ++ ++ return STATUS_SUCCESS; ++} ++ ++int qpol_filename_trans_get_object_class(const qpol_policy_t * policy, const qpol_filename_trans_t * rule, ++ const qpol_class_t ** obj_class) ++{ ++ policydb_t *db = NULL; ++ filename_trans_t *ft = NULL; ++ ++ if (obj_class) { ++ *obj_class = NULL; ++ } ++ ++ if (!policy || !rule || !obj_class) { ++ ERR(policy, "%s", strerror(EINVAL)); ++ errno = EINVAL; ++ return STATUS_ERR; ++ } ++ ++ db = &policy->p->p; ++ ft = (filename_trans_t *) rule; ++ ++ *obj_class = (qpol_class_t *) db->class_val_to_struct[ft->tclass - 1]; ++ ++ return STATUS_SUCCESS; ++} ++ ++int qpol_filename_trans_get_trans_type(const qpol_policy_t * policy, const qpol_filename_trans_t * rule, const qpol_type_t ** output_type) ++{ ++ policydb_t *db = NULL; ++ filename_trans_t *ft = NULL; ++ ++ if (output_type) { ++ *output_type = NULL; ++ } ++ ++ if (!policy || !rule || !output_type) { ++ ERR(policy, "%s", strerror(EINVAL)); ++ errno = EINVAL; ++ return STATUS_ERR; ++ } ++ ++ db = &policy->p->p; ++ ft = (filename_trans_t *) rule; ++ ++ *output_type = (qpol_type_t *) db->type_val_to_struct[ft->otype - 1]; ++ ++ return STATUS_SUCCESS; ++} ++ ++int qpol_filename_trans_get_default_type(const qpol_policy_t * policy, const qpol_filename_trans_t * rule, const qpol_type_t ** dflt) ++{ ++ policydb_t *db = NULL; ++ filename_trans_t *ft = NULL; ++ ++ if (dflt) { ++ *dflt = NULL; ++ } ++ ++ if (!policy || !rule || !dflt) { ++ ERR(policy, "%s", strerror(EINVAL)); ++ errno = EINVAL; ++ return STATUS_ERR; ++ } ++ ++ db = &policy->p->p; ++ ft = (filename_trans_t *) rule; ++ ++ *dflt = (qpol_type_t *) db->type_val_to_struct[ft->otype - 1]; ++ ++ return STATUS_SUCCESS; ++} ++ ++int qpol_filename_trans_get_filename(const qpol_policy_t * policy, const qpol_filename_trans_t * rule, const char ** name) ++{ ++ policydb_t *db = NULL; ++ filename_trans_t *ft = NULL; ++ ++ if (name) { ++ *name = NULL; ++ } ++ ++ if (!policy || !rule || !name) { ++ ERR(policy, "%s", strerror(EINVAL)); ++ errno = EINVAL; ++ return STATUS_ERR; ++ } ++ ++ db = &policy->p->p; ++ ft = (filename_trans_t *) rule; ++ ++ *name = ft->name; ++ ++ return STATUS_SUCCESS; ++} ++ +Index: setools-3.3.7/libqpol/src/libqpol.map +=================================================================== +--- setools-3.3.7.orig/libqpol/src/libqpol.map 2013-04-03 20:03:18.406208931 +0200 ++++ setools-3.3.7/libqpol/src/libqpol.map 2013-04-03 20:03:20.690277616 +0200 +@@ -34,6 +34,7 @@ VERS_1.2 { + qpol_policy_reevaluate_conds; + qpol_portcon_*; + qpol_range_trans_*; ++ qpol_filename_trans_*; + qpol_role_*; + qpol_syn_avrule_*; + qpol_syn_terule_*; +Index: setools-3.3.7/libqpol/src/module_compiler.c +=================================================================== +--- setools-3.3.7.orig/libqpol/src/module_compiler.c 2013-04-03 20:03:18.407208961 +0200 ++++ setools-3.3.7/libqpol/src/module_compiler.c 2013-04-03 20:03:20.690277616 +0200 +@@ -1256,6 +1256,18 @@ void append_role_allow(role_allow_rule_t + } + + /* this doesn't actually append, but really prepends it */ ++void append_filename_trans(filename_trans_rule_t * filename_trans_rules) ++{ ++ avrule_decl_t *decl = stack_top->decl; ++ ++ /* filename transitions are not allowed within conditionals */ ++ assert(stack_top->type == 1); ++ ++ filename_trans_rules->next = decl->filename_trans_rules; ++ decl->filename_trans_rules = filename_trans_rules; ++} ++ ++/* this doesn't actually append, but really prepends it */ + void append_range_trans(range_trans_rule_t * range_tr_rules) + { + avrule_decl_t *decl = stack_top->decl; +Index: setools-3.3.7/libqpol/src/policy_define.c +=================================================================== +--- setools-3.3.7.orig/libqpol/src/policy_define.c 2013-04-03 20:03:13.729068283 +0200 ++++ setools-3.3.7/libqpol/src/policy_define.c 2013-04-03 20:05:00.843289193 +0200 +@@ -2227,6 +2227,190 @@ int define_role_allow(void) + return 0; + } + ++avrule_t *define_cond_filename_trans(void) ++{ ++ yyerror("type transitions with a filename not allowed inside " ++ "conditionals\n"); ++ return COND_ERR; ++} ++ ++int define_filename_trans(void) ++{ ++ char *id, *name = NULL; ++ type_set_t stypes, ttypes; ++ ebitmap_t e_stypes, e_ttypes; ++ ebitmap_t e_tclasses; ++ ebitmap_node_t *snode, *tnode, *cnode; ++ filename_trans_t *ft; ++ filename_trans_rule_t *ftr; ++ class_datum_t *cladatum; ++ type_datum_t *typdatum; ++ uint32_t otype; ++ unsigned int c, s, t; ++ int add; ++ ++ if (pass == 1) { ++ /* stype */ ++ while ((id = queue_remove(id_queue))) ++ free(id); ++ /* ttype */ ++ while ((id = queue_remove(id_queue))) ++ free(id); ++ /* tclass */ ++ while ((id = queue_remove(id_queue))) ++ free(id); ++ /* otype */ ++ id = queue_remove(id_queue); ++ free(id); ++ /* name */ ++ id = queue_remove(id_queue); ++ free(id); ++ return 0; ++ } ++ ++ ++ add = 1; ++ type_set_init(&stypes); ++ while ((id = queue_remove(id_queue))) { ++ if (set_types(&stypes, id, &add, 0)) ++ goto bad; ++ } ++ ++ add =1; ++ type_set_init(&ttypes); ++ while ((id = queue_remove(id_queue))) { ++ if (set_types(&ttypes, id, &add, 0)) ++ goto bad; ++ } ++ ++ ebitmap_init(&e_tclasses); ++ while ((id = queue_remove(id_queue))) { ++ if (!is_id_in_scope(SYM_CLASSES, id)) { ++ yyerror2("class %s is not within scope", id); ++ free(id); ++ goto bad; ++ } ++ cladatum = hashtab_search(policydbp->p_classes.table, id); ++ if (!cladatum) { ++ yyerror2("unknown class %s", id); ++ goto bad; ++ } ++ if (ebitmap_set_bit(&e_tclasses, cladatum->s.value - 1, TRUE)) { ++ yyerror("Out of memory"); ++ goto bad; ++ } ++ free(id); ++ } ++ ++ id = (char *)queue_remove(id_queue); ++ if (!id) { ++ yyerror("no otype in transition definition?"); ++ goto bad; ++ } ++ if (!is_id_in_scope(SYM_TYPES, id)) { ++ yyerror2("type %s is not within scope", id); ++ free(id); ++ goto bad; ++ } ++ typdatum = hashtab_search(policydbp->p_types.table, id); ++ if (!typdatum) { ++ yyerror2("unknown type %s used in transition definition", id); ++ goto bad; ++ } ++ free(id); ++ otype = typdatum->s.value; ++ ++ name = queue_remove(id_queue); ++ if (!name) { ++ yyerror("no pathname specified in filename_trans definition?"); ++ goto bad; ++ } ++ ++ /* We expand the class set into seperate rules. We expand the types ++ * just to make sure there are not duplicates. They will get turned ++ * into seperate rules later */ ++ ebitmap_init(&e_stypes); ++ if (type_set_expand(&stypes, &e_stypes, policydbp, 1)) ++ goto bad; ++ ++ ebitmap_init(&e_ttypes); ++ if (type_set_expand(&ttypes, &e_ttypes, policydbp, 1)) ++ goto bad; ++ ++ ebitmap_for_each_bit(&e_tclasses, cnode, c) { ++ if (!ebitmap_node_get_bit(cnode, c)) ++ continue; ++ ebitmap_for_each_bit(&e_stypes, snode, s) { ++ if (!ebitmap_node_get_bit(snode, s)) ++ continue; ++ ebitmap_for_each_bit(&e_ttypes, tnode, t) { ++ if (!ebitmap_node_get_bit(tnode, t)) ++ continue; ++ ++ for (ft = policydbp->filename_trans; ft; ft = ft->next) { ++ if (ft->stype == (s + 1) && ++ ft->ttype == (t + 1) && ++ ft->tclass == (c + 1) && ++ !strcmp(ft->name, name)) { ++ yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s", ++ name, ++ policydbp->p_type_val_to_name[s], ++ policydbp->p_type_val_to_name[t], ++ policydbp->p_class_val_to_name[c]); ++ goto bad; ++ } ++ } ++ ++ ft = malloc(sizeof(*ft)); ++ if (!ft) { ++ yyerror("out of memory"); ++ goto bad; ++ } ++ memset(ft, 0, sizeof(*ft)); ++ ++ ft->next = policydbp->filename_trans; ++ policydbp->filename_trans = ft; ++ ++ ft->name = strdup(name); ++ if (!ft->name) { ++ yyerror("out of memory"); ++ goto bad; ++ } ++ ft->stype = s + 1; ++ ft->ttype = t + 1; ++ ft->tclass = c + 1; ++ ft->otype = otype; ++ } ++ } ++ ++ /* Now add the real rule since we didn't find any duplicates */ ++ ftr = malloc(sizeof(*ftr)); ++ if (!ftr) { ++ yyerror("out of memory"); ++ goto bad; ++ } ++ filename_trans_rule_init(ftr); ++ append_filename_trans(ftr); ++ ++ ftr->name = strdup(name); ++ ftr->stypes = stypes; ++ ftr->ttypes = ttypes; ++ ftr->tclass = c + 1; ++ ftr->otype = otype; ++ } ++ ++ free(name); ++ ebitmap_destroy(&e_stypes); ++ ebitmap_destroy(&e_ttypes); ++ ebitmap_destroy(&e_tclasses); ++ ++ return 0; ++ ++bad: ++ free(name); ++ return -1; ++} ++ + static constraint_expr_t *constraint_expr_clone(constraint_expr_t * expr) + { + constraint_expr_t *h = NULL, *l = NULL, *e, *newe; +Index: setools-3.3.7/libqpol/src/policy_parse.y +=================================================================== +--- setools-3.3.7.orig/libqpol/src/policy_parse.y 2013-04-03 20:03:18.409209021 +0200 ++++ setools-3.3.7/libqpol/src/policy_parse.y 2013-04-03 20:03:20.691277646 +0200 +@@ -98,6 +98,7 @@ extern char *qpol_src_inputlim;/* end of + %type require_decl_def + + %token PATH ++%token FILENAME + %token CLONE + %token COMMON + %token CLASS +@@ -360,7 +361,10 @@ cond_rule_def : cond_transitio + | require_block + { $$ = NULL; } + ; +-cond_transition_def : TYPE_TRANSITION names names ':' names identifier ';' ++cond_transition_def : TYPE_TRANSITION names names ':' names identifier filename ';' ++ { $$ = define_cond_filename_trans() ; ++ if ($$ == COND_ERR) return -1;} ++ | TYPE_TRANSITION names names ':' names identifier ';' + { $$ = define_cond_compute_type(AVRULE_TRANSITION) ; + if ($$ == COND_ERR) return -1;} + | TYPE_MEMBER names names ':' names identifier ';' +@@ -395,7 +399,9 @@ cond_dontaudit_def : DONTAUDIT names nam + { $$ = define_cond_te_avtab(AVRULE_DONTAUDIT); + if ($$ == COND_ERR) return -1; } + ; +-transition_def : TYPE_TRANSITION names names ':' names identifier ';' ++transition_def : TYPE_TRANSITION names names ':' names identifier filename ';' ++ {if (define_filename_trans()) return -1; } ++ | TYPE_TRANSITION names names ':' names identifier ';' + {if (define_compute_type(AVRULE_TRANSITION)) return -1;} + | TYPE_MEMBER names names ':' names identifier ';' + {if (define_compute_type(AVRULE_MEMBER)) return -1;} +@@ -752,6 +758,9 @@ identifier : IDENTIFIER + path : PATH + { if (insert_id(yytext,0)) return -1; } + ; ++filename : FILENAME ++ { yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) return -1; } ++ ; + number : NUMBER + { $$ = strtoul(yytext,NULL,0); } + ; +Index: setools-3.3.7/libqpol/src/policy_scan.l +=================================================================== +--- setools-3.3.7.orig/libqpol/src/policy_scan.l 2013-04-03 20:03:18.409209021 +0200 ++++ setools-3.3.7/libqpol/src/policy_scan.l 2013-04-03 20:03:20.692277676 +0200 +@@ -235,6 +235,7 @@ POLICYCAP { return(POLICYCAP); } + permissive | + PERMISSIVE { return(PERMISSIVE); } + "/"({alnum}|[_\.\-/])* { return(PATH); } ++\"({alnum}|[_\.\-])+\" { return(FILENAME); } + {letter}({alnum}|[_\-])*([\.]?({alnum}|[_\-]))* { return(IDENTIFIER); } + {digit}+|0x{hexval}+ { return(NUMBER); } + {digit}{1,3}(\.{digit}{1,3}){3} { return(IPV4_ADDR); } +Index: setools-3.3.7/secmds/sesearch.c +=================================================================== +--- setools-3.3.7.orig/secmds/sesearch.c 2013-04-03 20:03:18.410209051 +0200 ++++ setools-3.3.7/secmds/sesearch.c 2013-04-03 20:03:20.692277676 +0200 +@@ -575,6 +575,95 @@ static void print_te_results(const apol_ + free(expr); + } + ++static int perform_ft_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v) ++{ ++ apol_filename_trans_query_t *ftq = NULL; ++ int error = 0; ++ ++ if (!policy || !opt || !v) { ++ ERR(policy, "%s", strerror(EINVAL)); ++ errno = EINVAL; ++ return -1; ++ } ++ ++ if (!opt->type == QPOL_RULE_TYPE_TRANS && !opt->all) { ++ *v = NULL; ++ return 0; /* no search to do */ ++ } ++ ++ ftq = apol_filename_trans_query_create(); ++ if (!ftq) { ++ ERR(policy, "%s", strerror(ENOMEM)); ++ errno = ENOMEM; ++ return -1; ++ } ++ ++ apol_filename_trans_query_set_regex(policy, ftq, opt->useregex); ++ if (opt->src_name) { ++ if (apol_filename_trans_query_set_source(policy, ftq, opt->src_name)) { ++ error = errno; ++ goto err; ++ } ++ } ++ if (opt->tgt_name) { ++ if (apol_filename_trans_query_set_target(policy, ftq, opt->tgt_name, opt->indirect)) { ++ error = errno; ++ goto err; ++ } ++ } ++ ++ if (apol_filename_trans_get_by_query(policy, ftq, v)) { ++ error = errno; ++ goto err; ++ } ++ ++ apol_filename_trans_query_destroy(&ftq); ++ return 0; ++ ++ err: ++ apol_vector_destroy(v); ++ apol_filename_trans_query_destroy(&ftq); ++ ERR(policy, "%s", strerror(error)); ++ errno = error; ++ return -1; ++} ++ ++static void print_ft_results(const apol_policy_t * policy, const options_t * opt, const apol_vector_t * v) ++{ ++ qpol_policy_t *q = apol_policy_get_qpol(policy); ++ size_t i, num_rules = 0; ++ const qpol_filename_trans_t *rule = NULL; ++ char *tmp = NULL, *rule_str = NULL, *expr = NULL; ++ char enable_char = ' ', branch_char = ' '; ++ qpol_iterator_t *iter = NULL; ++ const qpol_cond_t *cond = NULL; ++ uint32_t enabled = 0, list = 0; ++ ++ if (!(num_rules = apol_vector_get_size(v))) ++ goto cleanup; ++ ++ fprintf(stdout, "Found %zd named file transition rules:\n", num_rules); ++ ++ for (i = 0; i < num_rules; i++) { ++ enable_char = branch_char = ' '; ++ if (!(rule = apol_vector_get_element(v, i))) ++ goto cleanup; ++ ++ if (!(rule_str = apol_filename_trans_render(policy, rule))) ++ goto cleanup; ++ fprintf(stdout, "%s %s\n", rule_str, expr ? expr : ""); ++ free(rule_str); ++ rule_str = NULL; ++ free(expr); ++ expr = NULL; ++ } ++ ++ cleanup: ++ free(tmp); ++ free(rule_str); ++ free(expr); ++} ++ + static int perform_ra_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v) + { + apol_role_allow_query_t *raq = NULL; +@@ -1128,6 +1217,18 @@ int main(int argc, char **argv) + print_te_results(policy, &cmd_opts, v); + fprintf(stdout, "\n"); + } ++ ++ if (cmd_opts.all || cmd_opts.type == QPOL_RULE_TYPE_TRANS) { ++ apol_vector_destroy(&v); ++ if (perform_ft_query(policy, &cmd_opts, &v)) { ++ rt = 1; ++ goto cleanup; ++ } ++ ++ print_ft_results(policy, &cmd_opts, v); ++ fprintf(stdout, "\n"); ++ } ++ + apol_vector_destroy(&v); + if (perform_ra_query(policy, &cmd_opts, &v)) { + rt = 1; +Index: setools-3.3.7/libapol/include/apol/Makefile.am +=================================================================== +--- setools-3.3.7.orig/libapol/include/apol/Makefile.am 2013-04-03 20:03:18.412209111 +0200 ++++ setools-3.3.7/libapol/include/apol/Makefile.am 2013-04-03 20:03:20.693277706 +0200 +@@ -27,6 +27,7 @@ apol_HEADERS = \ + relabel-analysis.h \ + render.h \ + role-query.h \ ++ ftrule-query.h \ + terule-query.h \ + type-query.h \ + types-relation-analysis.h \ +Index: setools-3.3.7/libqpol/include/qpol/Makefile.am +=================================================================== +--- setools-3.3.7.orig/libqpol/include/qpol/Makefile.am 2013-04-03 20:03:18.412209111 +0200 ++++ setools-3.3.7/libqpol/include/qpol/Makefile.am 2013-04-03 20:03:20.693277706 +0200 +@@ -25,6 +25,7 @@ qpol_HEADERS = \ + role_query.h \ + syn_rule_query.h \ + terule_query.h \ ++ ftrule_query.h \ + type_query.h \ + user_query.h \ + util.h diff --git a/0007-Remove-unused-variables.patch b/0007-Remove-unused-variables.patch new file mode 100644 index 0000000..9d1ec8f --- /dev/null +++ b/0007-Remove-unused-variables.patch @@ -0,0 +1,277 @@ +From e30036e358b8f1c3f56048b467e8646fa3bfffb6 Mon Sep 17 00:00:00 2001 +From: Dan Walsh +Date: Tue, 20 Sep 2011 16:40:26 -0400 +Subject: [PATCH 7/7] Remove unused variables + +--- + libapol/src/ftrule-query.c | 11 ++---- + libqpol/src/ftrule_query.c | 2 - + secmds/sesearch.c | 86 +++++++++++++++++++++++++++++++++----------- + 3 files changed, 68 insertions(+), 31 deletions(-) + +diff --git a/libapol/src/ftrule-query.c b/libapol/src/ftrule-query.c +index dc248de..9c7a23b 100644 +--- a/libapol/src/ftrule-query.c ++++ b/libapol/src/ftrule-query.c +@@ -45,14 +45,11 @@ struct apol_filename_trans_query + int apol_filename_trans_get_by_query(const apol_policy_t * p, const apol_filename_trans_query_t * t, apol_vector_t ** v) + { + apol_vector_t *source_list = NULL, *target_list = NULL, *class_list = NULL, *default_list = NULL; +- int retval = -1, source_as_any = 0, is_regex = 0, append_filename_trans; +- char *bool_name = NULL; ++ int retval = -1, source_as_any = 0, is_regex = 0; + *v = NULL; +- unsigned int flags = 0; +- qpol_iterator_t *iter = NULL, *type_iter = NULL; ++ qpol_iterator_t *iter = NULL; + + if (t != NULL) { +- flags = t->flags; + is_regex = t->flags & APOL_QUERY_REGEX; + if (t->source != NULL && + (source_list = +@@ -104,7 +101,7 @@ int apol_filename_trans_get_by_query(const apol_policy_t * p, const apol_filenam + if (qpol_iterator_get_item(iter, (void **)&filename_trans) < 0) { + goto cleanup; + } +- int match_source = 0, match_target = 0, match_default = 0, match_bool = 0; ++ int match_source = 0, match_target = 0, match_default = 0; + size_t i; + + if (source_list == NULL) { +@@ -265,10 +262,8 @@ char *apol_filename_trans_render(const apol_policy_t * policy, const qpol_filena + { + char *tmp = NULL; + const char *tmp_name = NULL; +- const char *filename_trans_type_str; + int error = 0; + size_t tmp_sz = 0; +- uint32_t filename_trans_type = 0; + const qpol_type_t *type = NULL; + const qpol_class_t *obj_class = NULL; + +diff --git a/libqpol/src/ftrule_query.c b/libqpol/src/ftrule_query.c +index d6db848..3148d30 100644 +--- a/libqpol/src/ftrule_query.c ++++ b/libqpol/src/ftrule_query.c +@@ -254,7 +254,6 @@ int qpol_filename_trans_get_default_type(const qpol_policy_t * policy, const qpo + + int qpol_filename_trans_get_filename(const qpol_policy_t * policy, const qpol_filename_trans_t * rule, const char ** name) + { +- policydb_t *db = NULL; + filename_trans_t *ft = NULL; + + if (name) { +@@ -267,7 +266,6 @@ int qpol_filename_trans_get_filename(const qpol_policy_t * policy, const qpol_fi + return STATUS_ERR; + } + +- db = &policy->p->p; + ft = (filename_trans_t *) rule; + + *name = ft->name; +diff --git a/secmds/sesearch.c b/secmds/sesearch.c +index e44b3bc..319ffe7 100644 +--- a/secmds/sesearch.c ++++ b/secmds/sesearch.c +@@ -72,6 +72,7 @@ static struct option const longopts[] = { + + {"source", required_argument, NULL, 's'}, + {"target", required_argument, NULL, 't'}, ++ {"default", required_argument, NULL, 'D'}, + {"role_source", required_argument, NULL, EXPR_ROLE_SOURCE}, + {"role_target", required_argument, NULL, EXPR_ROLE_TARGET}, + {"class", required_argument, NULL, 'c'}, +@@ -92,6 +93,7 @@ typedef struct options + { + char *src_name; + char *tgt_name; ++ char *default_name; + char *src_role_name; + char *tgt_role_name; + char *class_name; +@@ -293,7 +295,8 @@ static void print_syn_av_results(const apol_policy_t * policy, const options_t * + tmp = apol_cond_expr_render(policy, cond); + enable_char = (enabled ? 'E' : 'D'); + branch_char = ((is_true && enabled) || (!is_true && !enabled) ? 'T' : 'F'); +- asprintf(&expr, "[ %s ]", tmp); ++ if (asprintf(&expr, "[ %s ]", tmp) < 0) ++ goto cleanup; + free(tmp); + tmp = NULL; + if (!expr) +@@ -356,7 +359,8 @@ static void print_av_results(const apol_policy_t * policy, const options_t * opt + qpol_iterator_destroy(&iter); + enable_char = (enabled ? 'E' : 'D'); + branch_char = (list ? 'T' : 'F'); +- asprintf(&expr, "[ %s ]", tmp); ++ if (asprintf(&expr, "[ %s ]", tmp) < 0) ++ goto cleanup; + free(tmp); + tmp = NULL; + if (!expr) +@@ -488,7 +492,8 @@ static void print_syn_te_results(const apol_policy_t * policy, const options_t * + tmp = apol_cond_expr_render(policy, cond); + enable_char = (enabled ? 'E' : 'D'); + branch_char = ((is_true && enabled) || (!is_true && !enabled) ? 'T' : 'F'); +- asprintf(&expr, "[ %s ]", tmp); ++ if (asprintf(&expr, "[ %s ]", tmp) < 0) ++ goto cleanup; + free(tmp); + tmp = NULL; + if (!expr) +@@ -553,7 +558,8 @@ static void print_te_results(const apol_policy_t * policy, const options_t * opt + qpol_iterator_destroy(&iter); + enable_char = (enabled ? 'E' : 'D'); + branch_char = (list ? 'T' : 'F'); +- asprintf(&expr, "[ %s ]", tmp); ++ if (asprintf(&expr, "[ %s ]", tmp) < 0) ++ goto cleanup; + free(tmp); + tmp = NULL; + if (!expr) +@@ -586,7 +592,7 @@ static int perform_ft_query(const apol_policy_t * policy, const options_t * opt, + return -1; + } + +- if (!opt->type == QPOL_RULE_TYPE_TRANS && !opt->all) { ++ if (!opt->type && !opt->all) { + *v = NULL; + return 0; /* no search to do */ + } +@@ -600,17 +606,44 @@ static int perform_ft_query(const apol_policy_t * policy, const options_t * opt, + + apol_filename_trans_query_set_regex(policy, ftq, opt->useregex); + if (opt->src_name) { +- if (apol_filename_trans_query_set_source(policy, ftq, opt->src_name)) { ++ if (apol_filename_trans_query_set_source(policy, ftq, opt->src_name, opt->indirect)) { + error = errno; + goto err; + } + } ++ + if (opt->tgt_name) { + if (apol_filename_trans_query_set_target(policy, ftq, opt->tgt_name, opt->indirect)) { + error = errno; + goto err; + } + } ++ if (opt->default_name) { ++ if (apol_filename_trans_query_set_default(policy, ftq, opt->default_name)) { ++ error = errno; ++ goto err; ++ } ++ } ++ ++ if (opt->class_name) { ++ if (opt->class_vector == NULL) { ++ if (apol_filename_trans_query_append_class(policy, ftq, opt->class_name)) { ++ error = errno; ++ goto err; ++ } ++ } else { ++ for (size_t i = 0; i < apol_vector_get_size(opt->class_vector); ++i) { ++ char *class_name; ++ class_name = apol_vector_get_element(opt->class_vector, i); ++ if (!class_name) ++ continue; ++ if (apol_filename_trans_query_append_class(policy, ftq, class_name)) { ++ error = errno; ++ goto err; ++ } ++ } ++ } ++ } + + if (apol_filename_trans_get_by_query(policy, ftq, v)) { + error = errno; +@@ -630,37 +663,36 @@ static int perform_ft_query(const apol_policy_t * policy, const options_t * opt, + + static void print_ft_results(const apol_policy_t * policy, const options_t * opt, const apol_vector_t * v) + { +- qpol_policy_t *q = apol_policy_get_qpol(policy); +- size_t i, num_rules = 0; +- const qpol_filename_trans_t *rule = NULL; +- char *tmp = NULL, *rule_str = NULL, *expr = NULL; ++ size_t i, num_filename_trans = 0; ++ const qpol_filename_trans_t *filename_trans = NULL; ++ char *tmp = NULL, *filename_trans_str = NULL, *expr = NULL; + char enable_char = ' ', branch_char = ' '; + qpol_iterator_t *iter = NULL; + const qpol_cond_t *cond = NULL; + uint32_t enabled = 0, list = 0; + +- if (!(num_rules = apol_vector_get_size(v))) ++ if (!(num_filename_trans = apol_vector_get_size(v))) + goto cleanup; + +- fprintf(stdout, "Found %zd named file transition rules:\n", num_rules); ++ fprintf(stdout, "Found %zd named file transition filename_trans:\n", num_filename_trans); + +- for (i = 0; i < num_rules; i++) { ++ for (i = 0; i < num_filename_trans; i++) { + enable_char = branch_char = ' '; +- if (!(rule = apol_vector_get_element(v, i))) ++ if (!(filename_trans = apol_vector_get_element(v, i))) + goto cleanup; + +- if (!(rule_str = apol_filename_trans_render(policy, rule))) ++ if (!(filename_trans_str = apol_filename_trans_render(policy, filename_trans))) + goto cleanup; +- fprintf(stdout, "%s %s\n", rule_str, expr ? expr : ""); +- free(rule_str); +- rule_str = NULL; ++ fprintf(stdout, "%s %s\n", filename_trans_str, expr ? expr : ""); ++ free(filename_trans_str); ++ filename_trans_str = NULL; + free(expr); + expr = NULL; + } + + cleanup: + free(tmp); +- free(rule_str); ++ free(filename_trans_str); + free(expr); + } + +@@ -930,7 +962,7 @@ int main(int argc, char **argv) + + memset(&cmd_opts, 0, sizeof(cmd_opts)); + cmd_opts.indirect = true; +- while ((optc = getopt_long(argc, argv, "ATs:t:c:p:b:dRnSChV", longopts, NULL)) != -1) { ++ while ((optc = getopt_long(argc, argv, "ATs:t:c:p:b:dD:RnSChV", longopts, NULL)) != -1) { + switch (optc) { + case 0: + break; +@@ -946,6 +978,18 @@ int main(int argc, char **argv) + exit(1); + } + break; ++ case 'D': /* source */ ++ if (optarg == 0) { ++ usage(argv[0], 1); ++ printf("Missing source default type for -D (--default)\n"); ++ exit(1); ++ } ++ cmd_opts.default_name = strdup(optarg); ++ if (!cmd_opts.default_name) { ++ ++ exit(1); ++ } ++ break; + case 't': /* target */ + if (optarg == 0) { + usage(argv[0], 1); +@@ -1218,7 +1262,7 @@ int main(int argc, char **argv) + fprintf(stdout, "\n"); + } + +- if (cmd_opts.all || cmd_opts.type == QPOL_RULE_TYPE_TRANS) { ++ if (cmd_opts.all || cmd_opts.type) { + apol_vector_destroy(&v); + if (perform_ft_query(policy, &cmd_opts, &v)) { + rt = 1; +-- +1.7.6.2 + diff --git a/add-to-header-define_cond_filename_trans.patch b/add-to-header-define_cond_filename_trans.patch new file mode 100644 index 0000000..a6a236b --- /dev/null +++ b/add-to-header-define_cond_filename_trans.patch @@ -0,0 +1,12 @@ +Index: setools-3.3.7/libqpol/src/policy_define.h +=================================================================== +--- setools-3.3.7.orig/libqpol/src/policy_define.h 2010-04-23 18:22:08.000000000 +0200 ++++ setools-3.3.7/libqpol/src/policy_define.h 2013-04-03 15:26:40.164954714 +0200 +@@ -23,6 +23,7 @@ + * of code here */ + #define SECURITY_FS_USE_PSIDS 6 + ++avrule_t *define_cond_filename_trans(); + avrule_t *define_cond_compute_type(int which); + avrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * stmt); + avrule_t *define_cond_te_avtab(int which); diff --git a/setools.changes b/setools.changes index 8fdb9e4..e52f539 100644 --- a/setools.changes +++ b/setools.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Tue Mar 12 14:02:59 UTC 2013 - vcizek@suse.com + +- added patches: + * 0006-Changes-to-support-named-file_trans-rules.patch + * 0007-Remove-unused-variables.patch + - these two add support for named file trans rules + * add-to-header-define_cond_filename_trans.patch + - add missing define_cond_filename_trans() declaration + ------------------------------------------------------------------- Thu Oct 25 11:20:26 UTC 2012 - coolo@suse.com diff --git a/setools.spec b/setools.spec index 1453e83..56987ff 100644 --- a/setools.spec +++ b/setools.spec @@ -1,7 +1,7 @@ # # spec file for package setools # -# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -39,6 +39,10 @@ Patch7: %{name}-swig-2x.patch Patch8: %{name}-swig-2.0.7.patch Patch9: %{name}-am121.patch Patch10: %{name}-3.3.6-libsepol.patch +Patch15: 0006-Changes-to-support-named-file_trans-rules.patch +Patch16: 0007-Remove-unused-variables.patch +Patch23: add-to-header-define_cond_filename_trans.patch + BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: autoconf BuildRequires: automake @@ -227,6 +231,9 @@ This package includes the following graphical tools: %patch8 %patch9 -p1 %patch10 -p1 +%patch15 -p1 +%patch16 -p1 +%patch23 -p1 %build autoreconf -fi