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);
