parser: pass rule mode prompt through to backend

Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
John Johansen 2023-04-23 19:03:38 -07:00
parent 48b727b88a
commit 5c2bd20720
17 changed files with 227 additions and 117 deletions

View file

@ -344,7 +344,7 @@ int unix_rule::gen_policy_re(Profile &prof)
write_to_prot(buffer);
if ((mask & AA_NET_CREATE) && !has_peer_conds()) {
buf = buffer.str();
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY,
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode,
map_perms(AA_NET_CREATE),
map_perms(audit == AUDIT_FORCE ? AA_NET_CREATE : 0),
parseopts))
@ -369,7 +369,7 @@ int unix_rule::gen_policy_re(Profile &prof)
tmp << "\\x00";
buf = tmp.str();
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY,
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode,
map_perms(AA_NET_BIND),
map_perms(audit == AUDIT_FORCE ? AA_NET_BIND : 0),
parseopts))
@ -394,7 +394,7 @@ int unix_rule::gen_policy_re(Profile &prof)
AA_LOCAL_NET_PERMS & ~AA_LOCAL_NET_CMD;
if (mask & local_mask) {
buf = buffer.str();
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY,
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode,
map_perms(mask & local_mask),
map_perms(audit == AUDIT_FORCE ? mask & local_mask : 0),
parseopts))
@ -408,7 +408,7 @@ int unix_rule::gen_policy_re(Profile &prof)
/* TODO: backlog conditional: for now match anything*/
tmp << "..";
buf = tmp.str();
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY,
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode,
map_perms(AA_NET_LISTEN),
map_perms(audit == AUDIT_FORCE ? AA_NET_LISTEN : 0),
parseopts))
@ -421,9 +421,11 @@ int unix_rule::gen_policy_re(Profile &prof)
/* TODO: sockopt conditional: for now match anything */
tmp << "..";
buf = tmp.str();
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY,
if (!prof.policy.rules->add_rule(buf.c_str(),
rule_mode,
map_perms(mask & AA_NET_OPT),
map_perms(audit == AUDIT_FORCE ? AA_NET_OPT : 0),
map_perms(audit == AUDIT_FORCE ?
AA_NET_OPT : 0),
parseopts))
goto fail;
}
@ -442,7 +444,7 @@ int unix_rule::gen_policy_re(Profile &prof)
goto fail;
buf = buffer.str();
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(perms & AA_PEER_NET_PERMS), map_perms(audit == AUDIT_FORCE ? perms & AA_PEER_NET_PERMS : 0), parseopts))
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, map_perms(perms & AA_PEER_NET_PERMS), map_perms(audit == AUDIT_FORCE ? perms & AA_PEER_NET_PERMS : 0), parseopts))
goto fail;
}

View file

@ -274,20 +274,20 @@ int dbus_rule::gen_policy_re(Profile &prof)
}
if (perms & AA_DBUS_BIND) {
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms & AA_DBUS_BIND,
if (!prof.policy.rules->add_rule_vec(rule_mode, perms & AA_DBUS_BIND,
audit == AUDIT_FORCE ? perms & AA_DBUS_BIND : 0,
2, vec, parseopts, false))
goto fail;
}
if (perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE)) {
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY,
if (!prof.policy.rules->add_rule_vec(rule_mode,
perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
audit == AUDIT_FORCE ? perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE) : 0,
6, vec, parseopts, false))
goto fail;
}
if (perms & AA_DBUS_EAVESDROP) {
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY,
if (!prof.policy.rules->add_rule_vec(rule_mode,
perms & AA_DBUS_EAVESDROP,
audit == AUDIT_FORCE ? perms & AA_DBUS_EAVESDROP : 0,
1, vec, parseopts, false))

View file

@ -122,14 +122,14 @@ int io_uring_rule::gen_policy_re(Profile &prof)
}
if (perms & AA_VALID_IO_URING_PERMS) {
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, perms,
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, perms,
audit == AUDIT_FORCE ? perms : 0,
parseopts))
goto fail;
if (perms & AA_IO_URING_OVERRIDE_CREDS) {
buf = buffer.str(); /* update buf to have label */
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY,
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode,
perms, audit == AUDIT_FORCE ? perms : 0,
parseopts))
goto fail;

View file

