Hi all i developed a patch that allows to specify a type or an attribute to be excluded either from source and target criteria of a policy query performed with the 'sesearch' command line tool. This patch is in a initial state, it works only for AV semantic queries and applies on 'setools' source from the Fedora 13 rpm: setools-3.3.7-7.fc13.src.rpm diff -urp setools-3.3.7.orig/libapol/include/apol/avrule-query.h setools-3.3.7/libapol/include/apol/avrule-query.h --- setools-3.3.7.orig/libapol/include/apol/avrule-query.h 2010-09-10 14:32:24.032644009 +0200 +++ setools-3.3.7/libapol/include/apol/avrule-query.h 2010-09-13 15:23:43.050612738 +0200 @@ -123,6 +123,8 @@ extern "C" */ extern int apol_avrule_query_set_source(const apol_policy_t * p, apol_avrule_query_t * a, const char *symbol, int is_indirect); + extern int apol_avrule_query_set_source_neg(const apol_policy_t * p, apol_avrule_query_t * a, const char *symbol, + int is_indirect); /** * Set an avrule query to return rules whose source symbol is matched as a type @@ -158,6 +160,8 @@ extern "C" */ extern int apol_avrule_query_set_target(const apol_policy_t * p, apol_avrule_query_t * a, const char *symbol, int is_indirect); + extern int apol_avrule_query_set_target_neg(const apol_policy_t * p, apol_avrule_query_t * a, const char *symbol, + int is_indirect); /** * Set an avrule query to return rules whose target symbol is matched as a type diff -urp setools-3.3.7.orig/libapol/src/avrule-query.c setools-3.3.7/libapol/src/avrule-query.c --- setools-3.3.7.orig/libapol/src/avrule-query.c 2010-09-10 14:32:24.026643858 +0200 +++ setools-3.3.7/libapol/src/avrule-query.c 2010-09-13 15:23:43.051613507 +0200 @@ -36,6 +36,7 @@ struct apol_avrule_query { char *source, *target, *bool_name; + char *sourceneg, *targetneg; apol_vector_t *classes, *perms; unsigned int rules; unsigned int flags; @@ -51,6 +52,10 @@ struct apol_avrule_query * If NULL, accept all types. * @param target_list If non-NULL, list of types to use as target. * If NULL, accept all types. + * @param sourceneg_list If non-NULL, list of types to exclude from source_list. + * If NULL, accept all types. + * @param targetneg_list If non-NULL, list of types to exclude from target_list. + * If NULL, accept all types. * @param class_list If non-NULL, list of classes to use. * If NULL, accept all classes. * @param perm_list If non-NULL, list of permisions to use. @@ -60,7 +65,9 @@ struct apol_avrule_query * @return 0 on success and < 0 on failure. */ static int rule_select(const apol_policy_t * p, apol_vector_t * v, uint32_t rule_type, unsigned int flags, - const apol_vector_t * source_list, const apol_vector_t * target_list, const apol_vector_t * class_list, + const apol_vector_t * source_list, const apol_vector_t * target_list, + const apol_vector_t * sourceneg_list, const apol_vector_t * targetneg_list, + const apol_vector_t * class_list, const apol_vector_t * perm_list, const char *bool_name) { qpol_iterator_t *iter = NULL, *perm_iter = NULL; @@ -109,16 +116,19 @@ static int rule_select(const apol_policy } } - if (source_list == NULL) { + if (source_list == NULL && sourceneg_list == NULL) { match_source = 1; } else { const qpol_type_t *source_type; if (qpol_avrule_get_source_type(p->p, rule, &source_type) < 0) { goto cleanup; } - if (apol_vector_get_index(source_list, source_type, NULL, NULL, &i) == 0) { + if (source_list == NULL || (source_list != NULL && apol_vector_get_index(source_list, + source_type, NULL, NULL, &i) == 0)) match_source = 1; - } + if (sourceneg_list != NULL && apol_vector_get_index(sourceneg_list, + source_type, NULL, NULL, &i) == 0) + match_source = 0; } /* if source did not match, but treating source symbol @@ -128,16 +138,19 @@ static int rule_select(const apol_policy continue; } - if (target_list == NULL || (source_as_any && match_source)) { + if ((target_list == NULL && targetneg_list == NULL) || (source_as_any && match_source)) { match_target = 1; } else { const qpol_type_t *target_type; if (qpol_avrule_get_target_type(p->p, rule, &target_type) < 0) { goto cleanup; } - if (apol_vector_get_index(target_list, target_type, NULL, NULL, &i) == 0) { + if (target_list == NULL || (target_list != NULL && apol_vector_get_index(target_list, + target_type, NULL, NULL, &i) == 0)) match_target = 1; - } + if (targetneg_list != NULL && apol_vector_get_index(targetneg_list, + target_type, NULL, NULL, &i) == 0) + match_target = 0; } if (!match_target) { @@ -192,6 +205,7 @@ static int rule_select(const apol_policy int apol_avrule_get_by_query(const apol_policy_t * p, const apol_avrule_query_t * a, apol_vector_t ** v) { apol_vector_t *source_list = NULL, *target_list = NULL, *class_list = NULL, *perm_list = NULL; + apol_vector_t *sourceneg_list = NULL, *targetneg_list = NULL; int retval = -1, source_as_any = 0, is_regex = 0; char *bool_name = NULL; *v = NULL; @@ -216,17 +230,38 @@ int apol_avrule_get_by_query(const apol_ APOL_QUERY_SOURCE_TYPE))) == NULL) { goto cleanup; } + if (a->sourceneg != NULL && + (sourceneg_list = + apol_query_create_candidate_type_list(p, a->sourceneg, is_regex, + a->flags & APOL_QUERY_SOURCE_INDIRECT, + ((a->flags & (APOL_QUERY_SOURCE_TYPE | APOL_QUERY_SOURCE_ATTRIBUTE)) / + APOL_QUERY_SOURCE_TYPE))) == NULL) { + goto cleanup; + } if ((a->flags & APOL_QUERY_SOURCE_AS_ANY) && a->source != NULL) { target_list = source_list; + if (a->sourceneg != NULL) + targetneg_list = sourceneg_list; source_as_any = 1; - } else if (a->target != NULL && + } else { + if (a->target != NULL && (target_list = apol_query_create_candidate_type_list(p, a->target, is_regex, a->flags & APOL_QUERY_TARGET_INDIRECT, ((a-> flags & (APOL_QUERY_TARGET_TYPE | APOL_QUERY_TARGET_ATTRIBUTE)) / APOL_QUERY_TARGET_TYPE))) == NULL) { - goto cleanup; + goto cleanup; + } + if (a->targetneg != NULL && + (targetneg_list = + apol_query_create_candidate_type_list(p, a->targetneg, is_regex, + a->flags & APOL_QUERY_TARGET_INDIRECT, + ((a-> + flags & (APOL_QUERY_TARGET_TYPE | APOL_QUERY_TARGET_ATTRIBUTE)) + / APOL_QUERY_TARGET_TYPE))) == NULL) { + goto cleanup; + } } if (a->classes != NULL && apol_vector_get_size(a->classes) > 0 && @@ -243,7 +278,8 @@ int apol_avrule_get_by_query(const apol_ goto cleanup; } - if (rule_select(p, *v, rule_type, flags, source_list, target_list, class_list, perm_list, bool_name)) { + if (rule_select(p, *v, rule_type, flags, source_list, target_list, + sourceneg_list, targetneg_list, class_list, perm_list, bool_name)) { goto cleanup; } @@ -253,8 +289,10 @@ int apol_avrule_get_by_query(const apol_ apol_vector_destroy(v); } apol_vector_destroy(&source_list); + apol_vector_destroy(&sourceneg_list); if (!source_as_any) { apol_vector_destroy(&target_list); + apol_vector_destroy(&targetneg_list); } apol_vector_destroy(&class_list); /* don't destroy perm_list - it points to query's permission list */ @@ -265,6 +303,7 @@ int apol_syn_avrule_get_by_query(const a { qpol_iterator_t *iter = NULL, *perm_iter = NULL; apol_vector_t *source_list = NULL, *target_list = NULL, *class_list = NULL, *perm_list = NULL, *syn_v = NULL; + apol_vector_t *sourceneg_list = NULL, *targetneg_list = NULL; apol_vector_t *target_types_list = NULL; int retval = -1, source_as_any = 0, is_regex = 0; char *bool_name = NULL; @@ -322,7 +361,8 @@ int apol_syn_avrule_get_by_query(const a goto cleanup; } - if (rule_select(p, *v, rule_type, flags, source_list, target_list, class_list, perm_list, bool_name)) { + if (rule_select(p, *v, rule_type, flags, source_list, target_list, + sourceneg_list, targetneg_list, class_list, perm_list, bool_name)) { goto cleanup; } @@ -486,6 +526,12 @@ int apol_avrule_query_set_source(const a return apol_query_set(p, &a->source, NULL, symbol); } +int apol_avrule_query_set_source_neg(const apol_policy_t * p, apol_avrule_query_t * a, const char *symbol, int is_indirect) +{ + apol_query_set_flag(p, &a->flags, is_indirect, APOL_QUERY_SOURCE_INDIRECT); + return apol_query_set(p, &a->sourceneg, NULL, symbol); +} + int apol_avrule_query_set_source_component(const apol_policy_t * p, apol_avrule_query_t * a, unsigned int component) { if (!a || !(component & APOL_QUERY_SYMBOL_IS_BOTH)) { @@ -504,6 +550,12 @@ int apol_avrule_query_set_target(const a return apol_query_set(p, &a->target, NULL, symbol); } +int apol_avrule_query_set_target_neg(const apol_policy_t * p, apol_avrule_query_t * a, const char *symbol, int is_indirect) +{ + apol_query_set_flag(p, &a->flags, is_indirect, APOL_QUERY_TARGET_INDIRECT); + return apol_query_set(p, &a->targetneg, NULL, symbol); +} + int apol_avrule_query_set_target_component(const apol_policy_t * p, apol_avrule_query_t * a, unsigned int component) { if (!a || !(component && APOL_QUERY_SYMBOL_IS_BOTH)) { diff -urp setools-3.3.7.orig/secmds/sesearch.c setools-3.3.7/secmds/sesearch.c --- setools-3.3.7.orig/secmds/sesearch.c 2010-09-10 14:32:24.083894085 +0200 +++ setools-3.3.7/secmds/sesearch.c 2010-09-13 15:23:43.055612620 +0200 @@ -72,6 +72,8 @@ static struct option const longopts[] = {"source", required_argument, NULL, 's'}, {"target", required_argument, NULL, 't'}, + {"source-neg", required_argument, NULL, 'u'}, + {"target-neg", required_argument, NULL, 'v'}, {"role_source", required_argument, NULL, EXPR_ROLE_SOURCE}, {"role_target", required_argument, NULL, EXPR_ROLE_TARGET}, {"class", required_argument, NULL, 'c'}, @@ -92,6 +94,8 @@ typedef struct options { char *src_name; char *tgt_name; + char *srcneg_name; + char *tgtneg_name; char *src_role_name; char *tgt_role_name; char *class_name; @@ -136,6 +140,8 @@ void usage(const char *program_name, int printf("EXPRESSIONS:\n"); printf(" -s NAME, --source=NAME rules with type/attribute NAME as source\n"); printf(" -t NAME, --target=NAME rules with type/attribute NAME as target\n"); + printf(" -u NAME,--source-neg=NAME rules without type/attribute NAME as source\n"); + printf(" -v NAME,--target-neg=NAME rules without type/attribute NAME as target\n"); printf(" --role_source=NAME rules with role NAME as source\n"); printf(" --role_target=NAME rules with role NAME as target\n"); printf(" -c NAME, --class=NAME rules with class NAME as the object class\n"); @@ -197,6 +203,10 @@ static int perform_av_query(const apol_p apol_avrule_query_set_source(policy, avq, opt->src_name, opt->indirect); if (opt->tgt_name) apol_avrule_query_set_target(policy, avq, opt->tgt_name, opt->indirect); + if (opt->srcneg_name) + apol_avrule_query_set_source_neg(policy, avq, opt->srcneg_name, opt->indirect); + if (opt->tgtneg_name) + apol_avrule_query_set_target_neg(policy, avq, opt->tgtneg_name, opt->indirect); if (opt->bool_name) apol_avrule_query_set_bool(policy, avq, opt->bool_name); if (opt->class_name) { @@ -841,7 +851,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:u:v:c:p:b:dRnSChV", longopts, NULL)) != -1) { switch (optc) { case 0: break; @@ -869,6 +879,30 @@ int main(int argc, char **argv) exit(1); } break; + case 'u': /* source (negated) */ + if (optarg == 0) { + usage(argv[0], 1); + printf("Missing source type/attribute for -u (--source-neg)\n"); + exit(1); + } + cmd_opts.srcneg_name = strdup(optarg); + if (!cmd_opts.srcneg_name) { + fprintf(stderr, "%s\n", strerror(errno)); + exit(1); + } + break; + case 'v': /* target (negated) */ + if (optarg == 0) { + usage(argv[0], 1); + printf("Missing target type/attribute for -v (--target-neg)\n"); + exit(1); + } + cmd_opts.tgtneg_name = strdup(optarg); + if (!cmd_opts.tgtneg_name) { + fprintf(stderr, "%s\n", strerror(errno)); + exit(1); + } + break; case EXPR_ROLE_SOURCE: if (optarg == 0) { usage(argv[0], 1); @@ -1162,6 +1196,8 @@ int main(int argc, char **argv) apol_policy_path_destroy(&pol_path); free(cmd_opts.src_name); free(cmd_opts.tgt_name); + free(cmd_opts.srcneg_name); + free(cmd_opts.tgtneg_name); free(cmd_opts.class_name); free(cmd_opts.permlist); free(cmd_opts.bool_name);