[apparmor] [patch 15/24] Add the ability to mediate signals.

john.johansen at canonical.com john.johansen at canonical.com
Fri Mar 7 17:31:36 UTC 2014


Add signal rules and make sure the parser encodes support for them
if the supported feature set reports supporting them.

The current format of the signal rule is

  [audit] [deny] signal [<signal_perms>] [<signal_set>] <target_profile>,

  signal_perm  := 'send'|'receive'|'r'|'w'|'rw'
  signal_perms := <signal_perm> | '(' <signal_perm> ([,]<signal_perm>)* ')'
  signal := ("hup"|"int"|"quit"|"ill"|"trap"|"abrt"|"bus"|"fpe"|"kill"|
             "usr1"|"segv"|"usr2"|"pipe"|"alrm"|"term"|"tkflt"|"chld"|
             "cont"|"stop"|"stp"|"ttin"|"ttou"|"urg"|"xcpu"|"xfsz"|"vtalrm"|
             "prof"|"winch"|"io"|"pwr"|"sys"|"emt"|"exists")
  signal_set   := set=<signal> | '(' <signal> ([,]<signal>)* ')'


it does not currently follow the peer=() format, and there is some question
as to whether it should or not. Input welcome.


---
 parser/Makefile        |    8 -
 parser/parser.h        |    5 
 parser/parser_common.c |    1 
 parser/parser_lex.l    |   22 ++-
 parser/parser_main.c   |    2 
 parser/parser_misc.c   |    1 
 parser/parser_regex.c  |    7 -
 parser/parser_yacc.y   |   68 +++++++++++
 parser/policydb.h      |    1 
 parser/signal.c        |  301 +++++++++++++++++++++++++++++++++++++++++++++++++
 parser/signal.h        |   58 +++++++++
 11 files changed, 462 insertions(+), 12 deletions(-)

--- 2.9-test.orig/parser/Makefile
+++ 2.9-test/parser/Makefile
@@ -79,8 +79,9 @@
 SRCS = parser_common.c parser_include.c parser_interface.c parser_lex.c \
        parser_main.c parser_misc.c parser_merge.c parser_symtab.c \
        parser_yacc.c parser_regex.c parser_variable.c parser_policy.c \
-       parser_alias.c mount.c dbus.c lib.c profile.cc rule.c
-HDRS = parser.h parser_include.h immunix.h mount.h dbus.h lib.h profile.h rule.h
+       parser_alias.c mount.c dbus.c lib.c profile.cc rule.c signal.c
+HDRS = parser.h parser_include.h immunix.h mount.h dbus.h lib.h profile.h \
+       rule.h signal.h
 TOOLS = apparmor_parser
 
 OBJECTS = $(SRCS:.c=.o)
@@ -239,6 +240,9 @@
 dbus.o: dbus.c dbus.h parser.h immunix.h parser_yacc.h rule.h $(APPARMOR_H)
 	$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
 
+signal.o: signal.c signal.h parser.h immunix.h parser_yacc.h rule.h $(APPARMOR_H)
+	$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
+
 profile.o: profile.cc profile.h parser.h
 	$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
 
--- 2.9-test.orig/parser/parser.h
+++ 2.9-test/parser/parser.h
@@ -300,6 +300,7 @@
 extern int kernel_supports_policydb;
 extern int kernel_supports_mount;
 extern int kernel_supports_dbus;
+extern int kernel_supports_signal;
 extern int conf_verbose;
 extern int conf_quiet;
 extern int names_only;
@@ -331,7 +332,9 @@
 extern const char *basedir;
 
 /* parser_regex.c */
-extern const char *default_match_pattern;
+#define default_match_pattern "[^\\000]*"
+#define anyone_match_pattern "[^\\000]+"
+
 extern pattern_t convert_aaregex_to_pcre(const char *aare, int anchor,
 					 std::string& pcre, int *first_re_pos);
 extern int build_list_val_expr(std::string& buffer, struct value_list *list);
--- 2.9-test.orig/parser/parser_common.c
+++ 2.9-test/parser/parser_common.c
@@ -70,6 +70,7 @@
 int kernel_supports_policydb = 0;	/* kernel supports new policydb */
 int kernel_supports_mount = 0;	        /* kernel supports mount rules */
 int kernel_supports_dbus = 0;		/* kernel supports dbus rules */