@ -44,10 +44,10 @@ aare_rules::~aare_rules(void)
expr_map.clear();
}
bool aare_rules::add_rule(const char *rule, int deny, uint32_t perms,
bool aare_rules::add_rule(const char *rule, rule_mode_t mode, uint32_t perms,
uint32_t audit, optflags const &opts)
{
return add_rule_vec(deny, perms, audit, 1, &rule, opts, false);
return add_rule_vec(mode, perms, audit, 1, &rule, opts, false);
}
void aare_rules::add_to_rules(Node *tree, Node *perms)
@ -71,7 +71,7 @@ static Node *cat_with_oob_separator(Node *l, Node *r)
return new CatNode(new CatNode(l, new CharNode(transchar(-1, true))), r);
}
bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
bool aare_rules::add_rule_vec(rule_mode_t mode, uint32_t perms, uint32_t audit,
int count, const char **rulev, optflags const &opts,
bool oob)
{
@ -107,7 +107,7 @@ bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
if (reverse)
flip_tree(tree);
accept = unique_perms.insert(deny, perms, audit, exact_match);
accept = unique_perms.insert(mode, perms, audit, exact_match);
if (opts.dump & DUMP_DFA_RULE_EXPR) {
const char *separator;
@ -123,8 +123,11 @@ bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
}
cerr << " -> ";
tree->dump(cerr);
if (deny)
// TODO: split out from prefixes class
if (mode == RULE_DENY)
cerr << " deny";
else if (mode == RULE_PROMPT)
cerr << " prompt";
cerr << " (0x" << hex << perms <<"/" << audit << dec << ")";
accept->dump(cerr);
cerr << "\n\n";

View file

@ -31,17 +31,18 @@
#include "expr-tree.h"
#include "../immunix.h"
#include "../perms.h"
#include "../rule.h"
class UniquePerm {
public:
bool deny;
rule_mode_t mode;
bool exact_match;
uint32_t perms;
uint32_t audit;
bool operator<(UniquePerm const &rhs)const
{
if (deny == rhs.deny) {
if (mode >= rhs.mode) {
if (exact_match == rhs.exact_match) {
if (perms == rhs.perms)
return audit < rhs.audit;
@ -49,7 +50,7 @@ public:
}
return exact_match;
}
return deny;
return true; // mode < rhs.mode
}
};
@ -70,15 +71,17 @@ public:
nodes.clear();
}
Node *insert(bool deny, uint32_t perms, uint32_t audit,
Node *insert(rule_mode_t mode, uint32_t perms, uint32_t audit,
bool exact_match)
{
UniquePerm tmp = { deny, exact_match, perms, audit };
UniquePerm tmp = { mode, exact_match, perms, audit };
iterator res = nodes.find(tmp);
if (res == nodes.end()) {
Node *node;
if (deny)
if (mode == RULE_DENY)
node = new DenyMatchFlag(perms, audit);
else if (mode == RULE_PROMPT)
node = new PromptMatchFlag(perms, audit);
else if (exact_match)
node = new ExactMatchFlag(perms, audit);
else
@ -106,10 +109,11 @@ class aare_rules {
aare_rules(int reverse): root(NULL), unique_perms(), expr_map(), reverse(reverse), rule_count(0) { };
~aare_rules();
bool add_rule(const char *rule, int deny, uint32_t perms,
bool add_rule(const char *rule, rule_mode_t mode, uint32_t perms,
uint32_t audit, optflags const &opts);
bool add_rule_vec(int deny, uint32_t perms, uint32_t audit, int count,
const char **rulev, optflags const &opts, bool oob);
bool add_rule_vec(rule_mode_t mode, uint32_t perms, uint32_t audit,
int count, const char **rulev, optflags const &opts,
bool oob);
bool append_rule(const char *rule, bool oob, bool with_perm, optflags const &opts);
CHFA *create_chfa(int *min_match_len,
vector <aa_perms> &perms_table,

View file

@ -911,6 +911,12 @@ public:
}
};
class PromptMatchFlag: public MatchFlag {
public:
PromptMatchFlag(uint32_t prompt, uint32_t audit): MatchFlag(prompt, audit) {}
};
/* Traverse the syntax tree depth-first in an iterator-like manner. */
class depth_first_traversal {
stack<Node *>pos;

View file

@ -1076,8 +1076,10 @@ void DFA::dump(ostream & os)
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
if (*i == start || (*i)->perms.is_accept()) {
os << **i;
if (*i == start)
os << " <== (allow/deny/audit/quiet)";
if (*i == start) {
os << " <== ";
(*i)->perms.dump_header(os);
}
if ((*i)->perms.is_accept())
(*i)->perms.dump(os);
os << "\n";
@ -1304,16 +1306,17 @@ void DFA::apply_equivalence_classes(map<transchar, transchar> &eq)
void DFA::compute_perms_table_ent(State *state, size_t pos,
vector <aa_perms> &perms_table)
{
uint32_t accept1, accept2;
uint32_t accept1, accept2, accept3;
state->map_perms_to_accept(accept1, accept2);
// until front end doesn't map the way it does
state->map_perms_to_accept(accept1, accept2, accept3);
if (filedfa) {
state->idx = pos * 2;
perms_table[pos*2] = compute_fperms_user(accept1, accept2);
perms_table[pos*2 + 1] = compute_fperms_other(accept1, accept2);
perms_table[pos*2] = compute_fperms_user(accept1, accept2, accept3);
perms_table[pos*2 + 1] = compute_fperms_other(accept1, accept2, accept3);
} else {
state->idx = pos;
perms_table[pos] = compute_perms_entry(accept1, accept2);
perms_table[pos] = compute_perms_entry(accept1, accept2, accept3);
}
}
@ -1383,6 +1386,7 @@ int accept_perms(NodeVec *state, perms_t &perms, bool filedfa)
{
int error = 0;
uint32_t exact_match_allow = 0;
uint32_t exact_match_prompt = 0;
uint32_t exact_audit = 0;
perms.clear();
@ -1405,6 +1409,9 @@ int accept_perms(NodeVec *state, perms_t &perms, bool filedfa)
} else if (match->is_type(NODE_TYPE_DENYMATCHFLAG)) {
perms.deny |= match->flag;
perms.quiet |= match->audit;
} else if (dynamic_cast<PromptMatchFlag *>(match)) {
perms.prompt |= match->flag;
perms.audit |= match->audit;
} else {
if (filedfa && !is_merged_x_consistent(perms.allow, match->flag))
error = 1;
@ -1415,9 +1422,11 @@ int accept_perms(NodeVec *state, perms_t &perms, bool filedfa)
if (filedfa) {
perms.allow |= exact_match_allow & ~(ALL_AA_EXEC_TYPE);
perms.prompt |= exact_match_prompt & ~(ALL_AA_EXEC_TYPE);
perms.audit |= exact_audit & ~(ALL_AA_EXEC_TYPE);
} else {
perms.allow |= exact_match_allow;
perms.prompt |= exact_match_prompt;
perms.audit |= exact_audit;
}
if (exact_match_allow & AA_USER_EXEC) {
@ -1438,6 +1447,8 @@ int accept_perms(NodeVec *state, perms_t &perms, bool filedfa)
perms.allow &= ~perms.deny;
perms.quiet &= perms.deny;
perms.prompt &= ~perms.deny;
perms.prompt &= ~perms.allow;
if (error)
fprintf(stderr, "profile has merged rule with conflicting x modifiers\n");

View file

@ -51,16 +51,20 @@ class perms_t {
public:
perms_t(void): allow(0), deny(0), audit(0), quiet(0), exact(0) { };
bool is_accept(void) { return (allow | audit | quiet); }
bool is_accept(void) { return (allow | prompt | audit | quiet); }
void dump_header(ostream &os)
{
os << "(allow/deny/prompt/audit/quiet)";
}
void dump(ostream &os)
{
os << " (0x " << hex
<< allow << "/" << deny << "/" << audit << "/" << quiet
<< allow << "/" << deny << "/" << "/" << prompt << "/" << audit << "/" << quiet
<< ')' << dec;
}
void clear(void) { allow = deny = audit = quiet = 0; }
void clear(void) { allow = deny = prompt = audit = quiet = 0; }
void add(perms_t &rhs, bool filedfa)
{
deny |= rhs.deny;
@ -97,6 +101,7 @@ public:
allow = (allow | (rhs.allow & ~ALL_AA_EXEC_TYPE));
else
allow |= rhs.allow;
prompt |= rhs.prompt;
audit |= rhs.audit;
quiet = (quiet | rhs.quiet);
@ -114,6 +119,7 @@ public:
{
if (deny) {
allow &= ~deny;
prompt &= ~deny;
quiet &= deny;
deny = 0;
return !is_accept();
@ -127,12 +133,14 @@ public:
return allow < rhs.allow;
if (deny < rhs.deny)
return deny < rhs.deny;
if (prompt < rhs.prompt)
return prompt < rhs.prompt;
if (audit < rhs.audit)
return audit < rhs.audit;
return quiet < rhs.quiet;
}
uint32_t allow, deny, audit, quiet, exact;
uint32_t allow, deny, prompt, audit, quiet, exact;
};
int accept_perms(NodeVec *state, perms_t &perms, bool filedfa);
@ -250,10 +258,11 @@ public:
void flatten_relative(State *, int upper_bound);
int apply_and_clear_deny(void) { return perms.apply_and_clear_deny(); }
void map_perms_to_accept(uint32_t &accept1, uint32_t &accept2)
void map_perms_to_accept(uint32_t &accept1, uint32_t &accept2, uint32_t &accept3)
{
accept1 = perms.allow;
accept2 = PACK_AUDIT_CTL(perms.audit, perms.quiet & perms.deny);
accept3 = perms.prompt;
}
int label;

View file

@ -64,23 +64,23 @@ static uint32_t dfa_map_xindex(uint16_t mask)
/*
* map old dfa inline permissions to new format
*/
#define dfa_user_allow(accept1, accept2) (((accept1) & 0x7f) | \
#define dfa_user_allow(accept1) (((accept1) & 0x7f) | \
((accept1) & 0x80000000))
#define dfa_user_xbits(accept1, accept2) (((accept1) >> 7) & 0x7f)
#define dfa_user_xbits(accept1) (((accept1) >> 7) & 0x7f)
#define dfa_user_audit(accept1, accept2) ((accept2) & 0x7f)
#define dfa_user_quiet(accept1, accept2) (((accept2) >> 7) & 0x7f)
#define dfa_user_xindex(accept1, accept2) \
#define dfa_user_xindex(accept1) \
(dfa_map_xindex(accept1 & 0x3fff))
#define dfa_other_allow(accept1, accept2) ((((accept1) >> 14) & \
#define dfa_other_allow(accept1) ((((accept1) >> 14) & \
0x7f) | \
((accept1) & 0x80000000))
#define dfa_other_xbits(accept1, accept2) \
#define dfa_other_xbits(accept1) \
((((accept1) >> 7) >> 14) & 0x7f)
#define dfa_other_audit(accept1, accept2) (((accept2) >> 14) & 0x7f)
#define dfa_other_quiet(accept1, accept2) \
((((accept2) >> 7) >> 14) & 0x7f)
#define dfa_other_xindex(accept1, accept2) \
#define dfa_other_xindex(accept1) \
dfa_map_xindex((accept1 >> 14) & 0x3fff)
/**
@ -122,39 +122,33 @@ static void compute_fperms_allow(struct aa_perms *perms, uint32_t accept1)
perms->allow |= AA_MAY_ONEXEC;
}
struct aa_perms compute_fperms_user(uint32_t accept1, uint32_t accept2)
struct aa_perms compute_fperms_user(uint32_t accept1, uint32_t accept2,
uint32_t accept3)
{
struct aa_perms perms = { };
perms.allow = map_old_perms(dfa_user_allow(accept1, accept2));
perms.allow = map_old_perms(dfa_user_allow(accept1));
perms.prompt = map_old_perms(dfa_user_allow(accept3));
perms.audit = map_old_perms(dfa_user_audit(accept1, accept2));
perms.quiet = map_old_perms(dfa_user_quiet(accept1, accept2));
perms.xindex = dfa_user_xindex(accept1, accept2);
perms.xindex = dfa_user_xindex(accept1);
compute_fperms_allow(&perms, accept1);
// prompt being carried as audit need to change
perms.allow &= ~perms.prompt;
if (perms.allow & perms.prompt) {
//std::cerr << "user allow & prompt\n";
}
return perms;
}
struct aa_perms compute_fperms_other(uint32_t accept1, uint32_t accept2)
struct aa_perms compute_fperms_other(uint32_t accept1, uint32_t accept2,
uint32_t accept3)
{
struct aa_perms perms = { };
perms.allow = map_old_perms(dfa_other_allow(accept1, accept2));
perms.allow = map_old_perms(dfa_other_allow(accept1));
perms.prompt = map_old_perms(dfa_other_allow(accept3));
perms.audit = map_old_perms(dfa_other_audit(accept1, accept2));
perms.quiet = map_old_perms(dfa_other_quiet(accept1, accept2));
perms.xindex = dfa_other_xindex(accept1, accept2);
perms.xindex = dfa_other_xindex(accept1);
compute_fperms_allow(&perms, accept1);
// prompt being carried as audit need to change
perms.allow &= ~perms.prompt;
if (perms.allow & perms.prompt) {
std::cerr << "other allow & prompt\n";
}
return perms;
}
@ -171,13 +165,15 @@ static uint32_t map_xbits(uint32_t x)
((x & 0x7e) << 9);
}
struct aa_perms compute_perms_entry(uint32_t accept1, uint32_t accept2)
struct aa_perms compute_perms_entry(uint32_t accept1, uint32_t accept2,
uint32_t accept3)
// don't need to worry about version internally within the parser
// uint32_t version)
{
struct aa_perms perms = { };
perms.allow = dfa_user_allow(accept1, accept2);
perms.allow = dfa_user_allow(accept1);
perms.prompt = dfa_user_allow(accept3);
perms.audit = dfa_user_audit(accept1, accept2);
perms.quiet = dfa_user_quiet(accept1, accept2);
@ -192,7 +188,7 @@ struct aa_perms compute_perms_entry(uint32_t accept1, uint32_t accept2)
* Unfortunately there is no way to force auditing on the
* perms represented by the xbits
*/
perms.allow |= map_other(dfa_other_allow(accept1, accept2));
perms.allow |= map_other(dfa_other_allow(accept1));
// v9 encoding never rolled out. AA_MAY_LOCK needed to fix
// non fs unix locking see kernel commit
// 1cf26c3d2c4c apparmor: fix apparmor mediating locking non-fs unix sockets
@ -205,6 +201,7 @@ struct aa_perms compute_perms_entry(uint32_t accept1, uint32_t accept2)
* for v5-v9 perm mapping in the policydb, the other set is used
* to extend the general perm set
*/
perms.prompt |= map_other(dfa_other_allow(accept3));
perms.audit |= map_other(dfa_other_audit(accept1, accept2));
perms.quiet |= map_other(dfa_other_quiet(accept1, accept2));
//if (VERSION_GT(version, v8))

View file

@ -18,8 +18,8 @@
#ifndef __AA_POLICY_COMPAT_H
#define __AA_POLICY_COMPAT_H
struct aa_perms compute_fperms_user(uint32_t accept1, uint32_t accept2);
struct aa_perms compute_fperms_other(uint32_t accept1, uint32_t accept2);
struct aa_perms compute_perms_entry(uint32_t accept1, uint32_t accept2);
struct aa_perms compute_fperms_user(uint32_t accept1, uint32_t accept2, uint32_t accept3);
struct aa_perms compute_fperms_other(uint32_t accept1, uint32_t accept2, uint32_t accept3);
struct aa_perms compute_perms_entry(uint32_t accept1, uint32_t accept2, uint32_t accept3);
#endif /* __AA_POLICY_COMPAT_H */

View file

@ -797,7 +797,7 @@ int mnt_rule::gen_policy_remount(Profile &prof, int &count,
* if a data match is required this only has AA_MATCH_CONT perms
* else it has full perms
*/
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, tmpperms, tmpaudit, 4,
if (!prof.policy.rules->add_rule_vec(rule_mode, tmpperms, tmpaudit, 4,
vec, parseopts, false))
goto fail;
count++;
@ -808,7 +808,7 @@ int mnt_rule::gen_policy_remount(Profile &prof, int &count,
if (!build_mnt_opts(optsbuf, opts))
goto fail;
vec[4] = optsbuf.c_str();
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms,
if (!prof.policy.rules->add_rule_vec(rule_mode, perms,
(audit == AUDIT_FORCE ? perms : 0),
5, vec, parseopts, false))
goto fail;
@ -850,7 +850,7 @@ int mnt_rule::gen_policy_bind_mount(Profile &prof, int &count,
opt_flags & MS_BIND_FLAGS))
goto fail;
vec[3] = flagsbuf;
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms, audit == AUDIT_FORCE ? perms : 0,
if (!prof.policy.rules->add_rule_vec(rule_mode, perms, audit == AUDIT_FORCE ? perms : 0,
4, vec,
parseopts, false))
goto fail;
@ -907,7 +907,7 @@ int mnt_rule::gen_policy_change_mount_type(Profile &prof, int &count,
opt_flags & MS_MAKE_FLAGS))
goto fail;
vec[3] = flagsbuf;
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms, audit == AUDIT_FORCE ? perms : 0,
if (!prof.policy.rules->add_rule_vec(rule_mode, perms, audit == AUDIT_FORCE ? perms : 0,
4, vec,
parseopts, false))
goto fail;
@ -950,7 +950,7 @@ int mnt_rule::gen_policy_move_mount(Profile &prof, int &count,
opt_flags & MS_MOVE_FLAGS))
goto fail;
vec[3] = flagsbuf;
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms, audit == AUDIT_FORCE ? perms : 0,
if (!prof.policy.rules->add_rule_vec(rule_mode, perms, audit == AUDIT_FORCE ? perms : 0,
4, vec,
parseopts, false))
goto fail;
@ -1002,7 +1002,7 @@ int mnt_rule::gen_policy_new_mount(Profile &prof, int &count,
tmpaudit = audit == AUDIT_FORCE ? perms : 0;
}
/* rule for match without required data || data MATCH_CONT */
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, tmpperms, tmpaudit, 4,
if (!prof.policy.rules->add_rule_vec(rule_mode, tmpperms, tmpaudit, 4,
vec, parseopts, false))
goto fail;
count++;
@ -1013,7 +1013,7 @@ int mnt_rule::gen_policy_new_mount(Profile &prof, int &count,
if (!build_mnt_opts(optsbuf, opts))
goto fail;
vec[4] = optsbuf.c_str();
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms,
if (!prof.policy.rules->add_rule_vec(rule_mode, perms,
audit == AUDIT_FORCE ? perms : 0,
5, vec, parseopts, false))
goto fail;
@ -1105,7 +1105,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
if (!convert_entry(mntbuf, mnt_point))
goto fail;
vec[0] = mntbuf.c_str();
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms,
if (!prof.policy.rules->add_rule_vec(rule_mode, perms,
(audit == AUDIT_FORCE ? perms : 0), 1, vec,
parseopts, false))
goto fail;
@ -1120,7 +1120,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
if (!clear_and_convert_entry(devbuf, device))
goto fail;
vec[1] = devbuf.c_str();
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms,
if (!prof.policy.rules->add_rule_vec(rule_mode, perms,
(audit == AUDIT_FORCE ? perms : 0), 2, vec,
parseopts, false))
goto fail;

View file

@ -231,10 +231,10 @@ int mqueue_rule::gen_policy_re(Profile &prof)
/* store perms at name match so label doesn't need
* to be checked
*/
if (!label && !prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, 1, vec, parseopts, false))
if (!label && !prof.policy.rules->add_rule_vec(rule_mode, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, 1, vec, parseopts, false))
goto fail;
/* also provide label match with perm */
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, size, vec, parseopts, false))
if (!prof.policy.rules->add_rule_vec(rule_mode, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, size, vec, parseopts, false))
goto fail;
}
}
@ -266,10 +266,10 @@ int mqueue_rule::gen_policy_re(Profile &prof)
}
if (perms & AA_VALID_SYSV_MQ_PERMS) {
if (!label && !prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, 1, vec, parseopts, false))
if (!label && !prof.policy.rules->add_rule_vec(rule_mode, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, 1, vec, parseopts, false))
goto fail;
/* also provide label match with perm */
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, size, vec, parseopts, false))
if (!prof.policy.rules->add_rule_vec(rule_mode, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, size, vec, parseopts, false))
goto fail;
}
}

