diff --git a/parser/af_unix.cc b/parser/af_unix.cc index 4e3b97077..a098ee7f3 100644 --- a/parser/af_unix.cc +++ b/parser/af_unix.cc @@ -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,10 +421,12 @@ 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, - map_perms(mask & AA_NET_OPT), - map_perms(audit == AUDIT_FORCE ? AA_NET_OPT : 0), - parseopts)) + 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), + parseopts)) goto fail; } mask &= ~AA_LOCAL_NET_PERMS | AA_NET_ACCEPT; @@ -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; } diff --git a/parser/dbus.cc b/parser/dbus.cc index fc028de6c..163d8c396 100644 --- a/parser/dbus.cc +++ b/parser/dbus.cc @@ -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)) diff --git a/parser/io_uring.cc b/parser/io_uring.cc index 3425ea36c..687b6d08c 100644 --- a/parser/io_uring.cc +++ b/parser/io_uring.cc @@ -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; diff --git a/parser/libapparmor_re/aare_rules.cc b/parser/libapparmor_re/aare_rules.cc index 75883c7e7..08e8e6fb9 100644 --- a/parser/libapparmor_re/aare_rules.cc +++ b/parser/libapparmor_re/aare_rules.cc @@ -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"; diff --git a/parser/libapparmor_re/aare_rules.h b/parser/libapparmor_re/aare_rules.h index 8a22afb89..ca24c7eb2 100644 --- a/parser/libapparmor_re/aare_rules.h +++ b/parser/libapparmor_re/aare_rules.h @@ -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 &perms_table, diff --git a/parser/libapparmor_re/expr-tree.h b/parser/libapparmor_re/expr-tree.h index 95d68f8c7..8341b4ff9 100644 --- a/parser/libapparmor_re/expr-tree.h +++ b/parser/libapparmor_re/expr-tree.h @@ -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 { stackpos; diff --git a/parser/libapparmor_re/hfa.cc b/parser/libapparmor_re/hfa.cc index 323f3236a..75e43e36a 100644 --- a/parser/libapparmor_re/hfa.cc +++ b/parser/libapparmor_re/hfa.cc @@ -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 &eq) void DFA::compute_perms_table_ent(State *state, size_t pos, vector &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(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"); diff --git a/parser/libapparmor_re/hfa.h b/parser/libapparmor_re/hfa.h index 575b23cc8..2c5ab15d6 100644 --- a/parser/libapparmor_re/hfa.h +++ b/parser/libapparmor_re/hfa.h @@ -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; diff --git a/parser/libapparmor_re/policy_compat.cc b/parser/libapparmor_re/policy_compat.cc index 8213109a8..5b8106647 100644 --- a/parser/libapparmor_re/policy_compat.cc +++ b/parser/libapparmor_re/policy_compat.cc @@ -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)) diff --git a/parser/libapparmor_re/policy_compat.h b/parser/libapparmor_re/policy_compat.h index f19c14b20..7563c41bf 100644 --- a/parser/libapparmor_re/policy_compat.h +++ b/parser/libapparmor_re/policy_compat.h @@ -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 */ diff --git a/parser/mount.cc b/parser/mount.cc index 31b43ef6d..bbd2bab12 100644 --- a/parser/mount.cc +++ b/parser/mount.cc @@ -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; diff --git a/parser/mqueue.cc b/parser/mqueue.cc index 4d91011ef..8166110c3 100644 --- a/parser/mqueue.cc +++ b/parser/mqueue.cc @@ -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; } } diff --git a/parser/network.cc b/parser/network.cc index 939f2112f..55bf17170 100644 --- a/parser/network.cc +++ b/parser/network.cc @@ -697,7 +697,7 @@ bool network_rule::gen_ip_conds(Profile &prof, std::list &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 &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; diff --git a/parser/parser_regex.c b/parser/parser_regex.c index a1c208de4..b6600266d 100644 --- a/parser/parser_regex.c +++ b/parser/parser_regex.c @@ -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; diff --git a/parser/ptrace.cc b/parser/ptrace.cc index 3a4bbf690..9627f84b4 100644 --- a/parser/ptrace.cc +++ b/parser/ptrace.cc @@ -133,8 +133,9 @@ 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, - parseopts)) + if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, perms, + audit == AUDIT_FORCE ? perms : 0, + parseopts)) goto fail; } diff --git a/parser/signal.cc b/parser/signal.cc index b2eda5ac2..a161c275a 100644 --- a/parser/signal.cc +++ b/parser/signal.cc @@ -316,8 +316,9 @@ 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, - parseopts)) + if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, + perms, audit == AUDIT_FORCE ? perms : 0, + parseopts)) goto fail; } diff --git a/parser/userns.cc b/parser/userns.cc index cbef5e580..96a60c649 100644 --- a/parser/userns.cc +++ b/parser/userns.cc @@ -95,9 +95,9 @@ 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, - audit == AUDIT_FORCE ? perms : 0, - parseopts)) + if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, perms, + audit == AUDIT_FORCE ? perms : 0, + parseopts)) goto fail; }