3
* Canonical, Ltd. (All rights reserved)
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of version 2 of the GNU General Public
7
* License published by the Free Software Foundation.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, contact Novell, Inc. or Canonical
21
#include <sys/apparmor.h>
31
#include "parser_yacc.h"
34
#define MAXMAPPED_SIG 35
35
#define MINRT_SIG 128 /* base of RT sigs */
36
#define MAXRT_SIG 32 /* Max RT above MINRT_SIG */
38
/* Signal names mapped to and internal ordering */
39
static struct signal_map { const char *name; int num; } signal_map[] = {
78
/* this table is ordered post sig_map[sig] mapping */
79
static const char *const sig_names[MAXMAPPED_SIG + 1] = {
116
"exists", /* always last existance test mapped to MAXMAPPED_SIG */
120
int parse_signal_mode(const char *str_mode, int *mode, int fail)
122
return parse_X_mode("signal", AA_VALID_SIGNAL_PERMS, str_mode, mode, fail);
125
static int find_signal_mapping(const char *sig)
127
if (strncmp("rtmin+", sig, 6) == 0) {
129
unsigned long n = strtoul(sig + 6, &end, 10);
130
if (end == sig || n > MAXRT_SIG)
132
return MINRT_SIG + n;
134
for (int i = 0; signal_map[i].name; i++) {
135
if (strcmp(sig, signal_map[i].name) == 0)
136
return signal_map[i].num;
142
void signal_rule::extract_sigs(struct value_list **list)
144
struct value_list *entry, *tmp, *prev = NULL;
145
list_for_each_safe(*list, entry, tmp) {
146
int i = find_signal_mapping(entry->value);
149
list_remove_at(*list, prev, entry);
150
free_value_list(entry);
152
yyerror("unknown signal \"%s\"\n", entry->value);
158
void signal_rule::move_conditionals(struct cond_entry *conds)
160
struct cond_entry *cond_ent;
162
list_for_each(conds, cond_ent) {
163
/* for now disallow keyword 'in' (list) */
165
yyerror("keyword \"in\" is not allowed in signal rules\n");
166
if (strcmp(cond_ent->name, "set") == 0) {
167
extract_sigs(&cond_ent->vals);
168
} else if (strcmp(cond_ent->name, "peer") == 0) {
169
move_conditional_value("signal", &peer_label, cond_ent);
171
yyerror("invalid signal rule conditional \"%s\"\n",
177
signal_rule::signal_rule(int mode_p, struct cond_entry *conds):
178
signals(), peer_label(NULL), audit(0), deny(0)
182
if (mode & ~AA_VALID_SIGNAL_PERMS)
183
yyerror("mode contains invalid permission for signals\n");
185
mode = AA_VALID_SIGNAL_PERMS;
188
move_conditionals(conds);
190
free_cond_list(conds);
193
ostream &signal_rule::dump(ostream &os)
202
if (mode != AA_VALID_SIGNAL_PERMS) {
205
if (mode & AA_MAY_SEND)
207
if (mode & AA_MAY_RECEIVE)
212
if (!signals.empty()) {
214
for (Signals::iterator i = signals.begin(); i != signals.end();
216
if (i != signals.begin())
221
os << "rtmin+" << (*i - MINRT_SIG);
227
os << " " << peer_label;
234
int signal_rule::expand_variables(void)
236
return expand_entry_variables(&peer_label);
239
/* do we want to warn once/profile or just once per compile?? */
240
static void warn_once(const char *name)
242
static const char *warned_name = NULL;
244
if ((warnflags & WARN_RULE_NOT_ENFORCED) && warned_name != name) {
245
cerr << "Warning from profile " << name << " (";
246
if (current_filename)
247
cerr << current_filename;
250
cerr << ") signal rules not enforced\n";
255
int signal_rule::gen_policy_re(Profile &prof)
257
std::ostringstream buffer;
263
/* Currently do not generate the rules if the kernel doesn't support
264
* it. We may want to switch this so that a compile could be
265
* used for full support on kernels that don't support the feature
267
if (!kernel_supports_signal) {
268
warn_once(prof.name);
269
return RULE_NOT_SUPPORTED;
272
if (signals.size() == 0) {
273
/* not conditional on signal set, so will generate a label
276
buffer << "(" << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_LABEL << "\\x" << AA_CLASS_SIGNAL << "|";
279
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_SIGNAL;
281
if (signals.size()) {
283
for (Signals::iterator i = signals.begin(); i != signals.end(); i++) {
284
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << *i;
292
if (signals.size() == 0) {
293
/* close alternation */
297
ptype = convert_aaregex_to_pcre(peer_label, 0, glob_default, buf, &pos);
298
if (ptype == ePatternInvalid)
302
buffer << anyone_match_pattern;
306
if (mode & (AA_MAY_SEND | AA_MAY_RECEIVE)) {
307
if (!prof.policy.rules->add_rule(buf.c_str(), deny, mode, audit,