View file

@ -697,7 +697,7 @@ bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &st
buf = oss.str();
/* AA_CONT_MATCH mapping (cond_perms) only applies to perms, not audit */
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, cond_perms,
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, cond_perms,
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
parseopts))
return false;
@ -710,7 +710,7 @@ bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &st
oss << "\\x00"; /* null transition */
buf = oss.str();
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, cond_perms,
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, cond_perms,
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
parseopts))
return false;
@ -735,7 +735,7 @@ bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mas
if (!features_supports_inet || (family != AF_INET && family != AF_INET6)) {
buf = buffer.str();
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(perms),
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, map_perms(perms),
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
parseopts))
return false;
@ -745,7 +745,7 @@ bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mas
buf = buffer.str();
/* create perms need to be generated excluding the rest of the perms */
if (perms & AA_NET_CREATE) {
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(perms & AA_NET_CREATE) | (AA_CONT_MATCH << 1),
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, map_perms(perms & AA_NET_CREATE) | (AA_CONT_MATCH << 1),
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms & AA_NET_CREATE) : 0,
parseopts))
return false;
@ -797,7 +797,7 @@ bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mas
/* length of queue allowed - not used for now */
listen_buffer << "..";
buf = listen_buffer.str();
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(perms),
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, map_perms(perms),
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
parseopts))
return false;
@ -816,7 +816,7 @@ bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mas
/* socket mapping - not used for now */
opt_buffer << "..";
buf = opt_buffer.str();
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(perms),
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, map_perms(perms),
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
parseopts))
return false;