+int kernel_supports_signal = 0;		/* kernel supports signal rules */
 int conf_verbose = 0;
 int conf_quiet = 0;
 int names_only = 0;
--- 2.9-test.orig/parser/parser_lex.l
+++ 2.9-test/parser/parser_lex.l
@@ -253,6 +253,7 @@
 %x RLIMIT_MODE
 %x MOUNT_MODE
 %x DBUS_MODE
+%x SIGNAL_MODE
 %x CHANGE_PROFILE_MODE
 %x INCLUDE
 
@@ -267,7 +268,7 @@
 	}
 %}
 
-<INITIAL,INCLUDE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,RLIMIT_MODE,MOUNT_MODE,DBUS_MODE>{
+<INITIAL,INCLUDE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,RLIMIT_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE>{
 	{WS}+	{  DUMP_PREPROCESS; /* Ignoring whitespace */ }
 }
 
@@ -293,7 +294,7 @@
 		yyterminate();
 }
 
-<INITIAL,MOUNT_MODE,DBUS_MODE>{
+<INITIAL,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE>{
 	{VARIABLE_NAME}/{WS}*=	{
 		/* we match to the = in the lexer so that we can switch scanner
 		 * state.  By the time the parser see the = it may be too late
@@ -462,12 +463,15 @@
 }
 
 <DBUS_MODE>{
+	bind		{ RETURN_TOKEN(TOK_BIND); }
+	eavesdrop	{ RETURN_TOKEN(TOK_EAVESDROP); }
+}
+
+<DBUS_MODE,SIGNAL_MODE>{
 	send		{ RETURN_TOKEN(TOK_SEND); }
 	receive		{ RETURN_TOKEN(TOK_RECEIVE); }
-	bind		{ RETURN_TOKEN(TOK_BIND); }
 	read		{ RETURN_TOKEN(TOK_READ); }
 	write		{ RETURN_TOKEN(TOK_WRITE); }
-	eavesdrop	{ RETURN_TOKEN(TOK_EAVESDROP); }
 	{OPEN_PAREN}	{
 			yy_push_state(LIST_VAL_MODE);
 			RETURN_TOKEN(TOK_OPENPAREN);
@@ -478,7 +482,7 @@
 			}
 }
 
-<MOUNT_MODE,DBUS_MODE>{
+<MOUNT_MODE,DBUS_MODE,SIGNAL_MODE>{
 	{ARROW}		{ RETURN_TOKEN(TOK_ARROW); }
 
 	({IDS_NOEQ}|{PATHNAME}|{QUOTED_ID}) {
@@ -567,13 +571,16 @@
 	case TOK_DBUS:
 		state = DBUS_MODE;
 		break;
+	case TOK_SIGNAL:
+		state = SIGNAL_MODE;
+		break;
 	default: /* nothing */
 		break;
 	}
 	PUSH_AND_RETURN(state, token);
 }
 
-<INITIAL,NETWORK_MODE,RLIMIT_MODE,MOUNT_MODE,DBUS_MODE>{
+<INITIAL,NETWORK_MODE,RLIMIT_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE>{
 	{END_OF_RULE}	{
 		if (YY_START != INITIAL)
 			yy_pop_state();
@@ -586,7 +593,7 @@
 	}
 }
 
-<INITIAL,SUB_ID,SUB_VALUE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,MOUNT_MODE,DBUS_MODE>{
+<INITIAL,SUB_ID,SUB_VALUE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE>{
 	[^\n]	{
 		DUMP_PREPROCESS;
 		/* Something we didn't expect */
@@ -613,6 +620,7 @@
 	STATE_TABLE_ENT(RLIMIT_MODE),
 	STATE_TABLE_ENT(MOUNT_MODE),
 	STATE_TABLE_ENT(DBUS_MODE),
+	STATE_TABLE_ENT(SIGNAL_MODE),
 	STATE_TABLE_ENT(CHANGE_PROFILE_MODE),
 	STATE_TABLE_ENT(INCLUDE),
 };
--- 2.9-test.orig/parser/parser_main.c
+++ 2.9-test/parser/parser_main.c
@@ -847,6 +847,8 @@
 		kernel_supports_mount = 1;
 	if (strstr(features_string, "dbus"))
 		kernel_supports_dbus = 1;
+	if (strstr(features_string, "signal"))
+		kernel_supports_signal = 1;
 }
 
 int process_binary(int option, const char *profilename)
--- 2.9-test.orig/parser/parser_misc.c
+++ 2.9-test/parser/parser_misc.c
@@ -142,6 +142,7 @@
 	{"pivot_root",		TOK_PIVOTROOT},
 	{"in",			TOK_IN},
 	{"dbus",		TOK_DBUS},
+	{"signal",		TOK_SIGNAL},
 	{"send",                TOK_SEND},
 	{"receive",             TOK_RECEIVE},
 	{"bind",                TOK_BIND},
--- 2.9-test.orig/parser/parser_regex.c
+++ 2.9-test/parser/parser_regex.c
@@ -43,8 +43,6 @@
 	e_parse_error,
 };
 
-/* match any char except \000 0 or more times */
-const char *default_match_pattern = "[^\\000]*";
 
 /* Filters out multiple slashes (except if the first two are slashes,
  * that's a distinct namespace in linux) and trailing slashes.
@@ -675,6 +673,7 @@
 static const char *mediates_file = CLASS_STR(AA_CLASS_FILE);
 static const char *mediates_mount = CLASS_STR(AA_CLASS_MOUNT);
 static const char *mediates_dbus =  CLASS_STR(AA_CLASS_DBUS);
+static const char *mediates_signal =  CLASS_STR(AA_CLASS_SIGNAL);
 
 int process_profile_policydb(Profile *prof)
 {
@@ -701,6 +700,10 @@
 	if (kernel_supports_dbus &&
 	    !prof->policy.rules->add_rule(mediates_dbus, 0, AA_MAY_READ, 0, dfaflags))
 		goto out;
+	if (kernel_supports_signal &&
+	    !prof->policy.rules->add_rule(mediates_signal, 0, AA_MAY_READ, 0, dfaflags))
+		goto out;
+
 	if (prof->policy.rules->rule_count > 0) {
 		prof->policy.dfa = prof->policy.rules->create_dfa(&prof->policy.size, dfaflags);
 		delete prof->policy.rules;
--- 2.9-test.orig/parser/parser_yacc.y
+++ 2.9-test/parser/parser_yacc.y
@@ -28,6 +28,8 @@
 #include <fcntl.h>
 #include <libintl.h>
 #include <sys/apparmor.h>
+
+#include <iostream>
 #define _(s) gettext(s)
 
 /* #define DEBUG */
@@ -128,6 +130,7 @@
 %token TOK_PIVOTROOT
 %token TOK_IN
 %token TOK_DBUS
+%token TOK_SIGNAL
 %token TOK_SEND
 %token TOK_RECEIVE
 %token TOK_BIND
@@ -166,6 +169,7 @@
 	#include "profile.h"
 	#include "mount.h"
 	#include "dbus.h"
+	#include "signal.h"
 }
 
 %union {
@@ -179,6 +183,7 @@
 
 	mnt_rule *mnt_entry;
 	dbus_rule *dbus_entry;
+	signal_rule *signal_entry;
 
 	flagvals flags;
 	int fmode;
@@ -241,6 +246,10 @@
 %type <fmode>	dbus_perms
 %type <fmode>	opt_dbus_perm
 %type <dbus_entry>	dbus_rule
+%type <fmode>	signal_perm
+%type <fmode>	signal_perms
+%type <fmode>	opt_signal_perm
+%type <signal_entry>	signal_rule
 %type <transition> opt_named_transition
 %type <boolean> opt_unsafe
 %type <boolean> opt_file
@@ -698,6 +707,22 @@
 		$$ = $1;
 	}
 
+rules:  rules opt_prefix signal_rule
+	{
+		if ($2.owner)
+			yyerror(_("owner prefix not allowed on signal rules"));
+		if ($2.deny && $2.audit) {
+			$3->deny = 1;
+		} else if ($2.deny) {
+			$3->deny = 1;
+			$3->audit = $3->mode;
+		} else if ($2.audit) {
+			$3->audit = $3->mode;
+		}
+		$1->rule_ents.push_back($3);
+		$$ = $1;
+	}
+
 rules:	rules change_profile
 	{
 		PDEBUG("matched: rules change_profile\n");
@@ -1214,6 +1239,49 @@
 		$$ = ent;
 	}
 
+signal_perm: TOK_VALUE
+	{
+		if (strcmp($1, "send") == 0 || strcmp($1, "write") == 0)
+			$$ = AA_MAY_SEND;
+		else if (strcmp($1, "receive") == 0 || strcmp($1, "read") == 0)
+			$$ = AA_MAY_RECEIVE;
+		else if ($1) {
+			parse_signal_mode($1, &$$, 1);
+		} else
+			$$ = 0;
+
+		if ($1)
+			free($1);
+	}
+	| TOK_SEND { $$ = AA_MAY_SEND; }
+	| TOK_RECEIVE { $$ = AA_MAY_RECEIVE; }
+	| TOK_READ { $$ = AA_MAY_RECEIVE; }
+	| TOK_WRITE { $$ = AA_MAY_SEND; }
+	| TOK_MODE
+	{
+		parse_signal_mode($1, &$$, 1);
+		free($1);
+	}
+
+signal_perms: { /* nothing */ $$ = 0; }
+	| signal_perms signal_perm { $$ = $1 | $2; }
+	| signal_perms TOK_COMMA signal_perm { $$ = $1 | $3; }
+
+opt_signal_perm: { /* nothing */ $$ = 0; }
+	| signal_perm { $$ = $1; }
+	| TOK_OPENPAREN signal_perms TOK_CLOSEPAREN { $$ = $2; }
+
+signal_rule: TOK_SIGNAL opt_signal_perm opt_conds TOK_END_OF_RULE
+	{
+		signal_rule *ent = new signal_rule($2, $3, NULL);
+		$$ = ent;
+	}
+	|  TOK_SIGNAL opt_signal_perm opt_conds TOK_ID TOK_END_OF_RULE
+	{
+		signal_rule *ent = new signal_rule($2, $3, $4);
+		$$ = ent;
+	}
+
 hat_start: TOK_CARET {}
 	| TOK_HAT {}
 
--- 2.9-test.orig/parser/policydb.h
+++ 2.9-test/parser/policydb.h
@@ -31,6 +31,7 @@
 #define AA_CLASS_MOUNT		7
 #define AA_CLASS_NS_DOMAIN	8
 #define AA_CLASS_PTRACE		9
+#define AA_CLASS_SIGNAL		10
 
 #define AA_CLASS_LABEL		16
 
--- /dev/null
+++ 2.9-test/parser/signal.c
@@ -0,0 +1,301 @@
+/*
+ *   Copyright (c) 2014
+ *   Canonical, Ltd. (All rights reserved)
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License published by the Free Software Foundation.
+ *
+ *   This program 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 General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, contact Novell, Inc. or Canonical
+ *   Ltd.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/apparmor.h>
+
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <map>
+
+#include "parser.h"
+#include "profile.h"
+#include "parser_yacc.h"
+#include "signal.h"
+
+#define MAXMAPPED_SIG 35
+#define MINRT_SIG 128		/* base of RT sigs */
+#define MAXRT_SIG 32		/* Max RT above MINRT_SIG */
+
+/* Signal names mapped to and internal ordering */
+static struct signal_map { const char *name; int num; } signal_map[] = {
+	{"hup",		1},
+	{"int",		2},
+	{"quit",	3},
+	{"ill",		4},
+	{"trap",	5},
+	{"abrt",	6},
+	{"bus",		7},
+	{"fpe",		8},
+	{"kill",	9},
+	{"usr1",	10},
+	{"segv",	11},
+	{"usr2",	12},
+	{"pipe",	13},
+	{"alrm",	14},
+	{"term",	15},
+	{"tkflt",	16},
+	{"chld",	17},
+	{"cont",	18},
+	{"stop",	19},
+	{"stp",		20},
+	{"ttin",	21},
+	{"ttou",	22},
+	{"urg",		23},
+	{"xcpu",	24},
+	{"xfsz",	25},
+	{"vtalrm",	26},
+	{"prof",	27},
+	{"winch",	28},
+	{"io",		29},
+	{"pwr",		30},
+	{"sys",		31},
+	{"emt",		32},
+	{"exists",	35},
+
+	/* terminate */
+	{NULL,		0}
+};
+
+/* this table is ordered post sig_map[sig] mapping */
+static const char *const sig_names[MAXMAPPED_SIG + 1] = {
+	"unknown",
+	"hup",
+	"int",
+	"quit",
+	"ill",
+	"trap",
+	"abrt",
+	"bus",
+	"fpe",
+	"kill",
+	"usr1",
+	"segv",
+	"usr2",
+	"pipe",
+	"alrm",
+	"term",
+	"tkflt",
+	"chld",
+	"cont",
+	"stop",
+	"stp",
+	"ttin",
+	"ttou",
+	"urg",
+	"xcpu",
+	"xfsz",
+	"vtalrm",
+	"prof",
+	"winch",
+	"io",
+	"pwr",
+	"sys",
+	"emt",
+	"lost",
+	"unused",
+
+	"exists",	/* always last existance test mapped to MAXMAPPED_SIG */
+};
+
+
+int parse_signal_mode(const char *str_mode, int *mode, int fail)
+{
+	return parse_X_mode("signal", AA_VALID_SIGNAL_PERMS, str_mode, mode, fail);
+}
+
+static int find_signal_mapping(const char *sig)
+{
+	if (strncmp("rtmin+", sig, 6) == 0) {
+		char *end;
+		unsigned long n = strtoul(sig + 6, &end, 10);
+		if (end == sig || n > MAXRT_SIG)
+			return -1;
+		return MINRT_SIG + n;
+	} else {
+		for (int i = 0; signal_map[i].name; i++) {
+			if (strcmp(sig, signal_map[i].name) == 0)
+				return signal_map[i].num;
+		}
+	}
+	return -1;
+}
+
+void signal_rule::extract_sigs(struct value_list **list)
+{
+	struct value_list *entry, *tmp, *prev = NULL;
+	list_for_each_safe(*list, entry, tmp) {
+		int i = find_signal_mapping(entry->value);
+		if (i != -1) {
+			signals.insert(i);
+			list_remove_at(*list, prev, entry);
+			free_value_list(entry);
+		} else {
+			yyerror("unknown signal \"%s\"\n", entry->value);
+			prev = entry;
+		}
+	}
+}
+
+void signal_rule::move_conditionals(struct cond_entry *conds)
+{
+	struct cond_entry *cond_ent;
+
+	list_for_each(conds, cond_ent) {
+		/* for now disallow keyword 'in' (list) */
+		if (!cond_ent->eq)
+			yyerror("keyword \"in\" is not allowed in signal rules\n");
+		/* use alternation instead????
+		 * set=(kill,usr1) vs. set={kill,usr1}
+		 */
+		if (strcmp(cond_ent->name, "set") == 0) {
+			extract_sigs(&cond_ent->vals);
+		} else {
+			yyerror("invalid signal rule conditional \"%s\"\n",
+				cond_ent->name);
+		}
+	}
+}
+
+signal_rule::signal_rule(int mode_p, struct cond_entry *conds,
+			 char *peer):
+	signals(), peer_label(peer), audit(0), deny(0)
+{
+	if (mode_p) {
+		mode = mode_p;
+		if (mode & ~AA_VALID_SIGNAL_PERMS)
+			yyerror("mode contains invalid permission for signals\n");
+	} else {
+		mode = AA_VALID_SIGNAL_PERMS;
+	}
+
+	move_conditionals(conds);
+
+	free_cond_list(conds);
+}
+
+ostream &signal_rule::dump(ostream &os)
+{
+	if (audit)
+		os << "audit ";
+	if (deny)
+		os << "deny ";
+
+	os << "signal";
+
+	if (mode != AA_VALID_SIGNAL_PERMS) {
+		os << " (";
+
+		if (mode & AA_MAY_SEND)
+			os << "send ";
+		if (mode & AA_MAY_RECEIVE)
+			os << "receive ";
+		os << ")";
+	}
+
+	if (!signals.empty()) {
+		os << " set=(";
+		for (Signals::iterator i = signals.begin(); i != signals.end();
+		     i++) {
+			if (i != signals.begin())
+				os << ", ";
+			if (*i < MINRT_SIG)
+				os << sig_names[*i];
+			else
+				os << "rtmin+" << (*i - MINRT_SIG);
+		}
+		os << ")";
+	}
+
+	if (peer_label)
+		os << " " << peer_label;
+
+	os << ",\n";
+
+	return os;
+}
+
+int signal_rule::expand_variables(void)
+{
+	return expand_entry_variables(&peer_label);
+}
+
+int signal_rule::gen_policy_re(Profile &prof)
+{
+	std::ostringstream buffer;
+	std::string buf;
+
+	pattern_t ptype;
+	int pos;
+
+	/* Currently do not generate the rules if the kernel doesn't support
+	 * it. We may want to switch this so that a compile could be
+	 * used for full support on kernels that don't support the feature
+	 */
+	if (!kernel_supports_signal) {
+		pwarn("profile %s signal rules not enforced\n", prof.name);
+		return RULE_NOT_SUPPORTED;
+	}
+
+	if (signals.size() == 0) {
+		/* not conditional on signal set, so will generate a label
+		 * rule as well
+		 */
+		buffer << "(" << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_LABEL << "\\x" << AA_CLASS_SIGNAL << "|";
+	}
+
+	buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_SIGNAL;
+
+	if (signals.size()) {
+		buffer << "[";
+		for (Signals::iterator i = signals.begin(); i != signals.end(); i++) {
+			buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << *i;
+		}
+		buffer << "]";
+	} else {
+		/* match any char */
+		buffer << ".";
+	}
+
+	if (signals.size() == 0) {
+		/* close alternation */
+		buffer << ")";
+	}
+	if (peer_label) {
+		ptype = convert_aaregex_to_pcre(peer_label, 0, buf, &pos);
+		if (ptype == ePatternInvalid)
+			goto fail;
+		buffer << buf;
+	} else {
+		buffer << anyone_match_pattern;
+	}
+
+	buf = buffer.str();
+	if (mode & (AA_MAY_SEND | AA_MAY_RECEIVE)) {
+		if (!prof.policy.rules->add_rule(buf.c_str(), deny, mode, audit,
+						 dfaflags))
+			goto fail;
+	}
+
+	return RULE_OK;
+
+fail:
+	return RULE_ERROR;
+}
--- /dev/null
+++ 2.9-test/parser/signal.h
@@ -0,0 +1,58 @@
+/*
+ *   Copyright (c) 2014
+ *   Canonical, Ltd. (All rights reserved)
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License published by the Free Software Foundation.
+ *
+ *   This program 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 General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, contact Novell, Inc. or Canonical
+ *   Ltd.
+ */
+
+#ifndef __AA_SIGNAL_H
+#define __AA_SIGNAL_H
+
+#include "parser.h"
+#include "rule.h"
+#include "profile.h"
+
+
+#define AA_MAY_SEND			(1 << 1)
+#define AA_MAY_RECEIVE			(1 << 2)
+#define AA_VALID_SIGNAL_PERMS		(AA_MAY_SEND | AA_MAY_RECEIVE)
+
+
+typedef set<int> Signals;
+
+int parse_signal_mode(const char *str_mode, int *mode, int fail);
+
+class signal_rule: public rule_t {
+	void extract_sigs(struct value_list **list);
+	void move_conditionals(struct cond_entry *conds);
+public:
+	Signals signals;
+	char *peer_label;
+	int mode;
+	int audit;
+	int deny;
+
+	signal_rule(int mode, struct cond_entry *conds, char *peer);
+	virtual ~signal_rule() {
+		signals.clear();
+		free(peer_label);
+	};
+
+	virtual ostream &dump(ostream &os);
+	virtual int expand_variables(void);
+	virtual int gen_policy_re(Profile &prof);
+	virtual void post_process(Profile &prof __unused) { };
+};
+
+#endif /* __AA_SIGNAL_H */




More information about the AppArmor mailing list