View file

@ -507,7 +507,8 @@ static int process_profile_name_xmatch(Profile *prof)
aare_rules *rules = new aare_rules();
if (!rules)
return FALSE;
if (!rules->add_rule(tbuf.c_str(), 0, AA_MAY_EXEC, 0, parseopts)) {
if (!rules->add_rule(tbuf.c_str(), RULE_ALLOW,
AA_MAY_EXEC, 0, parseopts)) {
delete rules;
return FALSE;
}
@ -520,7 +521,9 @@ static int process_profile_name_xmatch(Profile *prof)
ptype = convert_aaregex_to_pcre(alt->name, 0,
glob_default,
tbuf, &len);
if (!rules->add_rule(tbuf.c_str(), 0, AA_MAY_EXEC, 0, parseopts)) {
if (!rules->add_rule(tbuf.c_str(),
RULE_ALLOW, AA_MAY_EXEC,
0, parseopts)) {
delete rules;
return FALSE;
}
@ -642,14 +645,14 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
if (entry->rule_mode == RULE_DENY) {
if ((entry->perms & ~AA_LINK_BITS) &&
!is_change_profile_perms(entry->perms) &&
!dfarules->add_rule(tbuf.c_str(), entry->rule_mode == RULE_DENY,
!dfarules->add_rule(tbuf.c_str(), entry->rule_mode,
entry->perms & ~(AA_LINK_BITS | AA_CHANGE_PROFILE),
entry->audit == AUDIT_FORCE ? entry->perms & ~(AA_LINK_BITS | AA_CHANGE_PROFILE) : 0,
parseopts))
return FALSE;
} else if (!is_change_profile_perms(entry->perms)) {
if (!dfarules->add_rule(tbuf.c_str(),
entry->rule_mode == RULE_DENY, entry->perms,
entry->rule_mode, entry->perms,
entry->audit == AUDIT_FORCE ? entry->perms : 0,
parseopts))
return FALSE;
@ -674,7 +677,7 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
perms |= LINK_TO_LINK_SUBSET(perms);
vec[1] = "/[^/].*";
}
if (!dfarules->add_rule_vec(entry->rule_mode == RULE_DENY, perms, entry->audit == AUDIT_FORCE ? perms & AA_LINK_BITS : 0, 2, vec, parseopts, false))
if (!dfarules->add_rule_vec(entry->rule_mode, perms, entry->audit == AUDIT_FORCE ? perms & AA_LINK_BITS : 0, 2, vec, parseopts, false))
return FALSE;
}
if (is_change_profile_perms(entry->perms)) {
@ -725,13 +728,13 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
}
/* regular change_profile rule */
if (!dfarules->add_rule_vec(entry->rule_mode == RULE_DENY,
if (!dfarules->add_rule_vec(entry->rule_mode,
AA_CHANGE_PROFILE | onexec_perms,
0, index - 1, &vec[1], parseopts, false))
return FALSE;
/* onexec rules - both rules are needed for onexec */
if (!dfarules->add_rule_vec(entry->rule_mode == RULE_DENY, onexec_perms,
if (!dfarules->add_rule_vec(entry->rule_mode, onexec_perms,
0, 1, vec, parseopts, false))
return FALSE;
@ -740,7 +743,7 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
* unsafe exec transitions
*/
onexec_perms |= (entry->perms & (AA_EXEC_BITS | ALL_AA_EXEC_UNSAFE));
if (!dfarules->add_rule_vec(entry->rule_mode == RULE_DENY, onexec_perms,
if (!dfarules->add_rule_vec(entry->rule_mode, onexec_perms,
0, index, vec, parseopts, false))
return FALSE;
}
@ -980,6 +983,80 @@ int post_process_policydb_ents(Profile *prof)
return TRUE;
}
static bool gen_net_rule(Profile *prof, u16 family, unsigned int type_mask,
bool audit, rule_mode_t rmode) {
std::ostringstream buffer;
std::string buf;
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_NETV8;
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ((family & 0xff00) >> 8);
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (family & 0xff);
if (type_mask > 0xffff) {
buffer << "..";
} else {
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ((type_mask & 0xff00) >> 8);
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (type_mask & 0xff);
}
buf = buffer.str();
if (!prof->policy.rules->add_rule(buf.c_str(), rmode, map_perms(AA_VALID_NET_PERMS),
audit ? map_perms(AA_VALID_NET_PERMS) : 0,
parseopts))
return false;
return true;
}
static bool gen_af_rules(Profile *prof, u16 family, unsigned int type_mask,
unsigned int audit_mask, rule_mode_t rmode)
{
if (type_mask > 0xffff && audit_mask > 0xffff) {
/* instead of generating multiple rules wild card type */
return gen_net_rule(prof, family, type_mask, audit_mask, rmode);
} else {
int t;
/* generate rules for types that are set */
for (t = 0; t < 16; t++) {
if (type_mask & (1 << t)) {
if (!gen_net_rule(prof, family, t,
audit_mask & (1 << t),
rmode))
return false;
}
}
}
return true;
}
bool post_process_policydb_net(Profile *prof)
{
u16 af;
/* no network rules defined so we don't have generate them */
if (!prof->net.allow)
return true;
/* generate rules if the af has something set */
for (af = AF_UNSPEC; af < get_af_max(); af++) {
if (prof->net.allow[af] ||
prof->net.deny[af] ||
prof->net.audit[af] ||
prof->net.quiet[af]) {
if (!gen_af_rules(prof, af, prof->net.allow[af],
prof->net.audit[af],
{ RULE_ALLOW}))
return false;
if (!gen_af_rules(prof, af, prof->net.deny[af],
prof->net.quiet[af],
{ RULE_DENY}))
return false;
}
}
return true;
}
#define MAKE_STR(X) #X
#define CLASS_STR(X) "\\d" MAKE_STR(X)
#define MAKE_SUB_STR(X) "\\000" MAKE_STR(X)
@ -1013,9 +1090,8 @@ int process_profile_policydb(Profile *prof)
/* insert entries to show indicate what compiler/policy expects
* to be supported
*/
if (features_supports_userns &&
!prof->policy.rules->add_rule(mediates_ns, 0, AA_MAY_READ, 0, parseopts))
!prof->policy.rules->add_rule(mediates_ns, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
goto out;
/* don't add mediated classes to unconfined profiles */
@ -1023,35 +1099,35 @@ int process_profile_policydb(Profile *prof)
prof->flags.mode != MODE_DEFAULT_ALLOW) {
/* note: this activates fs based unix domain sockets mediation on connect */
if (kernel_abi_version > 5 &&
!prof->policy.rules->add_rule(mediates_file, 0, AA_MAY_READ, 0, parseopts))
!prof->policy.rules->add_rule(mediates_file, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
goto out;
if (features_supports_mount &&
!prof->policy.rules->add_rule(mediates_mount, 0, AA_MAY_READ, 0, parseopts))
!prof->policy.rules->add_rule(mediates_mount, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
goto out;
if (features_supports_dbus &&
!prof->policy.rules->add_rule(mediates_dbus, 0, AA_MAY_READ, 0, parseopts))
!prof->policy.rules->add_rule(mediates_dbus, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
goto out;
if (features_supports_signal &&
!prof->policy.rules->add_rule(mediates_signal, 0, AA_MAY_READ, 0, parseopts))
!prof->policy.rules->add_rule(mediates_signal, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
goto out;
if (features_supports_ptrace &&
!prof->policy.rules->add_rule(mediates_ptrace, 0, AA_MAY_READ, 0, parseopts))
!prof->policy.rules->add_rule(mediates_ptrace, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
goto out;
if (features_supports_networkv8 &&
!prof->policy.rules->add_rule(mediates_netv8, 0, AA_MAY_READ, 0, parseopts))
!prof->policy.rules->add_rule(mediates_netv8, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
goto out;
if (features_supports_unix &&
(!prof->policy.rules->add_rule(mediates_extended_net, 0, AA_MAY_READ, 0, parseopts) ||
!prof->policy.rules->add_rule(mediates_net_unix, 0, AA_MAY_READ, 0, parseopts)))
(!prof->policy.rules->add_rule(mediates_extended_net, RULE_ALLOW, AA_MAY_READ, 0, parseopts) ||
!prof->policy.rules->add_rule(mediates_net_unix, RULE_ALLOW, AA_MAY_READ, 0, parseopts)))
goto out;
if (features_supports_posix_mqueue &&
!prof->policy.rules->add_rule(mediates_posix_mqueue, 0, AA_MAY_READ, 0, parseopts))
!prof->policy.rules->add_rule(mediates_posix_mqueue, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
goto out;
if (features_supports_sysv_mqueue &&
!prof->policy.rules->add_rule(mediates_sysv_mqueue, 0, AA_MAY_READ, 0, parseopts))
!prof->policy.rules->add_rule(mediates_sysv_mqueue, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
goto out;
if (features_supports_io_uring &&
!prof->policy.rules->add_rule(mediates_io_uring, 0, AA_MAY_READ, 0, parseopts))
!prof->policy.rules->add_rule(mediates_io_uring, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
goto out;
}
@ -1060,11 +1136,11 @@ int process_profile_policydb(Profile *prof)
// This requires file rule processing happen first
if (!prof->dfa.rules->rule_count) {
// add null dfa
if (!prof->dfa.rules->add_rule(deny_file, true, AA_MAY_READ, 0, parseopts))
if (!prof->dfa.rules->add_rule(deny_file, RULE_DENY, AA_MAY_READ, 0, parseopts))
goto out;
}
if (!prof->policy.rules->rule_count) {
if (!prof->policy.rules->add_rule(mediates_file, true, AA_MAY_READ, 0, parseopts))
if (!prof->policy.rules->add_rule(mediates_file, RULE_DENY, AA_MAY_READ, 0, parseopts))
goto out;
}
int xmatch_len = 0;

View file

@ -133,7 +133,8 @@ int ptrace_rule::gen_policy_re(Profile &prof)
buf = buffer.str();
if (perms & AA_VALID_PTRACE_PERMS) {
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, perms, audit == AUDIT_FORCE ? perms : 0,
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, perms,
audit == AUDIT_FORCE ? perms : 0,
parseopts))
goto fail;
}

View file

@ -316,7 +316,8 @@ int signal_rule::gen_policy_re(Profile &prof)
buf = buffer.str();
if (perms & (AA_MAY_SEND | AA_MAY_RECEIVE)) {
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, perms, audit == AUDIT_FORCE ? perms : 0,
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode,
perms, audit == AUDIT_FORCE ? perms : 0,
parseopts))
goto fail;
}

View file

@ -95,7 +95,7 @@ int userns_rule::gen_policy_re(Profile &prof)
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_NS;
buf = buffer.str();
if (perms & AA_VALID_USERNS_PERMS) {
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, perms,
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, perms,
audit == AUDIT_FORCE ? perms : 0,
parseopts))
goto fail;