diff --git a/binutils/aa_load.c b/binutils/aa_load.c index 6133e899a..b7e6eca28 100644 --- a/binutils/aa_load.c +++ b/binutils/aa_load.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include diff --git a/parser/af_unix.cc b/parser/af_unix.cc index f9b977a49..4a0039a5b 100644 --- a/parser/af_unix.cc +++ b/parser/af_unix.cc @@ -30,6 +30,8 @@ #include "profile.h" #include "af_unix.h" +using namespace std; + /* See unix(7) for autobind address definition */ #define autobind_address_pattern "\\x00[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]"; diff --git a/parser/apparmor.d.pod b/parser/apparmor.d.pod index dfcb37077..9533155c8 100644 --- a/parser/apparmor.d.pod +++ b/parser/apparmor.d.pod @@ -1196,17 +1196,17 @@ using inode access times. Matches only: =item B<< mount options=(ro, atime) options in (nodev, user) /dev/foo -E /mnt/, >> -allow mounting /dev/foo on /mmt/ read only and using inode access times or -allow mounting /dev/foo on /mnt/ with some combination of 'nodev' and 'user'. +allow mounting /dev/foo on /mnt/ read only and using inode access times, in +addition to allowing some combination of 'nodev' and 'user' to be added on top. Matches only: $ mount -o ro,atime /dev/foo /mnt - $ mount -o nodev /dev/foo /mnt + $ mount -o ro,atime,nodev /dev/foo /mnt - $ mount -o user /dev/foo /mnt + $ mount -o ro,atime,user /dev/foo /mnt - $ mount -o nodev,user /dev/foo /mnt + $ mount -o ro,atime,nodev,user /dev/foo /mnt =back diff --git a/parser/file_cache.h b/parser/file_cache.h index 7483be22d..81ddd7d27 100644 --- a/parser/file_cache.h +++ b/parser/file_cache.h @@ -21,14 +21,12 @@ #include #include -using namespace std; - /* TODO: have includecache be a frontend for file cache, don't just * store name. */ class IncludeCache_t { public: - set cache; + std::set cache; IncludeCache_t() = default; virtual ~IncludeCache_t() = default; @@ -39,7 +37,7 @@ public: } bool insert(const char *name) { - pair::iterator,bool> res = cache.insert(name); + std::pair::iterator,bool> res = cache.insert(name); if (res.second == false) { return false; } diff --git a/parser/lib.c b/parser/lib.c index a105fa379..a3d21f9a1 100644 --- a/parser/lib.c +++ b/parser/lib.c @@ -28,6 +28,8 @@ #include "lib.h" #include "parser.h" +using namespace std; + int dirat_for_each(int dirfd, const char *name, void *data, int (* cb)(int, const char *, struct stat *, void *)) { diff --git a/parser/libapparmor_re/aare_rules.cc b/parser/libapparmor_re/aare_rules.cc index d5546dde4..f2ddc564c 100644 --- a/parser/libapparmor_re/aare_rules.cc +++ b/parser/libapparmor_re/aare_rules.cc @@ -34,6 +34,7 @@ #include "chfa.h" #include "../immunix.h" +using namespace std; aare_rules::~aare_rules(void) { diff --git a/parser/libapparmor_re/aare_rules.h b/parser/libapparmor_re/aare_rules.h index 91ae289b3..45f277f02 100644 --- a/parser/libapparmor_re/aare_rules.h +++ b/parser/libapparmor_re/aare_rules.h @@ -59,7 +59,7 @@ public: class UniquePermsCache { public: - typedef map UniquePermMap; + typedef std::map UniquePermMap; typedef UniquePermMap::iterator iterator; UniquePermMap nodes; @@ -89,7 +89,7 @@ public: node = new ExactMatchFlag(priority, perms, audit); else node = new MatchFlag(priority, perms, audit); - pair val = nodes.insert(make_pair(tmp, node)); + std::pair val = nodes.insert(std::make_pair(tmp, node)); if (val.second == false) { delete node; return val.first->second; @@ -121,17 +121,17 @@ class aare_rules { 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, + std::vector &perms_table, optflags const &opts, bool filedfa, bool extended_perms, bool prompt); void *create_dfablob(size_t *size, int *min_match_len, - vector &perms_table, + std::vector &perms_table, optflags const &opts, bool filedfa, bool extended_perms, bool prompt); void *create_welded_dfablob(aare_rules *file_rules, size_t *size, int *min_match_len, size_t *new_start, - vector &perms_table, + std::vector &perms_table, optflags const &opts, bool extended_perms, bool prompt); }; diff --git a/parser/libapparmor_re/chfa.cc b/parser/libapparmor_re/chfa.cc index 809bcefed..d0e3a60af 100644 --- a/parser/libapparmor_re/chfa.cc +++ b/parser/libapparmor_re/chfa.cc @@ -37,6 +37,8 @@ #include "../policydb.h" #include "flex-tables.h" +using namespace std; + void CHFA::init_free_list(vector > &free_list, size_t prev, size_t start) { diff --git a/parser/libapparmor_re/chfa.h b/parser/libapparmor_re/chfa.h index cc36e8580..983c664e9 100644 --- a/parser/libapparmor_re/chfa.h +++ b/parser/libapparmor_re/chfa.h @@ -32,39 +32,37 @@ #define MATCH_FLAG_OOB_TRANSITION 0x20000000 #define base_mask_size(X) ((X) & ~BASE32_FLAGS) -using namespace std; - -typedef vector > DefaultBase; -typedef vector > NextCheck; +typedef std::vector > DefaultBase; +typedef std::vector > NextCheck; class CHFA { public: CHFA(void); - CHFA(DFA &dfa, map &eq, optflags const &opts, + CHFA(DFA &dfa, std::map &eq, optflags const &opts, bool permindex, bool prompt); void dump(ostream & os); void flex_table(ostream &os, optflags const &opts); - void init_free_list(vector > &free_list, + void init_free_list(std::vector > &free_list, size_t prev, size_t start); - bool fits_in(vector > &free_list, size_t base, + bool fits_in(std::vector > &free_list, size_t base, StateTrans &cases); - void insert_state(vector > &free_list, + void insert_state(std::vector > &free_list, State *state, DFA &dfa); void weld_file_to_policy(CHFA &file_chfa, size_t &new_start, bool accept_idx, bool prompt, - vector &policy_perms, - vector &file_perms); + std::vector &policy_perms, + std::vector &file_perms); // private: // sigh templates suck, friend declaration does not work so for now // make these public - vector accept; - vector accept2; + std::vector accept; + std::vector accept2; DefaultBase default_base; NextCheck next_check; const State *start; Renumber_Map num; - map eq; + std::map eq; unsigned int chfaflags; private: transchar max_eq; diff --git a/parser/libapparmor_re/expr-tree.cc b/parser/libapparmor_re/expr-tree.cc index 184d51515..420b7a37b 100644 --- a/parser/libapparmor_re/expr-tree.cc +++ b/parser/libapparmor_re/expr-tree.cc @@ -38,6 +38,8 @@ #include "expr-tree.h" #include "apparmor_re.h" +using namespace std; + /* Use a single static EpsNode as it carries no node specific information */ EpsNode epsnode; diff --git a/parser/libapparmor_re/expr-tree.h b/parser/libapparmor_re/expr-tree.h index 3e0c5b085..970020040 100644 --- a/parser/libapparmor_re/expr-tree.h +++ b/parser/libapparmor_re/expr-tree.h @@ -44,8 +44,6 @@ #include "../perms.h" #include "apparmor_re.h" -using namespace std; - /* * transchar - representative input character for state transitions * @@ -146,9 +144,9 @@ public: class Chars { public: - set chars; + std::set chars; - typedef set::iterator iterator; + typedef std::set::iterator iterator; iterator begin() { return chars.begin(); } iterator end() { return chars.end(); } @@ -166,11 +164,11 @@ public: { return chars.find(key); } - pair insert(transchar c) + std::pair insert(transchar c) { return chars.insert(c); } - pair insert(char c) + std::pair insert(char c) { transchar tmp(c); return chars.insert(tmp); @@ -181,9 +179,9 @@ public: ostream &operator<<(ostream &os, transchar c); /* Compute the union of two sets. */ -template set operator+(const set &a, const set &b) +template std::set operator+(const std::set &a, const std::set &b) { - set c(a); + std::set c(a); c.insert(b.begin(), b.end()); return c; } @@ -196,7 +194,7 @@ template set operator+(const set &a, const set &b) */ class Node; class ImportantNode; -typedef set NodeSet; +typedef std::set NodeSet; /** * Text-dump a state (for debugging). @@ -212,12 +210,12 @@ ostream &operator<<(ostream &os, const NodeSet &state); * enumerating all the explicit tranitions for default matches. */ typedef struct Cases { - typedef map::iterator iterator; + typedef std::map::iterator iterator; iterator begin() { return cases.begin(); } iterator end() { return cases.end(); } Cases(): otherwise(0) { } - map cases; + std::map cases; NodeSet *otherwise; } Cases; @@ -891,7 +889,8 @@ public: { type_flags |= NODE_TYPE_MATCHFLAG; } - ostream &dump(ostream &os) override { return os << "< 0x" << hex << perms << std::dec << '>'; } + + ostream &dump(ostream &os) override { return os << "< 0x" << std::hex << perms << std::dec << '>'; } int priority; perm32_t perms; @@ -925,7 +924,7 @@ public: /* Traverse the syntax tree depth-first in an iterator-like manner. */ class depth_first_traversal { - stackpos; + std::stackpos; void push_left(Node *node) { pos.push(node); @@ -1051,7 +1050,7 @@ struct deref_less_than { class NodeVecCache: public CacheStats { public: - set cache; + std::set cache; NodeVecCache(void): cache() { }; ~NodeVecCache() override { clear(); }; @@ -1060,7 +1059,7 @@ public: void clear() { - for (set::iterator i = cache.begin(); + for (std::set::iterator i = cache.begin(); i != cache.end(); i++) { delete *i; } @@ -1072,7 +1071,7 @@ public: { if (!nodes) return NULL; - pair::iterator,bool> uniq; + std::pair::iterator,bool> uniq; NodeVec *nv = new NodeVec(nodes); uniq = cache.insert(nv); if (uniq.second == false) { diff --git a/parser/libapparmor_re/hfa.cc b/parser/libapparmor_re/hfa.cc index 470b58871..45e0dff04 100644 --- a/parser/libapparmor_re/hfa.cc +++ b/parser/libapparmor_re/hfa.cc @@ -38,6 +38,8 @@ #include "../immunix.h" #include "../perms.h" +using namespace std; + ostream &operator<<(ostream &os, const CacheStats &cache) { /* dump the state label */ @@ -1443,9 +1445,31 @@ static int pri_update_perm(optflags const &opts, vector &priority, int i, MatchFlag *match, perms_t &perms, perms_t &exact, bool filedfa) { - if (priority[i] > match->priority) { + // scaling priority *4 + int pri = match->priority<<2; + + /* use priority to get proper ordering and application of the type + * of match flag. + * + * Note: this is the last use of priority, it is dropped and not + * used in the backend. + */ + if (match->is_type(NODE_TYPE_DENYMATCHFLAG)) + pri += 3; + // exact match must be same priority as allow as its audit + // flags has the same priority. + // current no ALLOWMATCHFLAG it is just absence of other flags + // so it has to be second last in this list, using !last + // until this gets fixed + else if (match->is_type(NODE_TYPE_EXACTMATCHFLAG) || + (!match->is_type(NODE_TYPE_PROMPTMATCHFLAG))) + pri += 2; + else if (match->is_type(NODE_TYPE_PROMPTMATCHFLAG)) + pri += 1; + + if (priority[i] > pri) { if (opts.dump & DUMP_DFA_PERMS) - cerr << " " << match << "[" << i << "]=" << priority[i] << " > " << match->priority << " SKIPPING " << hex << (match->perms) << "/" << (match->audit) << dec << "\n"; + cerr << " " << match << "[" << i << "]=" << priority[i] << " > " << pri << " SKIPPING " << hex << (match->perms) << "/" << (match->audit) << dec << "\n"; return 0; } @@ -1461,8 +1485,8 @@ static int pri_update_perm(optflags const &opts, vector &priority, int i, if (match->perms & AA_EXEC_INHERIT) { xmask |= AA_USER_EXEC_MMAP; //USER_EXEC_MAP = 6 - if (priority[6] < match->priority) - priority[6] = match->priority; + if (priority[6] < pri) + priority[6] = pri; } amask = mask | xmask; } else if (mask & AA_OTHER_EXEC) { @@ -1471,8 +1495,8 @@ static int pri_update_perm(optflags const &opts, vector &priority, int i, if (match->perms & AA_OTHER_EXEC_INHERIT) { xmask |= AA_OTHER_EXEC_MMAP; //OTHER_EXEC_MAP = 20 - if (priority[20] < match->priority) - priority[20] = match->priority; + if (priority[20] < pri) + priority[20] = pri; } amask = mask | xmask; } else if (((mask & AA_USER_EXEC_MMAP) && @@ -1481,17 +1505,17 @@ static int pri_update_perm(optflags const &opts, vector &priority, int i, (match->perms & AA_OTHER_EXEC_INHERIT))) { // if exec && ix we handled mmp above if (opts.dump & DUMP_DFA_PERMS) - cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << match->priority << " SKIPPING mmap unmasked " << hex << match->perms << "/" << match->audit << " masked " << (match->perms & amask) << "/" << (match->audit & amask) << " data " << (perms.allow & mask) << "/" << (perms.audit & mask) << " exact " << (exact.allow & mask) << "/" << (exact.audit & mask) << dec << "\n"; + cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << pri << " SKIPPING mmap unmasked " << hex << match->perms << "/" << match->audit << " masked " << (match->perms & amask) << "/" << (match->audit & amask) << " data " << (perms.allow & mask) << "/" << (perms.audit & mask) << " exact " << (exact.allow & mask) << "/" << (exact.audit & mask) << dec << "\n"; return 0; } } if (opts.dump & DUMP_DFA_PERMS) - cerr << " " << match << "[" << i << "]=" << priority[i] << " vs. " << match->priority << " mask: " << hex << mask << " xmask: " << xmask << " amask: " << amask << dec << "\n"; - if (priority[i] < match->priority) { + cerr << " " << match << "[" << i << "]=" << priority[i] << " vs. " << pri << " mask: " << hex << mask << " xmask: " << xmask << " amask: " << amask << dec << "\n"; + if (priority[i] < pri) { if (opts.dump & DUMP_DFA_PERMS) - cerr << " " << match << "[" << i << "]=" << priority[i] << " < " << match->priority << " clearing " << hex << (perms.allow & amask) << "/" << (perms.audit & amask) << " -> " << dec; - priority[i] = match->priority; + cerr << " " << match << "[" << i << "]=" << priority[i] << " < " << pri << " clearing " << hex << (perms.allow & amask) << "/" << (perms.audit & amask) << " -> " << dec; + priority[i] = pri; perms.clear_bits(amask); exact.clear_bits(amask); if (opts.dump & DUMP_DFA_PERMS) @@ -1501,7 +1525,7 @@ static int pri_update_perm(optflags const &opts, vector &priority, int i, // the if conditions in order of permission priority if (match->is_type(NODE_TYPE_DENYMATCHFLAG)) { if (opts.dump & DUMP_DFA_PERMS) - cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << match->priority << " deny " << hex << (match->perms & amask) << "/" << (match->audit & amask) << dec << "\n"; + cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << pri << " deny " << hex << (match->perms & amask) << "/" << (match->audit & amask) << dec << "\n"; perms.deny |= match->perms & amask; perms.quiet |= match->audit & amask; @@ -1511,11 +1535,11 @@ static int pri_update_perm(optflags const &opts, vector &priority, int i, } else if (match->is_type(NODE_TYPE_EXACTMATCHFLAG)) { /* exact match only asserts dominance on the XTYPE */ if (opts.dump & DUMP_DFA_PERMS) - cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << match->priority << " exact " << hex << (match->perms & amask) << "/" << (match->audit & amask) << dec << "\n"; + cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << pri << " exact " << hex << (match->perms & amask) << "/" << (match->audit & amask) << dec << "\n"; if (filedfa && !is_merged_x_consistent(exact.allow, match->perms & amask)) { if (opts.dump & DUMP_DFA_PERMS) - cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << match->priority << " exact match conflict" << "\n"; + cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << pri << " exact match conflict" << "\n"; return 1; } exact.allow |= match->perms & amask; @@ -1536,11 +1560,11 @@ static int pri_update_perm(optflags const &opts, vector &priority, int i, // allow perms, if exact has been encountered will already be set // if overlaps x here, don't conflict, because exact will override if (opts.dump & DUMP_DFA_PERMS) - cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << match->priority << " allow " << hex << (match->perms & amask) << "/" << (match->audit & amask) << dec << "\n"; + cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << pri << " allow " << hex << (match->perms & amask) << "/" << (match->audit & amask) << dec << "\n"; if (filedfa && !(exact.allow & mask) && !is_merged_x_consistent(perms.allow, match->perms & amask)) { if (opts.dump & DUMP_DFA_PERMS) - cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << match->priority << " allow match conflict" << "\n"; + cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << pri << " allow match conflict" << "\n"; return 1; } // mask off if XTYPE in xmatch @@ -1554,11 +1578,11 @@ static int pri_update_perm(optflags const &opts, vector &priority, int i, } } else { // if (match->is_type(NODE_TYPE_PROMPTMATCHFLAG)) { if (opts.dump & DUMP_DFA_PERMS) - cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << match->priority << " prompt " << hex << (match->perms & amask) << "/" << (match->audit & amask) << dec << "\n"; + cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << pri << " prompt " << hex << (match->perms & amask) << "/" << (match->audit & amask) << dec << "\n"; if (filedfa && !((exact.allow | perms.allow) & mask) && !is_merged_x_consistent(perms.allow, match->perms & amask)) { if (opts.dump & DUMP_DFA_PERMS) - cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << match->priority << " prompt match conflict" << "\n"; + cerr << " " << match << "[" << i << "]=" << priority[i] << " <= " << pri << " prompt match conflict" << "\n"; return 1; } if ((exact.allow | exact.audit | perms.allow | perms.audit) & mask) { @@ -1584,7 +1608,8 @@ int accept_perms(optflags const &opts, NodeVec *state, perms_t &perms, { int error = 0; perms_t exact; - std::vector priority(sizeof(perm32_t)*8, MIN_INTERNAL_PRIORITY); // 32 but wan't tied to perm32_t + // scaling priority by *4 + std::vector priority(sizeof(perm32_t)*8, MIN_INTERNAL_PRIORITY<<2); // 32 but wan't tied to perm32_t perms.clear(); if (!state) diff --git a/parser/libapparmor_re/hfa.h b/parser/libapparmor_re/hfa.h index af66c57ce..c442a6a0f 100644 --- a/parser/libapparmor_re/hfa.h +++ b/parser/libapparmor_re/hfa.h @@ -42,8 +42,8 @@ extern int prompt_compat_mode; class State; -typedef map StateTrans; -typedef list Partition; +typedef std::map StateTrans; +typedef std::list Partition; #include "../immunix.h" @@ -62,9 +62,9 @@ public: } ostream &dump(ostream &os) { - os << "(0x " << hex + os << "(0x " << std::hex << allow << "/" << deny << "/" << "/" << prompt << "/" << audit << "/" << quiet - << ')' << dec; + << ')' << std::dec; return os; } @@ -317,11 +317,11 @@ public: class NodeMap: public CacheStats { public: - typedef map::iterator iterator; + typedef std::map::iterator iterator; iterator begin() { return cache.begin(); } iterator end() { return cache.end(); } - map cache; + std::map cache; NodeMap(void): cache() { }; ~NodeMap() override { clear(); }; @@ -334,10 +334,10 @@ public: CacheStats::clear(); } - pair insert(ProtoState &proto, State *state) + std::pair insert(ProtoState &proto, State *state) { - pair uniq; - uniq = cache.insert(make_pair(proto, state)); + std::pair uniq; + uniq = cache.insert(std::make_pair(proto, state)); if (uniq.second == false) { dup++; } else { @@ -349,7 +349,7 @@ public: } }; -typedef map Renumber_Map; +typedef std::map Renumber_Map; /* Transitions in the DFA. */ class DFA { @@ -360,7 +360,7 @@ class DFA { NodeSet *nnodes, State *other); void update_state_transitions(optflags const &opts, State *state); void process_work_queue(const char *header, optflags const &); - void dump_diff_chain(ostream &os, map &relmap, + void dump_diff_chain(ostream &os, std::map &relmap, Partition &chain, State *state, unsigned int &count, unsigned int &total, unsigned int &max); @@ -369,7 +369,7 @@ class DFA { NodeVecCache anodes_cache; NodeVecCache nnodes_cache; NodeMap node_map; - list work_queue; + std::list work_queue; public: DFA(Node *root, optflags const &flags, bool filedfa); @@ -394,14 +394,14 @@ public: void dump_uniq_perms(const char *s); ostream &dump_partition(ostream &os, Partition &p); ostream &dump_partitions(ostream &os, const char *description, - list &partitions); - map equivalence_classes(optflags const &flags); - void apply_equivalence_classes(map &eq); + std::list &partitions); + std::map equivalence_classes(optflags const &flags); + void apply_equivalence_classes(std::map &eq); void compute_perms_table_ent(State *state, size_t pos, - vector &perms_table, + std::vector &perms_table, bool prompt); - void compute_perms_table(vector &perms_table, + void compute_perms_table(std::vector &perms_table, bool prompt); unsigned int diffcount; @@ -415,6 +415,6 @@ public: bool filedfa; }; -void dump_equivalence_classes(ostream &os, map &eq); +void dump_equivalence_classes(ostream &os, std::map &eq); #endif /* __LIBAA_RE_HFA_H */ diff --git a/parser/libapparmor_re/parse.y b/parser/libapparmor_re/parse.y index 4a89b81e0..47f3ccc46 100644 --- a/parser/libapparmor_re/parse.y +++ b/parser/libapparmor_re/parse.y @@ -24,6 +24,8 @@ /* #define DEBUG_TREE */ #include "expr-tree.h" +using namespace std; + %} %union { @@ -60,7 +62,7 @@ static inline Chars* insert_char_range(Chars* cset, transchar a, transchar b) %lex-param {YYLEX_PARAM} %parse-param {Node **root} %parse-param {const char *text} -%name-prefix "regex_" +%define api.prefix {regex_} %token CHAR %type regex_char cset_char1 cset_char cset_charN diff --git a/parser/mount.cc b/parser/mount.cc index ce7df3731..a98f067fd 100644 --- a/parser/mount.cc +++ b/parser/mount.cc @@ -228,6 +228,8 @@ #include "profile.h" #include "mount.h" +using namespace std; + struct mnt_keyword_table { const char *keyword; unsigned int set; diff --git a/parser/parser.h b/parser/parser.h index 56fae71f2..005bbe580 100644 --- a/parser/parser.h +++ b/parser/parser.h @@ -41,8 +41,6 @@ #include -using namespace std; - #include diff --git a/parser/parser_interface.c b/parser/parser_interface.c index 5e4724812..8aa752164 100644 --- a/parser/parser_interface.c +++ b/parser/parser_interface.c @@ -41,6 +41,7 @@ #define SD_CODE_SIZE (sizeof(u8)) #define SD_STR_LEN (sizeof(u16)) +using namespace std; int __sd_serialize_profile(int option, aa_kernel_interface *kernel_interface, Profile *prof, int cache_fd); diff --git a/parser/parser_lex.l b/parser/parser_lex.l index 15f0bccd2..f7b3ff4db 100644 --- a/parser/parser_lex.l +++ b/parser/parser_lex.l @@ -46,6 +46,8 @@ #include "policy_cache.h" #include "file_cache.h" +using namespace std; + #ifdef PDEBUG #undef PDEBUG #endif diff --git a/parser/parser_misc.c b/parser/parser_misc.c index 897a21a5c..6f3f40895 100644 --- a/parser/parser_misc.c +++ b/parser/parser_misc.c @@ -66,6 +66,8 @@ void *reallocarray(void *ptr, size_t nmemb, size_t size) #define NULL nullptr #endif +using namespace std; + int is_blacklisted(const char *name, const char *path) { int retval = _aa_is_blacklisted(name); diff --git a/parser/parser_policy.c b/parser/parser_policy.c index 58d4fad01..7e0743f3d 100644 --- a/parser/parser_policy.c +++ b/parser/parser_policy.c @@ -45,6 +45,7 @@ #endif #define NPDEBUG(fmt, args...) /* Do nothing */ +using namespace std; ProfileList policy_list; diff --git a/parser/parser_yacc.y b/parser/parser_yacc.y index 4d9c62762..21ff2d783 100644 --- a/parser/parser_yacc.y +++ b/parser/parser_yacc.y @@ -45,6 +45,7 @@ #include #include +using namespace std; #define CIDR_32 htonl(0xffffffff) #define CIDR_24 htonl(0xffffff00) diff --git a/parser/profile.cc b/parser/profile.cc index 2f235e587..52a195b9d 100644 --- a/parser/profile.cc +++ b/parser/profile.cc @@ -21,6 +21,8 @@ #include #include +using namespace std; + const char *profile_mode_table[] = { "", "enforce", diff --git a/parser/profile.h b/parser/profile.h index 207c9b57e..e7df0f90e 100644 --- a/parser/profile.h +++ b/parser/profile.h @@ -42,16 +42,16 @@ struct deref_profileptr_lt { class ProfileList { public: - set list; + std::set list; - typedef set::iterator iterator; + typedef std::set::iterator iterator; iterator begin() { return list.begin(); } iterator end() { return list.end(); } ProfileList() { }; virtual ~ProfileList() { clear(); } virtual bool empty(void) { return list.empty(); } - virtual pair insert(Profile *); + virtual std::pair insert(Profile *); virtual void erase(ProfileList::iterator pos); void clear(void); void dump(void); @@ -368,7 +368,7 @@ struct dfa_stuff { void *dfa; size_t size; size_t file_start; /* special start in welded dfa */ - vector perms_table; + std::vector perms_table; dfa_stuff(void): rules(NULL), dfa(NULL), size(0) { } }; @@ -382,7 +382,7 @@ public: void *xmatch; size_t xmatch_size; int xmatch_len; - vector xmatch_perms_table; + std::vector xmatch_perms_table; struct cond_entry_list xattrs; /* char *sub_name; */ /* subdomain name or NULL */ @@ -477,7 +477,7 @@ public: debug_cod_entries(entries); for (RuleList::iterator i = rule_ents.begin(); i != rule_ents.end(); i++) { - (*i)->dump(cout); + (*i)->dump(std::cout); } printf("\n"); @@ -511,7 +511,7 @@ public: void dump_name(bool fqp) { - cout << get_name(fqp);; + std::cout << get_name(fqp);; } void post_parse_profile(void); diff --git a/parser/rule.h b/parser/rule.h index a46cc00f2..f8a101634 100644 --- a/parser/rule.h +++ b/parser/rule.h @@ -25,8 +25,6 @@ #include "perms.h" #include "policydb.h" -using namespace std; - #define PROMPT_COMPAT_UNKNOWN 0 #define PROMPT_COMPAT_IGNORE 1 #define PROMPT_COMPAT_PERMSV2 2 @@ -436,9 +434,9 @@ public: class_rule_t::dump(os); if (saved) - os << "(0x" << hex << perms << "/orig " << saved << ") "; + os << "(0x" << std::hex << perms << "/orig " << saved << ") "; else - os << "(0x" << hex << perms << ") "; + os << "(0x" << std::hex << perms << ") "; return os; } @@ -464,7 +462,7 @@ public: ostream &dump(ostream &os) override { class_rule_t::dump(os); - os << "(0x" << hex << perms << ") "; + os << "(0x" << std::hex << perms << ") "; return os; } diff --git a/parser/signal.cc b/parser/signal.cc index 81502509b..514a5a182 100644 --- a/parser/signal.cc +++ b/parser/signal.cc @@ -30,6 +30,8 @@ #include "parser_yacc.h" #include "signal.h" +using namespace std; + #define MAXMAPPED_SIG 35 #define MINRT_SIG 128 /* base of RT sigs */ #define MAXRT_SIG 32 /* Max RT above MINRT_SIG */ diff --git a/parser/signal.h b/parser/signal.h index 60219c45c..b39e1115f 100644 --- a/parser/signal.h +++ b/parser/signal.h @@ -29,7 +29,7 @@ #define AA_VALID_SIGNAL_PERMS (AA_MAY_SEND | AA_MAY_RECEIVE) -typedef set Signals; +typedef std::set Signals; int find_signal_mapping(const char *sig); int parse_signal_perms(const char *str_perms, perm32_t *perms, int fail); diff --git a/parser/tst/equality.sh b/parser/tst/equality.sh index 6f4ee6082..f0b90379b 100755 --- a/parser/tst/equality.sh +++ b/parser/tst/equality.sh @@ -1223,7 +1223,7 @@ done set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters -if [ $# -eq 0 -o -z $testtype] ; then +if [ $# -eq 0 -o -z "$testtype" ] ; then run_tests "$@" exit $? fi diff --git a/parser/tst/simple_tests/file/priority/front_perms_ok_1.sd b/parser/tst/simple_tests/file/priority/front_perms_ok_1.sd index 2375fd1dc..137a9454a 100644 --- a/parser/tst/simple_tests/file/priority/front_perms_ok_1.sd +++ b/parser/tst/simple_tests/file/priority/front_perms_ok_1.sd @@ -15,10 +15,5 @@ priority=-1 file ux /foo3, priority=-1 file Ux /foo4, priority=-1 file ix /foo5, - priority=-1 file unsafe px /foo6, - priority=-1 file unsafe Px /foo7, - priority=-1 file unsafe ux /foo8, - priority=-1 file unsafe Ux /foo9, - priority=-1 file unsafe ix /foo10, } diff --git a/parser/tst/simple_tests/file/priority/front_perms_ok_2.sd b/parser/tst/simple_tests/file/priority/front_perms_ok_2.sd index f1ee0837a..88db2191f 100644 --- a/parser/tst/simple_tests/file/priority/front_perms_ok_2.sd +++ b/parser/tst/simple_tests/file/priority/front_perms_ok_2.sd @@ -15,10 +15,5 @@ priority=-1 ux /foo3, priority=-1 Ux /foo4, priority=-1 ix /foo5, - priority=-1 unsafe px /foo6, - priority=-1 unsafe Px /foo7, - priority=-1 unsafe ux /foo8, - priority=-1 unsafe Ux /foo9, - priority=-1 unsafe ix /foo10, } diff --git a/parser/tst/simple_tests/file/priority/front_perms_ok_3.sd b/parser/tst/simple_tests/file/priority/front_perms_ok_3.sd new file mode 100644 index 000000000..4140ae0ef --- /dev/null +++ b/parser/tst/simple_tests/file/priority/front_perms_ok_3.sd @@ -0,0 +1,12 @@ +# +#=DESCRIPTION perms before pathname + unsafe keyword +#=EXRESULT PASS +# +/usr/bin/foo { + priority=-1 file unsafe px /foo6, + priority=-1 file unsafe Px /foo7, + priority=-1 file unsafe ux /foo8, + priority=-1 file unsafe Ux /foo9, + priority=-1 file unsafe ix /foo10, + +} diff --git a/parser/tst/simple_tests/file/priority/front_perms_ok_4.sd b/parser/tst/simple_tests/file/priority/front_perms_ok_4.sd new file mode 100644 index 000000000..3a33020eb --- /dev/null +++ b/parser/tst/simple_tests/file/priority/front_perms_ok_4.sd @@ -0,0 +1,13 @@ +# +#=DESCRIPTION perms before pathname + unsafe keyword +#=EXRESULT PASS +# +/usr/bin/foo { + + priority=-1 unsafe px /foo6, + priority=-1 unsafe Px /foo7, + priority=-1 unsafe ux /foo8, + priority=-1 unsafe Ux /foo9, + priority=-1 unsafe ix /foo10, + +} diff --git a/profiles/apparmor.d/ssh-keyscan b/profiles/apparmor.d/ssh-keyscan new file mode 100644 index 000000000..7b05bfbbf --- /dev/null +++ b/profiles/apparmor.d/ssh-keyscan @@ -0,0 +1,30 @@ +#------------------------------------------------------------------ +# Copyright (C) 2025 Canonical Ltd. +# +# 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. +#------------------------------------------------------------------ +# vim: ft=apparmor +# +abi , + +include + +profile ssh-keyscan /usr/bin/ssh-keyscan { + include + include + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + network netlink raw, + + # Allow executable mapping and read for the binary + file mr /usr/bin/ssh-keyscan, + + # Site-specific additions and overrides. See local/README for details. + include if exists +} + diff --git a/utils/apparmor/regex.py b/utils/apparmor/regex.py index 256b5acb1..535918b17 100644 --- a/utils/apparmor/regex.py +++ b/utils/apparmor/regex.py @@ -21,7 +21,7 @@ from apparmor.translations import init_translation _ = init_translation() # Profile parsing Regex -RE_AUDIT_DENY = r'^\s*(?Paudit\s+)?(?Pallow\s+|deny\s+)?' # line start, optionally: leading whitespace, and /deny +RE_PRIORITY_AUDIT_DENY = r'^\s*(priority\s*=\s*(?P[+-]?[0-9]*)\s+)?(?Paudit\s+)?(?Pallow\s+|deny\s+)?' # line start, optionally: leading whitespace, = number, and /deny RE_EOL = r'\s*(?P#.*?)?\s*$' # optional whitespace, optional , optional whitespace, end of the line RE_COMMA_EOL = r'\s*,' + RE_EOL # optional whitespace, comma + RE_EOL @@ -34,8 +34,8 @@ RE_XATTRS = r'(\s+xattrs\s*=\s*\((?P([^)=]+(=[^)=]+)?\s?)+)\)\s*)?' RE_FLAGS = r'(\s+(flags\s*=\s*)?\((?P[^)]+)\))?' RE_PROFILE_END = re.compile(r'^\s*\}' + RE_EOL) -RE_PROFILE_ALL = re.compile(RE_AUDIT_DENY + r'all' + RE_COMMA_EOL) -RE_PROFILE_CAP = re.compile(RE_AUDIT_DENY + r'capability(?P(\s+\S+)+)?' + RE_COMMA_EOL) +RE_PROFILE_ALL = re.compile(RE_PRIORITY_AUDIT_DENY + r'all' + RE_COMMA_EOL) +RE_PROFILE_CAP = re.compile(RE_PRIORITY_AUDIT_DENY + r'capability(?P(\s+\S+)+)?' + RE_COMMA_EOL) RE_PROFILE_ALIAS = re.compile(r'^\s*alias\s+(?P"??.+?"??)\s+->\s*(?P"??.+?"??)' + RE_COMMA_EOL) RE_PROFILE_RLIMIT = re.compile(r'^\s*set\s+rlimit\s+(?P[a-z]+)\s*<=\s*(?P[^ ]+(\s+[a-zA-Z]+)?)' + RE_COMMA_EOL) RE_PROFILE_BOOLEAN = re.compile(r'^\s*(?P\$\{?\w*\}?)\s*=\s*(?Ptrue|false)\s*,?' + RE_EOL, flags=re.IGNORECASE) @@ -43,18 +43,18 @@ RE_PROFILE_VARIABLE = re.compile(r'^\s*(?P@\{?\w+\}?)\s*(?P\+?=)\ RE_PROFILE_CONDITIONAL = re.compile(r'^\s*if\s+(not\s+)?(\$\{?\w*\}?)\s*\{' + RE_EOL) RE_PROFILE_CONDITIONAL_VARIABLE = re.compile(r'^\s*if\s+(not\s+)?defined\s+(@\{?\w+\}?)\s*\{\s*(#.*)?$') RE_PROFILE_CONDITIONAL_BOOLEAN = re.compile(r'^\s*if\s+(not\s+)?defined\s+(\$\{?\w+\}?)\s*\{\s*(#.*)?$') -RE_PROFILE_NETWORK = re.compile(RE_AUDIT_DENY + r'network(?P
\s+.*)?' + RE_COMMA_EOL) +RE_PROFILE_NETWORK = re.compile(RE_PRIORITY_AUDIT_DENY + r'network(?P
\s+.*)?' + RE_COMMA_EOL) RE_PROFILE_CHANGE_HAT = re.compile(r'^\s*\^("??.+?"??)' + RE_COMMA_EOL) RE_PROFILE_HAT_DEF = re.compile(r'^(?P\s*)(?P\^|hat\s+)(?P"??[^)]+?"??)' + RE_FLAGS + r'\s*\{' + RE_EOL) -RE_PROFILE_DBUS = re.compile(RE_AUDIT_DENY + r'(dbus\s*,|dbus(?P
\s+[^#]*)\s*,)' + RE_EOL) -RE_PROFILE_MOUNT = re.compile(RE_AUDIT_DENY + r'((?Pmount|remount|umount|unmount)(?P
\s+[^#]*)?\s*,)' + RE_EOL) -RE_PROFILE_SIGNAL = re.compile(RE_AUDIT_DENY + r'(signal\s*,|signal(?P
\s+[^#]*)\s*,)' + RE_EOL) -RE_PROFILE_PTRACE = re.compile(RE_AUDIT_DENY + r'(ptrace\s*,|ptrace(?P
\s+[^#]*)\s*,)' + RE_EOL) -RE_PROFILE_PIVOT_ROOT = re.compile(RE_AUDIT_DENY + r'(pivot_root\s*,|pivot_root(?P
\s+[^#]*),)' + RE_EOL) -RE_PROFILE_UNIX = re.compile(RE_AUDIT_DENY + r'(unix\s*,|unix(?P
\s+[^#]*)\s*,)' + RE_EOL) -RE_PROFILE_USERNS = re.compile(RE_AUDIT_DENY + r'(userns\s*,|userns(?P
\s+[^#]*)\s*,)' + RE_EOL) -RE_PROFILE_MQUEUE = re.compile(RE_AUDIT_DENY + r'(mqueue\s*,|mqueue(?P
\s+[^#]*)\s*,)' + RE_EOL) -RE_PROFILE_IO_URING = re.compile(RE_AUDIT_DENY + r'(io_uring\s*,|io_uring(?P
\s+[^#]*)\s*,)' + RE_EOL) +RE_PROFILE_DBUS = re.compile(RE_PRIORITY_AUDIT_DENY + r'(dbus\s*,|dbus(?P
\s+[^#]*)\s*,)' + RE_EOL) +RE_PROFILE_MOUNT = re.compile(RE_PRIORITY_AUDIT_DENY + r'((?Pmount|remount|umount|unmount)(?P
\s+[^#]*)?\s*,)' + RE_EOL) +RE_PROFILE_SIGNAL = re.compile(RE_PRIORITY_AUDIT_DENY + r'(signal\s*,|signal(?P
\s+[^#]*)\s*,)' + RE_EOL) +RE_PROFILE_PTRACE = re.compile(RE_PRIORITY_AUDIT_DENY + r'(ptrace\s*,|ptrace(?P
\s+[^#]*)\s*,)' + RE_EOL) +RE_PROFILE_PIVOT_ROOT = re.compile(RE_PRIORITY_AUDIT_DENY + r'(pivot_root\s*,|pivot_root(?P
\s+[^#]*),)' + RE_EOL) +RE_PROFILE_UNIX = re.compile(RE_PRIORITY_AUDIT_DENY + r'(unix\s*,|unix(?P
\s+[^#]*)\s*,)' + RE_EOL) +RE_PROFILE_USERNS = re.compile(RE_PRIORITY_AUDIT_DENY + r'(userns\s*,|userns(?P
\s+[^#]*)\s*,)' + RE_EOL) +RE_PROFILE_MQUEUE = re.compile(RE_PRIORITY_AUDIT_DENY + r'(mqueue\s*,|mqueue(?P
\s+[^#]*)\s*,)' + RE_EOL) +RE_PROFILE_IO_URING = re.compile(RE_PRIORITY_AUDIT_DENY + r'(io_uring\s*,|io_uring(?P
\s+[^#]*)\s*,)' + RE_EOL) # match anything that's not " or #, or matching quotes with anything except quotes inside __re_no_or_quoted_hash = '([^#"]|"[^"]*")*' @@ -81,7 +81,7 @@ RE_PROFILE_START = re.compile( RE_PROFILE_CHANGE_PROFILE = re.compile( - RE_AUDIT_DENY + RE_PRIORITY_AUDIT_DENY + 'change_profile' + r'(\s+' + RE_SAFE_OR_UNSAFE + ')?' # optionally exec mode + r'(\s+' + RE_PROFILE_PATH_OR_VAR % 'execcond' + ')?' # optionally exec condition @@ -94,7 +94,7 @@ RE_PROFILE_CHANGE_PROFILE = re.compile( RE_PATH_PERMS = '(?P<%s>[mrwalkPUCpucix]+)' RE_PROFILE_FILE_ENTRY = re.compile( - RE_AUDIT_DENY + RE_PRIORITY_AUDIT_DENY + r'(?Powner\s+)?' # optionally: + '(' + '(?Pfile)' # bare 'file,' # noqa: E131 diff --git a/utils/apparmor/rule/__init__.py b/utils/apparmor/rule/__init__.py index d0fdf80bc..8484efecd 100644 --- a/utils/apparmor/rule/__init__.py +++ b/utils/apparmor/rule/__init__.py @@ -41,8 +41,10 @@ class BaseRule(metaclass=ABCMeta): _match_re = None def __init__(self, audit=False, deny=False, allow_keyword=False, - comment='', log_event=None): + comment='', log_event=None, priority=None): """initialize variables needed by all rule types""" + + self._store_priority(priority) self.audit = audit self.deny = deny self.allow_keyword = allow_keyword @@ -52,6 +54,21 @@ class BaseRule(metaclass=ABCMeta): # Set only in the parse() class method self.raw_rule = None + def _store_priority(self, priority): + if priority is None: # default priority + self.priority = None + return + + try: + ipriority = int(priority) + except ValueError: + raise AppArmorException("Invalid value for priority '%s'" % priority) + + if ipriority < -1000 or ipriority > 1000: + raise AppArmorException('priority %d out of range' % (ipriority)) + + self.priority = ipriority + def _aare_or_all(self, rulepart, partname, is_path, log_event, empty_ok=False): """checks rulepart and returns - (AARE, False) if rulepart is a (non-empty) string @@ -233,7 +250,9 @@ class BaseRule(metaclass=ABCMeta): """compare if rule_obj == self Calls _is_equal_localvars() to compare rule-specific variables""" - if self.audit != rule_obj.audit or self.deny != rule_obj.deny: + if (self.priority != rule_obj.priority + or self.audit != rule_obj.audit + or self.deny != rule_obj.deny): return False if strict and ( @@ -282,6 +301,9 @@ class BaseRule(metaclass=ABCMeta): headers = [] qualifier = [] + if self.priority: + qualifier.append('priority=%s' % self.priority) + if self.audit: qualifier.append('audit') @@ -318,7 +340,12 @@ class BaseRule(metaclass=ABCMeta): raise NotImplementedError("'%s' needs to implement store_edit(), but didn't" % (str(self))) def modifiers_str(self): - """return the allow/deny and audit keyword as string, including whitespace""" + """return priority, allow/deny, and audit keyword as string, including whitespace""" + + if self.priority is not None: + prioritystr = 'priority=%s ' % self.priority + else: + prioritystr = '' if self.audit: auditstr = 'audit ' @@ -332,7 +359,17 @@ class BaseRule(metaclass=ABCMeta): else: allowstr = '' - return '%s%s' % (auditstr, allowstr) + return '%s%s%s' % (prioritystr, auditstr, allowstr) + + def ensure_modifiers_not_supported(self): + if self.audit: + raise AppArmorBug('Attempt to initialize %s with audit flag' % self.__class__.__name__) + if self.deny: + raise AppArmorBug('Attempt to initialize %s with deny flag' % self.__class__.__name__) + if self.allow_keyword: + raise AppArmorBug('Attempt to initialize %s with allow keyword' % self.__class__.__name__) + if self.priority is not None: + raise AppArmorBug('Attempt to initialize %s with priority' % self.__class__.__name__) class BaseRuleset: @@ -565,9 +602,16 @@ def parse_comment(matches): def parse_modifiers(matches): - """returns audit, deny, allow_keyword and comment from the matches object + """returns priority, audit, deny, allow_keyword and comment from the + matches object + - priority is a number or None - audit, deny and allow_keyword are True/False - comment is the comment with a leading space""" + + priority = None + if matches.group('priority'): + priority = int(matches.group('priority')) + audit = False if matches.group('audit'): audit = True @@ -586,7 +630,7 @@ def parse_modifiers(matches): comment = parse_comment(matches) - return (audit, deny, allow_keyword, comment) + return (priority, audit, deny, allow_keyword, comment) def quote_if_needed(data): diff --git a/utils/apparmor/rule/abi.py b/utils/apparmor/rule/abi.py index 586db8428..d7bd974a5 100644 --- a/utils/apparmor/rule/abi.py +++ b/utils/apparmor/rule/abi.py @@ -29,11 +29,11 @@ class AbiRule(IncludeRule): _match_re = RE_ABI def __init__(self, path, ifexists, ismagic, audit=False, deny=False, allow_keyword=False, - comment='', log_event=None): + comment='', log_event=None, priority=None): super().__init__(path, ifexists, ismagic, audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) # abi doesn't support 'if exists' if ifexists: diff --git a/utils/apparmor/rule/alias.py b/utils/apparmor/rule/alias.py index aca4c530a..d0fd440d6 100644 --- a/utils/apparmor/rule/alias.py +++ b/utils/apparmor/rule/alias.py @@ -27,16 +27,13 @@ class AliasRule(BaseRule): _match_re = RE_PROFILE_ALIAS def __init__(self, orig_path, target, audit=False, deny=False, allow_keyword=False, - comment='', log_event=None): + comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) - # aliases don't support audit or deny - if audit: - raise AppArmorBug('Attempt to initialize %s with audit flag' % self.__class__.__name__) - if deny: - raise AppArmorBug('Attempt to initialize %s with deny flag' % self.__class__.__name__) + # aliases don't support priority, allow keyword, audit or deny + self.ensure_modifiers_not_supported() if not isinstance(orig_path, str): raise AppArmorBug('Passed unknown type for orig_path to %s: %s' % (self.__class__.__name__, orig_path)) @@ -65,7 +62,7 @@ class AliasRule(BaseRule): target = strip_quotes(matches.group('target').strip()) return cls(orig_path, target, - audit=False, deny=False, allow_keyword=False, comment=comment) + audit=False, deny=False, allow_keyword=False, comment=comment, priority=None) def get_clean(self, depth=0): """return rule (in clean/default formatting)""" diff --git a/utils/apparmor/rule/all.py b/utils/apparmor/rule/all.py index 4a859cfcc..b60781ed2 100644 --- a/utils/apparmor/rule/all.py +++ b/utils/apparmor/rule/all.py @@ -29,10 +29,10 @@ class AllRule(BaseRule): _match_re = RE_PROFILE_ALL def __init__(self, audit=False, deny=False, allow_keyword=False, - comment='', log_event=None): + comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) # no localvars -> nothing more to do @@ -40,11 +40,11 @@ class AllRule(BaseRule): def _create_instance(cls, raw_rule, matches): """parse raw_rule and return instance of this class""" - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) return cls(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment) + comment=comment, priority=priority) def get_clean(self, depth=0): """return rule (in clean/default formatting)""" diff --git a/utils/apparmor/rule/boolean.py b/utils/apparmor/rule/boolean.py index 7d24ddda7..ec1b901e8 100644 --- a/utils/apparmor/rule/boolean.py +++ b/utils/apparmor/rule/boolean.py @@ -28,16 +28,13 @@ class BooleanRule(BaseRule): _match_re = RE_PROFILE_BOOLEAN def __init__(self, varname, value, audit=False, deny=False, allow_keyword=False, - comment='', log_event=None): + comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) - # boolean variables don't support audit or deny - if audit: - raise AppArmorBug('Attempt to initialize %s with audit flag' % self.__class__.__name__) - if deny: - raise AppArmorBug('Attempt to initialize %s with deny flag' % self.__class__.__name__) + # boolean variables don't support priority, allow keyword, audit or deny + self.ensure_modifiers_not_supported() if not isinstance(varname, str): raise AppArmorBug('Passed unknown type for boolean variable to %s: %s' % (self.__class__.__name__, varname)) @@ -66,7 +63,7 @@ class BooleanRule(BaseRule): value = matches.group('value') return cls(varname, value, - audit=False, deny=False, allow_keyword=False, comment=comment) + audit=False, deny=False, allow_keyword=False, comment=comment, priority=None) def get_clean(self, depth=0): """return rule (in clean/default formatting)""" diff --git a/utils/apparmor/rule/capability.py b/utils/apparmor/rule/capability.py index ce00eb839..0a21c6caf 100644 --- a/utils/apparmor/rule/capability.py +++ b/utils/apparmor/rule/capability.py @@ -46,10 +46,10 @@ class CapabilityRule(BaseRule): _match_re = RE_PROFILE_CAP def __init__(self, cap_list, audit=False, deny=False, allow_keyword=False, - comment='', log_event=None): + comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) # Because we support having multiple caps in one rule, # initializer needs to accept a list of caps. self.all_caps = False @@ -78,7 +78,7 @@ class CapabilityRule(BaseRule): def _create_instance(cls, raw_rule, matches): """parse raw_rule and return instance of this class""" - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) if matches.group('capability'): capability = matches.group('capability').strip() @@ -88,7 +88,7 @@ class CapabilityRule(BaseRule): return cls(capability, audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment) + comment=comment, priority=priority) def get_clean(self, depth=0): """return rule (in clean/default formatting)""" diff --git a/utils/apparmor/rule/change_profile.py b/utils/apparmor/rule/change_profile.py index 70858891b..3f3722009 100644 --- a/utils/apparmor/rule/change_profile.py +++ b/utils/apparmor/rule/change_profile.py @@ -37,11 +37,11 @@ class ChangeProfileRule(BaseRule): _match_re = RE_PROFILE_CHANGE_PROFILE def __init__(self, execmode, execcond, targetprofile, audit=False, deny=False, allow_keyword=False, - comment='', log_event=None): + comment='', log_event=None, priority=None): """CHANGE_PROFILE RULE = 'change_profile' [ [ EXEC MODE ] EXEC COND ] [ -> PROGRAMCHILD ]""" super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) if execmode: if execmode != 'safe' and execmode != 'unsafe': @@ -80,7 +80,7 @@ class ChangeProfileRule(BaseRule): def _create_instance(cls, raw_rule, matches): """parse raw_rule and return instance of this class""" - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) execmode = matches.group('execmode') @@ -95,7 +95,7 @@ class ChangeProfileRule(BaseRule): targetprofile = cls.ALL return cls(execmode, execcond, targetprofile, - audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment) + audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, priority=priority) def get_clean(self, depth=0): """return rule (in clean/default formatting)""" diff --git a/utils/apparmor/rule/dbus.py b/utils/apparmor/rule/dbus.py index 4a6fd5293..e493601c6 100644 --- a/utils/apparmor/rule/dbus.py +++ b/utils/apparmor/rule/dbus.py @@ -80,10 +80,10 @@ class DbusRule(BaseRule): _match_re = RE_PROFILE_DBUS def __init__(self, access, bus, path, name, interface, member, peername, peerlabel, - audit=False, deny=False, allow_keyword=False, comment='', log_event=None): + audit=False, deny=False, allow_keyword=False, comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) self.access, self.all_access, unknown_items = check_and_split_list(access, access_keywords, self.ALL, type(self).__name__, 'access') if unknown_items: @@ -112,7 +112,7 @@ class DbusRule(BaseRule): def _create_instance(cls, raw_rule, matches): """parse raw_rule and return instance of this class""" - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) rule_details = '' if matches.group('details'): @@ -186,7 +186,8 @@ class DbusRule(BaseRule): peerlabel = cls.ALL return cls(access, bus, path, name, interface, member, peername, peerlabel, - audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment) + audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, + priority=priority) def get_clean(self, depth=0): """return rule (in clean/default formatting)""" diff --git a/utils/apparmor/rule/file.py b/utils/apparmor/rule/file.py index 6a92a82da..17537e6d2 100644 --- a/utils/apparmor/rule/file.py +++ b/utils/apparmor/rule/file.py @@ -47,7 +47,7 @@ class FileRule(BaseRule): _match_re = RE_PROFILE_FILE_ENTRY def __init__(self, path, perms, exec_perms, target, owner, file_keyword=False, leading_perms=False, - audit=False, deny=False, allow_keyword=False, comment='', log_event=None): + audit=False, deny=False, allow_keyword=False, comment='', log_event=None, priority=None): """Initialize object Parameters: @@ -61,7 +61,7 @@ class FileRule(BaseRule): """ super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) # rulepart partperms is_path log_event self.path, self.all_paths = self._aare_or_all(path, 'path', True, log_event) # noqa: E221 @@ -138,7 +138,7 @@ class FileRule(BaseRule): def _create_instance(cls, raw_rule, matches): """parse raw_rule and return instance of this class""" - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) owner = bool(matches.group('owner')) @@ -183,7 +183,7 @@ class FileRule(BaseRule): file_keyword = bool(matches.group('file_keyword')) return cls(path, perms, exec_perms, target, owner, file_keyword, leading_perms, - audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment) + audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, priority=priority) def get_clean(self, depth=0): """return rule (in clean/default formatting)""" diff --git a/utils/apparmor/rule/include.py b/utils/apparmor/rule/include.py index 6ade58874..f786b13fd 100644 --- a/utils/apparmor/rule/include.py +++ b/utils/apparmor/rule/include.py @@ -28,16 +28,13 @@ class IncludeRule(BaseRule): _match_re = RE_INCLUDE def __init__(self, path, ifexists, ismagic, audit=False, deny=False, allow_keyword=False, - comment='', log_event=None): + comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) - # include doesn't support audit or deny - if audit: - raise AppArmorBug('Attempt to initialize %s with audit flag' % self.__class__.__name__) - if deny: - raise AppArmorBug('Attempt to initialize %s with deny flag' % self.__class__.__name__) + # include doesn't support priority, allow keyword, audit or deny + self.ensure_modifiers_not_supported() if not isinstance(ifexists, bool): raise AppArmorBug('Passed unknown type for ifexists to %s: %s' % (self.__class__.__name__, ifexists)) @@ -62,7 +59,7 @@ class IncludeRule(BaseRule): path, ifexists, ismagic = re_match_include_parse(raw_rule, cls.rule_name) return cls(path, ifexists, ismagic, - audit=False, deny=False, allow_keyword=False, comment=comment) + audit=False, deny=False, allow_keyword=False, comment=comment, priority=None) def get_clean(self, depth=0): """return rule (in clean/default formatting)""" diff --git a/utils/apparmor/rule/io_uring.py b/utils/apparmor/rule/io_uring.py index 599f99e86..da88078c7 100644 --- a/utils/apparmor/rule/io_uring.py +++ b/utils/apparmor/rule/io_uring.py @@ -51,12 +51,12 @@ class IOUringRule(BaseRule): _match_re = RE_PROFILE_IO_URING def __init__(self, access, label, audit=False, deny=False, - allow_keyword=False, comment='', log_event=None): + allow_keyword=False, comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, - log_event=log_event) + log_event=log_event, priority=priority) self.access, self.all_access, unknown_items = check_and_split_list(access, access_keywords, self.ALL, type(self).__name__, 'access') if unknown_items: @@ -68,7 +68,7 @@ class IOUringRule(BaseRule): def _create_instance(cls, raw_rule, matches): '''parse raw_rule and return instance of this class''' - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) rule_details = '' if matches.group('details'): @@ -96,7 +96,7 @@ class IOUringRule(BaseRule): label = cls.ALL return cls(access, label, audit=audit, deny=deny, - allow_keyword=allow_keyword, comment=comment) + allow_keyword=allow_keyword, comment=comment, priority=priority) def get_clean(self, depth=0): '''return rule (in clean/default formatting)''' diff --git a/utils/apparmor/rule/mount.py b/utils/apparmor/rule/mount.py index 479f9ce3c..7bb3c8e01 100644 --- a/utils/apparmor/rule/mount.py +++ b/utils/apparmor/rule/mount.py @@ -112,12 +112,15 @@ class MountRule(BaseRule): rule_name = 'mount' _match_re = RE_PROFILE_MOUNT - def __init__(self, operation, fstype, options, source, dest, audit=False, deny=False, allow_keyword=False, comment='', log_event=None): + def __init__(self, operation, fstype, options, source, dest, + audit=False, deny=False, allow_keyword=False, + comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, - log_event=log_event) + log_event=log_event, + priority=priority) self.operation = operation @@ -164,7 +167,7 @@ class MountRule(BaseRule): def _create_instance(cls, raw_rule, matches): '''parse raw_rule and return instance of this class''' - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) operation = matches.group('operation') @@ -223,7 +226,9 @@ class MountRule(BaseRule): source = cls.ALL dest = cls.ALL - return cls(operation=operation, fstype=(is_fstype_equal, fstype), options=(is_options_equal, options), source=source, dest=dest, audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment) + return cls(operation=operation, fstype=(is_fstype_equal, fstype), options=(is_options_equal, options), + source=source, dest=dest, audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, + priority=priority) def get_clean(self, depth=0): space = ' ' * depth diff --git a/utils/apparmor/rule/mqueue.py b/utils/apparmor/rule/mqueue.py index eca5fa36e..10c397dc3 100644 --- a/utils/apparmor/rule/mqueue.py +++ b/utils/apparmor/rule/mqueue.py @@ -62,12 +62,13 @@ class MessageQueueRule(BaseRule): def __init__(self, access, mqueue_type, label, mqueue_name, audit=False, deny=False, allow_keyword=False, - comment='', log_event=None): + comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, - log_event=log_event) + log_event=log_event, + priority=priority) self.access, self.all_access, unknown_items = check_and_split_list(access, access_keywords, self.ALL, type(self).__name__, 'access') if unknown_items: @@ -92,7 +93,7 @@ class MessageQueueRule(BaseRule): def _create_instance(cls, raw_rule, matches): '''parse raw_rule and return instance of this class''' - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) rule_details = '' if matches.group('details'): @@ -132,7 +133,7 @@ class MessageQueueRule(BaseRule): mqueue_name = cls.ALL return cls(access, mqueue_type, label, mqueue_name, - audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment) + audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, priority=priority) def get_clean(self, depth=0): '''return rule (in clean/default formatting)''' diff --git a/utils/apparmor/rule/network.py b/utils/apparmor/rule/network.py index f788e1b9c..9239b6836 100644 --- a/utils/apparmor/rule/network.py +++ b/utils/apparmor/rule/network.py @@ -92,10 +92,10 @@ class NetworkRule(BaseRule): _match_re = RE_PROFILE_NETWORK def __init__(self, accesses, domain, type_or_protocol, local_expr, peer_expr, audit=False, deny=False, - allow_keyword=False, comment='', log_event=None): + allow_keyword=False, comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) if type(local_expr) is tuple: if accesses is None: @@ -159,7 +159,7 @@ class NetworkRule(BaseRule): def _create_instance(cls, raw_rule, matches): """parse raw_rule and return instance of this class""" - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) rule_details = '' if matches.group('details'): @@ -191,7 +191,7 @@ class NetworkRule(BaseRule): peer_expr = cls.ALL return cls(accesses, domain, type_or_protocol, local_expr, peer_expr, - audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment) + audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, priority=priority) def get_clean(self, depth=0): """return rule (in clean/default formatting)""" diff --git a/utils/apparmor/rule/pivot_root.py b/utils/apparmor/rule/pivot_root.py index 06f951d0a..d270c1d49 100644 --- a/utils/apparmor/rule/pivot_root.py +++ b/utils/apparmor/rule/pivot_root.py @@ -47,12 +47,13 @@ class PivotRootRule(BaseRule): _match_re = RE_PROFILE_PIVOT_ROOT # PIVOT ROOT RULE = [ QUALIFIERS ] pivot_root [ oldroot=OLD PUT FILEGLOB ] [ NEW ROOT FILEGLOB ] [ ’->’ PROFILE NAME ] - def __init__(self, oldroot, newroot, profile_name, audit=False, deny=False, allow_keyword=False, comment='', log_event=None): + def __init__(self, oldroot, newroot, profile_name, audit=False, deny=False, allow_keyword=False, + comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, - log_event=log_event) + log_event=log_event, priority=priority) self.oldroot, self.all_oldroots = self._aare_or_all(oldroot, 'oldroot', True, log_event) # noqa: E221 self.newroot, self.all_newroots = self._aare_or_all(newroot, 'newroot', True, log_event) # noqa: E221 @@ -66,7 +67,7 @@ class PivotRootRule(BaseRule): def _create_instance(cls, raw_rule, matches): '''parse raw_rule and return instance of this class''' - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) rule_details = '' if matches.group('details'): @@ -100,7 +101,7 @@ class PivotRootRule(BaseRule): profile_name = cls.ALL return cls(oldroot=oldroot, newroot=newroot, profile_name=profile_name, - audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment) + audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, priority=priority) def get_clean(self, depth=0): space = ' ' * depth diff --git a/utils/apparmor/rule/ptrace.py b/utils/apparmor/rule/ptrace.py index 8ec41f1a0..4b0584023 100644 --- a/utils/apparmor/rule/ptrace.py +++ b/utils/apparmor/rule/ptrace.py @@ -53,10 +53,10 @@ class PtraceRule(BaseRule): _match_re = RE_PROFILE_PTRACE def __init__(self, access, peer, audit=False, deny=False, allow_keyword=False, - comment='', log_event=None): + comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) self.access, self.all_access, unknown_items = check_and_split_list( access, access_keywords, self.ALL, type(self).__name__, 'access') @@ -69,7 +69,7 @@ class PtraceRule(BaseRule): def _create_instance(cls, raw_rule, matches): """parse raw_rule and return instance of this class""" - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) rule_details = '' if matches.group('details'): @@ -98,7 +98,7 @@ class PtraceRule(BaseRule): peer = cls.ALL return cls(access, peer, - audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment) + audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, priority=priority) def get_clean(self, depth=0): """return rule (in clean/default formatting)""" diff --git a/utils/apparmor/rule/rlimit.py b/utils/apparmor/rule/rlimit.py index 4bc810563..a4d8c8386 100644 --- a/utils/apparmor/rule/rlimit.py +++ b/utils/apparmor/rule/rlimit.py @@ -49,13 +49,13 @@ class RlimitRule(BaseRule): _match_re = RE_PROFILE_RLIMIT def __init__(self, rlimit, value, audit=False, deny=False, allow_keyword=False, - comment='', log_event=None): + comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) - if audit or deny or allow_keyword: - raise AppArmorBug('The audit, allow or deny keywords are not allowed in rlimit rules.') + # rlimit rules don't support priority, allow keyword, audit or deny + self.ensure_modifiers_not_supported() if isinstance(rlimit, str): if rlimit in rlimit_all: diff --git a/utils/apparmor/rule/signal.py b/utils/apparmor/rule/signal.py index e803ec223..4cf159f8d 100644 --- a/utils/apparmor/rule/signal.py +++ b/utils/apparmor/rule/signal.py @@ -78,10 +78,10 @@ class SignalRule(BaseRule): _match_re = RE_PROFILE_SIGNAL def __init__(self, access, signal, peer, audit=False, deny=False, allow_keyword=False, - comment='', log_event=None): + comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) self.access, self.all_access, unknown_items = check_and_split_list( access, access_keywords, self.ALL, type(self).__name__, 'access') @@ -103,7 +103,7 @@ class SignalRule(BaseRule): def _create_instance(cls, raw_rule, matches): """parse raw_rule and return instance of this class""" - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) rule_details = '' if matches.group('details'): @@ -141,7 +141,7 @@ class SignalRule(BaseRule): peer = cls.ALL return cls(access, signal, peer, - audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment) + audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, priority=priority) def get_clean(self, depth=0): """return rule (in clean/default formatting)""" diff --git a/utils/apparmor/rule/unix.py b/utils/apparmor/rule/unix.py index 8be505995..e7675070b 100644 --- a/utils/apparmor/rule/unix.py +++ b/utils/apparmor/rule/unix.py @@ -65,12 +65,14 @@ class UnixRule(BaseRule): rule_name = 'unix' _match_re = RE_PROFILE_UNIX - def __init__(self, accesses, rule_conds, local_expr, peer_expr, audit=False, deny=False, allow_keyword=False, comment='', log_event=None): + def __init__(self, accesses, rule_conds, local_expr, peer_expr, audit=False, deny=False, allow_keyword=False, + comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, - log_event=log_event) + log_event=log_event, + priority=priority) if type(rule_conds) is tuple: # This comes from the logparser, we convert it to dicts accesses = strip_parenthesis(accesses).replace(',', ' ').split() @@ -96,7 +98,7 @@ class UnixRule(BaseRule): def _create_instance(cls, raw_rule, matches): '''parse raw_rule and return instance of this class''' - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) rule_details = '' if matches.group('details'): @@ -124,7 +126,8 @@ class UnixRule(BaseRule): local_expr = cls.ALL peer_expr = cls.ALL - return cls(accesses=accesses, rule_conds=rule_conds, local_expr=local_expr, peer_expr=peer_expr, audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment) + return cls(accesses=accesses, rule_conds=rule_conds, local_expr=local_expr, peer_expr=peer_expr, + audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, priority=priority) def get_clean(self, depth=0): space = ' ' * depth diff --git a/utils/apparmor/rule/userns.py b/utils/apparmor/rule/userns.py index 2fc1df89b..5e3623463 100644 --- a/utils/apparmor/rule/userns.py +++ b/utils/apparmor/rule/userns.py @@ -44,12 +44,13 @@ class UserNamespaceRule(BaseRule): _match_re = RE_PROFILE_USERNS def __init__(self, access, audit=False, deny=False, - allow_keyword=False, comment='', log_event=None): + allow_keyword=False, comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment, - log_event=log_event) + log_event=log_event, + priority=priority) self.access, self.all_access, unknown_items = check_and_split_list(access, access_keyword, self.ALL, type(self).__name__, 'access') if unknown_items: @@ -59,7 +60,7 @@ class UserNamespaceRule(BaseRule): def _create_instance(cls, raw_rule, matches): '''parse raw_rule and return instance of this class''' - audit, deny, allow_keyword, comment = parse_modifiers(matches) + priority, audit, deny, allow_keyword, comment = parse_modifiers(matches) rule_details = '' if matches.group('details'): @@ -75,7 +76,7 @@ class UserNamespaceRule(BaseRule): access = cls.ALL return cls(access, audit=audit, deny=deny, - allow_keyword=allow_keyword, comment=comment) + allow_keyword=allow_keyword, comment=comment, priority=priority) @staticmethod def hashlog_from_event(hl, e): diff --git a/utils/apparmor/rule/variable.py b/utils/apparmor/rule/variable.py index 52d63dd95..a88fc42de 100644 --- a/utils/apparmor/rule/variable.py +++ b/utils/apparmor/rule/variable.py @@ -30,16 +30,13 @@ class VariableRule(BaseRule): _match_re = RE_PROFILE_VARIABLE def __init__(self, varname, mode, values, audit=False, deny=False, allow_keyword=False, - comment='', log_event=None): + comment='', log_event=None, priority=None): super().__init__(audit=audit, deny=deny, allow_keyword=allow_keyword, - comment=comment, log_event=log_event) + comment=comment, log_event=log_event, priority=priority) - # variables don't support audit or deny - if audit: - raise AppArmorBug('Attempt to initialize %s with audit flag' % self.__class__.__name__) - if deny: - raise AppArmorBug('Attempt to initialize %s with deny flag' % self.__class__.__name__) + # variables don't support priority, allow keyword, audit or deny + self.ensure_modifiers_not_supported() if not isinstance(varname, str): raise AppArmorBug('Passed unknown type for varname to %s: %s' % (self.__class__.__name__, varname)) @@ -73,7 +70,7 @@ class VariableRule(BaseRule): values = separate_vars(matches.group('values')) return cls(varname, mode, values, - audit=False, deny=False, allow_keyword=False, comment=comment) + audit=False, deny=False, allow_keyword=False, comment=comment, priority=None) def get_clean(self, depth=0): """return rule (in clean/default formatting)""" diff --git a/utils/test/test-alias.py b/utils/test/test-alias.py index 74f72bcc7..ea9ed47cb 100644 --- a/utils/test/test-alias.py +++ b/utils/test/test-alias.py @@ -30,10 +30,11 @@ exp = namedtuple('exp', ('comment', 'orig_path', 'target')) class AliasTest(AATest): def _compare_obj(self, obj, expected): - # aliases don't support the allow, audit or deny keyword + # aliases don't support the allow, audit, deny, or priority keyword self.assertEqual(False, obj.allow_keyword) self.assertEqual(False, obj.audit) self.assertEqual(False, obj.deny) + self.assertEqual(None, obj.priority) self.assertEqual(expected.orig_path, obj.orig_path) self.assertEqual(expected.target, obj.target) @@ -114,6 +115,14 @@ class InvalidAliasInit(AATest): with self.assertRaises(AppArmorBug): AliasRule('/foo', '/bar', deny=True) + def test_invalid_priority_1(self): + with self.assertRaises(AppArmorBug): + AliasRule('/foo', '/bar', priority=1) + + def test_invalid_priority_2(self): + with self.assertRaises(AppArmorBug): + AliasRule('/foo', '/bar', priority=0) + class InvalidAliasTest(AATest): def _check_invalid_rawrule(self, rawrule, matches_regex=False): diff --git a/utils/test/test-all.py b/utils/test/test-all.py index 476291df1..71eeb3267 100644 --- a/utils/test/test-all.py +++ b/utils/test/test-all.py @@ -116,6 +116,7 @@ class WriteAllTestAATest(AATest): (' deny all ,# foo bar', 'deny all, # foo bar'), (' allow all ,# foo bar', 'allow all, # foo bar'), (' allow all ,', 'allow all,'), + (' priority = -2 allow all ,', 'priority=-2 allow all,'), ) def _run_test(self, rawrule, expected): diff --git a/utils/test/test-baserule.py b/utils/test/test-baserule.py index 83ef17321..b3477dd21 100644 --- a/utils/test/test-baserule.py +++ b/utils/test/test-baserule.py @@ -71,7 +71,7 @@ class TestBaserule(AATest): self.ValidSubclass.match('foo') def test_parse_modifiers_invalid(self): - regex = re.compile(r'^\s*(?Paudit\s+)?(?Pallow\s+|deny\s+|invalid\s+)?') + regex = re.compile(r'^\s*(priority\s*=\s*(?P[+-]?[0-9]*)\s+)?(?Paudit\s+)?(?Pallow\s+|deny\s+|invalid\s+)?') matches = regex.search('audit invalid ') with self.assertRaises(AppArmorBug): diff --git a/utils/test/test-boolean.py b/utils/test/test-boolean.py index fc746f1b4..d6bce0e47 100644 --- a/utils/test/test-boolean.py +++ b/utils/test/test-boolean.py @@ -30,10 +30,11 @@ exp = namedtuple('exp', ('comment', 'varname', 'value')) class BooleanTest(AATest): def _compare_obj(self, obj, expected): - # boolean variables don't support the allow, audit or deny keyword + # boolean variables don't support the allow, audit, deny, or priority keyword self.assertEqual(False, obj.allow_keyword) self.assertEqual(False, obj.audit) self.assertEqual(False, obj.deny) + self.assertEqual(None, obj.priority) self.assertEqual(expected.varname, obj.varname) self.assertEqual(expected.value, obj.value) @@ -122,6 +123,14 @@ class InvalidBooleanInit(AATest): with self.assertRaises(AppArmorBug): BooleanRule('$foo', 'true', deny=True) + def test_invalid_priority_1(self): + with self.assertRaises(AppArmorBug): + BooleanRule('$foo', 'true', priority=-100) + + def test_invalid_priority_2(self): + with self.assertRaises(AppArmorBug): + BooleanRule('$foo', 'true', priority=0) + class InvalidBooleanTest(AATest): def _check_invalid_rawrule(self, rawrule, matches_regex=False): diff --git a/utils/test/test-capability.py b/utils/test/test-capability.py index 1858df745..666f48cc8 100644 --- a/utils/test/test-capability.py +++ b/utils/test/test-capability.py @@ -314,6 +314,18 @@ class WriteCapabilityTest(AATest): self.assertEqual(expected, obj.get_clean(2), 'unexpected clean rule') self.assertEqual(expected, obj.get_raw(2), 'unexpected raw rule') + def test_write_priority_1(self): + self._check_write_rule(' priority = 923 audit capability sys_admin,', 'priority=923 audit capability sys_admin,') + + def test_write_priority_2(self): + self._check_write_rule(' priority = 0 audit capability sys_admin,', 'priority=0 audit capability sys_admin,') + + def test_write_priority_3(self): + self._check_write_rule(' priority=-12 audit capability sys_admin,', 'priority=-12 audit capability sys_admin,') + + def test_write_priority_4(self): + self._check_write_rule(' priority=+99 audit capability sys_admin,', 'priority=99 audit capability sys_admin,') + class CapabilityCoveredTest(AATest): def _is_covered(self, obj, rule_to_test): diff --git a/utils/test/test-change_profile.py b/utils/test/test-change_profile.py index 272894838..0263a6c00 100644 --- a/utils/test/test-change_profile.py +++ b/utils/test/test-change_profile.py @@ -225,6 +225,10 @@ class WriteChangeProfileTestAATest(AATest): (' allow change_profile -> /bar ,# foo bar', 'allow change_profile -> /bar, # foo bar'), (' allow change_profile unsafe /** -> /bar ,# foo bar', 'allow change_profile unsafe /** -> /bar, # foo bar'), (' allow change_profile "/fo o" -> "/b ar",', 'allow change_profile "/fo o" -> "/b ar",'), + (' priority=9 audit deny change_profile /foo -> baz,', 'priority=9 audit deny change_profile /foo -> baz,'), + (' priority = 0 audit deny change_profile /foo -> baz,', 'priority=0 audit deny change_profile /foo -> baz,'), + (' priority=-54 audit deny change_profile /foo -> baz,', 'priority=-54 audit deny change_profile /foo -> baz,'), + (' priority=+42 audit deny change_profile /foo -> baz,', 'priority=42 audit deny change_profile /foo -> baz,'), ) def _run_test(self, rawrule, expected): diff --git a/utils/test/test-dbus.py b/utils/test/test-dbus.py index 9273024a8..e7c8f1468 100644 --- a/utils/test/test-dbus.py +++ b/utils/test/test-dbus.py @@ -419,6 +419,10 @@ class WriteDbusTest(AATest): ('dbus receive peer=(label=foo),', 'dbus receive peer=(label=foo),'), ('dbus (send receive) peer=(name=/usr/bin/bar),', 'dbus (receive send) peer=(name=/usr/bin/bar),'), ('dbus (, receive ,,, send ,) interface=/sbin/baz,', 'dbus (receive send) interface=/sbin/baz,'), # XXX leading and trailing ',' inside (...) causes error + (' priority=123 deny dbus send interface = ( foo ),', 'priority=123 deny dbus send interface=foo,'), + (' priority=0 deny dbus send interface = ( foo ),', 'priority=0 deny dbus send interface=foo,'), + (' priority=-72 deny dbus send interface = ( foo ),', 'priority=-72 deny dbus send interface=foo,'), + (' priority=+834 deny dbus send interface = ( foo ),', 'priority=834 deny dbus send interface=foo,'), # XXX add more complex rules ) diff --git a/utils/test/test-file.py b/utils/test/test-file.py index 20b585c7b..b73990434 100644 --- a/utils/test/test-file.py +++ b/utils/test/test-file.py @@ -415,6 +415,10 @@ class WriteFileTest(AATest): (' /foo r,', '/foo r,'), (' /foo lwr,', '/foo rwl,'), (' /foo Pxrm -> bar,', '/foo mrPx -> bar,'), + (' priority=-1 /foo Pxrm -> bar,', 'priority=-1 /foo mrPx -> bar,'), + (' priority=0 /foo Pxrm -> bar,', 'priority=0 /foo mrPx -> bar,'), + (' priority=343 /foo Pxrm -> bar,', 'priority=343 /foo mrPx -> bar,'), + (' priority=+65 /foo Pxrm -> bar,', 'priority=65 /foo mrPx -> bar,'), # with leading permissions (' audit file r /foo,', 'audit file r /foo,'), @@ -432,11 +436,19 @@ class WriteFileTest(AATest): (' r /foo ,', 'r /foo,'), (' klwr /foo ,', 'rwlk /foo,'), (' Pxrm /foo -> bar,', 'mrPx /foo -> bar,'), + (' priority=1 Pxrm /foo -> bar,', 'priority=1 mrPx /foo -> bar,'), + (' priority=0 Pxrm /foo -> bar,', 'priority=0 mrPx /foo -> bar,'), + (' priority=-22 Pxrm /foo -> bar,', 'priority=-22 mrPx /foo -> bar,'), + (' priority=+78 Pxrm /foo -> bar,', 'priority=78 mrPx /foo -> bar,'), # link rules (' link /foo -> /bar,', 'link /foo -> /bar,'), (' audit deny owner link subset /foo -> /bar,', 'audit deny owner link subset /foo -> /bar,'), - (' link subset /foo -> /bar,', 'link subset /foo -> /bar,') + (' link subset /foo -> /bar,', 'link subset /foo -> /bar,'), + (' priority=0 link /foo -> /bar,', 'priority=0 link /foo -> /bar,'), + (' priority=12 link /foo -> /bar,', 'priority=12 link /foo -> /bar,'), + (' priority=-1 link /foo -> /bar,', 'priority=-1 link /foo -> /bar,'), + (' priority=+4 link /foo -> /bar,', 'priority=4 link /foo -> /bar,'), ) def test_write_manually_1(self): @@ -844,21 +856,23 @@ class FileSeverityTest(AATest): class FileLogprofHeaderTest(AATest): tests = ( # log event old perms ALL / owner - (('file,', set(), set()), [ _('Path'), _('ALL'), _('New Mode'), _('ALL')]), # noqa: E201 - (('/foo r,', set(), set()), [ _('Path'), '/foo', _('New Mode'), 'r']), # noqa: E201 - (('file /bar Px -> foo,', set(), set()), [ _('Path'), '/bar', _('New Mode'), 'Px -> foo']), # noqa: E201 - (('deny file,', set(), set()), [_('Qualifier'), 'deny', _('Path'), _('ALL'), _('New Mode'), _('ALL')]), - (('allow file /baz rwk,', set(), set()), [_('Qualifier'), 'allow', _('Path'), '/baz', _('New Mode'), 'rwk']), - (('audit file /foo mr,', set(), set()), [_('Qualifier'), 'audit', _('Path'), '/foo', _('New Mode'), 'mr']), - (('audit deny /foo wk,', set(), set()), [_('Qualifier'), 'audit deny', _('Path'), '/foo', _('New Mode'), 'wk']), - (('owner file /foo ix,', set(), set()), [ _('Path'), '/foo', _('New Mode'), 'owner ix']), # noqa: E201 - (('audit deny file /foo rlx -> /baz,', set(), set()), [_('Qualifier'), 'audit deny', _('Path'), '/foo', _('New Mode'), 'rlx -> /baz']), - (('/foo rw,', set('r'), set()), [ _('Path'), '/foo', _('Old Mode'), _('r'), _('New Mode'), 'rw']), # noqa: E201 - (('/foo rw,', set(), set('rw')), [ _('Path'), '/foo', _('Old Mode'), _('owner rw'), _('New Mode'), 'rw']), # noqa: E201 - (('/foo mrw,', set('r'), set('k')), [ _('Path'), '/foo', _('Old Mode'), _('r + owner k'), _('New Mode'), 'mrw']), # noqa: E201 - (('/foo mrw,', set('r'), set('rk')), [ _('Path'), '/foo', _('Old Mode'), _('r + owner k'), _('New Mode'), 'mrw']), # noqa: E201 - (('link /foo -> /bar,', set(), set()), [ _('Path'), '/foo', _('New Mode'), 'link -> /bar']), # noqa: E201 - (('link subset /foo -> /bar,', set(), set()), [ _('Path'), '/foo', _('New Mode'), 'link subset -> /bar']), # noqa: E201 + (('file,', set(), set()), [ _('Path'), _('ALL'), _('New Mode'), _('ALL')]), # noqa: E201 + (('/foo r,', set(), set()), [ _('Path'), '/foo', _('New Mode'), 'r']), # noqa: E201 + (('file /bar Px -> foo,', set(), set()), [ _('Path'), '/bar', _('New Mode'), 'Px -> foo']), # noqa: E201 + (('deny file,', set(), set()), [_('Qualifier'), 'deny', _('Path'), _('ALL'), _('New Mode'), _('ALL')]), + (('allow file /baz rwk,', set(), set()), [_('Qualifier'), 'allow', _('Path'), '/baz', _('New Mode'), 'rwk']), + (('audit file /foo mr,', set(), set()), [_('Qualifier'), 'audit', _('Path'), '/foo', _('New Mode'), 'mr']), + (('audit deny /foo wk,', set(), set()), [_('Qualifier'), 'audit deny', _('Path'), '/foo', _('New Mode'), 'wk']), + (('priority=1 file,', set(), set()), [_('Qualifier'), 'priority=1', _('Path'), _('ALL'), _('New Mode'), _('ALL')]), + (('priority=-1 audit file /foo mr,', set(), set()), [_('Qualifier'), 'priority=-1 audit', _('Path'), '/foo', _('New Mode'), 'mr']), + (('owner file /foo ix,', set(), set()), [ _('Path'), '/foo', _('New Mode'), 'owner ix']), # noqa: E201 + (('audit deny file /foo rlx -> /baz,', set(), set()), [_('Qualifier'), 'audit deny', _('Path'), '/foo', _('New Mode'), 'rlx -> /baz']), + (('/foo rw,', set('r'), set()), [ _('Path'), '/foo', _('Old Mode'), _('r'), _('New Mode'), 'rw']), # noqa: E201 + (('/foo rw,', set(), set('rw')), [ _('Path'), '/foo', _('Old Mode'), _('owner rw'), _('New Mode'), 'rw']), # noqa: E201 + (('/foo mrw,', set('r'), set('k')), [ _('Path'), '/foo', _('Old Mode'), _('r + owner k'), _('New Mode'), 'mrw']), # noqa: E201 + (('/foo mrw,', set('r'), set('rk')), [ _('Path'), '/foo', _('Old Mode'), _('r + owner k'), _('New Mode'), 'mrw']), # noqa: E201 + (('link /foo -> /bar,', set(), set()), [ _('Path'), '/foo', _('New Mode'), 'link -> /bar']), # noqa: E201 + (('link subset /foo -> /bar,', set(), set()), [ _('Path'), '/foo', _('New Mode'), 'link subset -> /bar']), # noqa: E201 ) def _run_test(self, params, expected): diff --git a/utils/test/test-include.py b/utils/test/test-include.py index db67adafa..9c1bf7039 100644 --- a/utils/test/test-include.py +++ b/utils/test/test-include.py @@ -37,6 +37,7 @@ class IncludeTest(AATest): self.assertEqual(False, obj.allow_keyword) # not supported in include rules, expected to be always False self.assertEqual(False, obj.audit) # not supported in include rules, expected to be always False self.assertEqual(False, obj.deny) # not supported in include rules, expected to be always False + self.assertEqual(None, obj.priority) # not supported in include rules, expected to be always None self.assertEqual(expected.comment, obj.comment) self.assertEqual(expected.path, obj.path) @@ -159,6 +160,10 @@ class InvalidIncludeInit(AATest): with self.assertRaises(AppArmorBug): IncludeRule('foo', False, False, deny=True) + def test_priority_true(self): + with self.assertRaises(AppArmorBug): + IncludeRule('foo', False, False, priority=0) + class InvalidIncludeTest(AATest): def _check_invalid_rawrule(self, rawrule, matches_regex=False): diff --git a/utils/test/test-io_uring.py b/utils/test/test-io_uring.py index f4763495c..957956d5f 100644 --- a/utils/test/test-io_uring.py +++ b/utils/test/test-io_uring.py @@ -64,10 +64,10 @@ class IOUringTestParseInvalid(AATest): IOUringRule.create_instance('foo,') def test_diff_non_iouringrule(self): - exp = namedtuple('exp', ('audit', 'deny')) + exp = namedtuple('exp', ('audit', 'deny', 'priority')) obj = IOUringRule(('sqpoll'), IOUringRule.ALL) with self.assertRaises(AppArmorBug): - obj.is_equal(exp(False, False), False) + obj.is_equal(exp(False, False, None), False) def test_diff_access(self): obj1 = IOUringRule(IOUringRule.ALL, IOUringRule.ALL) @@ -124,6 +124,10 @@ class WriteIOUringTestAATest(AATest): ('io_uring sqpoll label="tst",', 'io_uring sqpoll label="tst",'), ('io_uring (override_creds) label=bar,', 'io_uring override_creds label=bar,'), ('io_uring (sqpoll override_creds) label=/foo,', 'io_uring (override_creds sqpoll) label=/foo,'), + (' priority=1 deny io_uring override_creds ,# foo bar', 'priority=1 deny io_uring override_creds, # foo bar'), + (' priority=0 deny io_uring override_creds ,# foo bar', 'priority=0 deny io_uring override_creds, # foo bar'), + (' priority=-23 deny io_uring override_creds ,# foo bar', 'priority=-23 deny io_uring override_creds, # foo bar'), + (' priority=+21 deny io_uring override_creds ,# foo bar', 'priority=21 deny io_uring override_creds, # foo bar'), ) def _run_test(self, rawrule, expected): diff --git a/utils/test/test-modifiers.py b/utils/test/test-modifiers.py new file mode 100644 index 000000000..36d773e54 --- /dev/null +++ b/utils/test/test-modifiers.py @@ -0,0 +1,90 @@ +#! /usr/bin/python3 +# ------------------------------------------------------------------ +# +# Copyright (C) 2025 Canonical Ltd. +# +# 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 as 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. +# +# ---------------------------------------------------------------------- + +import unittest + +from apparmor.common import AppArmorException +from apparmor.rule.capability import CapabilityRule +from apparmor.rule.change_profile import ChangeProfileRule +from apparmor.rule.dbus import DbusRule +from apparmor.rule.file import FileRule +from apparmor.rule.io_uring import IOUringRule +from apparmor.rule.mount import MountRule +from apparmor.rule.mqueue import MessageQueueRule +from apparmor.rule.network import NetworkRule +from apparmor.rule.pivot_root import PivotRootRule +from apparmor.rule.ptrace import PtraceRule +from apparmor.rule.signal import SignalRule +from apparmor.rule.unix import UnixRule +from apparmor.rule.userns import UserNamespaceRule +from apparmor.rule.all import AllRule +from common_test import AATest, setup_all_loops + + +class TestInvalid_parse_priority(AATest): + tests = ( + ((CapabilityRule, 'priority=a capability,'), AppArmorException), + ((DbusRule, 'priority=a dbus,'), AppArmorException), + ((MountRule, 'priority=a mount,'), AppArmorException), + ((MountRule, 'priority=a umount,'), AppArmorException), + ((MountRule, 'priority=a unmount,'), AppArmorException), + ((MountRule, 'priority=a remount,'), AppArmorException), + ((SignalRule, 'priority=a signal,'), AppArmorException), + ((PtraceRule, 'priority=a ptrace,'), AppArmorException), + ((PivotRootRule, 'priority=a pivot_root,'), AppArmorException), + ((UnixRule, 'priority=a unix,'), AppArmorException), + ((NetworkRule, 'priority=a network,'), AppArmorException), + ((UserNamespaceRule, 'priority=a userns,'), AppArmorException), + ((MessageQueueRule, 'priority=a mqueue,'), AppArmorException), + ((IOUringRule, 'priority=a io_uring,'), AppArmorException), + ((ChangeProfileRule, 'priority=a change_profile,'), AppArmorException), + ((FileRule, 'priority=a file,'), AppArmorException), + ((AllRule, 'priority=a all,'), AppArmorException), + ) + + def _run_test(self, params, expected): + rule_cls, rule = params + with self.assertRaises(expected): + rule_cls.create_instance(rule) # Invalid rule + + +class TestInvalid_init_priority(AATest): + tests = ( + ((CapabilityRule, (CapabilityRule.ALL,)), AppArmorException), + ((DbusRule, (DbusRule.ALL,) * 8), AppArmorException), + ((MountRule, (MountRule.ALL,) * 5), AppArmorException), + ((SignalRule, (SignalRule.ALL,) * 3), AppArmorException), + ((PtraceRule, (PtraceRule.ALL,) * 2), AppArmorException), + ((PivotRootRule, (PivotRootRule.ALL,) * 3), AppArmorException), + ((UnixRule, (UnixRule.ALL,) * 4), AppArmorException), + ((NetworkRule, (NetworkRule.ALL,) * 5), AppArmorException), + ((UserNamespaceRule, (UserNamespaceRule.ALL,) * 1), AppArmorException), + ((MessageQueueRule, (MessageQueueRule.ALL,) * 4), AppArmorException), + ((IOUringRule, (IOUringRule.ALL,) * 2), AppArmorException), + ((ChangeProfileRule, (ChangeProfileRule.ALL,) * 3), AppArmorException), + ((FileRule, (FileRule.ALL,) * 5), AppArmorException), + ((AllRule, ()), AppArmorException), + ) + + def _run_test(self, params, expected): + rule_cls, args = params + with self.assertRaises(expected): + rule_cls(*args, priority="invalid") # ValueError + + +setup_all_loops(__name__) +if __name__ == '__main__': + unittest.main(verbosity=1) diff --git a/utils/test/test-mount.py b/utils/test/test-mount.py index 9b2aa4d9f..60676deb5 100644 --- a/utils/test/test-mount.py +++ b/utils/test/test-mount.py @@ -123,10 +123,10 @@ class MountTestParseInvalid(AATest): MountRule.create_instance('foo,') def test_diff_non_mountrule(self): - exp = namedtuple('exp', ('audit', 'deny')) + exp = namedtuple('exp', ('audit', 'deny', 'priority')) obj = MountRule('mount', ('=', ['ext4']), MountRule.ALL, MountRule.ALL, MountRule.ALL) with self.assertRaises(AppArmorBug): - obj.is_equal(exp(False, False), False) + obj.is_equal(exp(False, False, None), False) def test_diff_invalid_fstype_equals_or_in(self): with self.assertRaises(AppArmorBug): @@ -230,6 +230,12 @@ class MountTestClean(AATest): (' umount /foo , ', 'umount /foo,'), (' remount , ', 'remount,'), (' remount /foo , ', 'remount /foo,'), + ('priority =1 mount "" -> /foo , ', 'priority=1 mount "" -> /foo,'), + ('priority=0 audit mount "/f /b" -> "/foo bar" , ', 'priority=0 audit mount "/f /b" -> "/foo bar",'), + (' priority = +10 umount , ', 'priority=10 umount,'), + (' priority=-2 deny umount /foo , ', 'priority=-2 deny umount /foo,'), + ('priority= 32 audit deny remount , ', 'priority=32 audit deny remount,'), + (' priority = -32 remount /foo , ', 'priority=-32 remount /foo,'), ) def _run_test(self, rawrule, expected): diff --git a/utils/test/test-mqueue.py b/utils/test/test-mqueue.py index c737726f3..1f6199c07 100644 --- a/utils/test/test-mqueue.py +++ b/utils/test/test-mqueue.py @@ -77,10 +77,10 @@ class MessageQueueTestParseInvalid(AATest): MessageQueueRule.create_instance('foo,') def test_diff_non_mqueuerule(self): - exp = namedtuple('exp', ('audit', 'deny')) + exp = namedtuple('exp', ('audit', 'deny', 'priority')) obj = MessageQueueRule(('open'), 'posix', 'bar', '/foo') with self.assertRaises(AppArmorBug): - obj.is_equal(exp(False, False), False) + obj.is_equal(exp(False, False, None), False) def test_diff_access(self): obj1 = MessageQueueRule(('open'), 'posix', 'bar', '/foo') @@ -171,6 +171,10 @@ class WriteMessageQueueTestAATest(AATest): ('mqueue wr label=tst 1234,', 'mqueue wr label=tst 1234,'), ('mqueue wr type=sysv label=tst 1234,', 'mqueue wr type=sysv label=tst 1234,'), ('mqueue wr type=posix label=tst /foo,', 'mqueue wr type=posix label=tst /foo,'), + (' priority = -82 mqueue getattr /foo,', 'priority=-82 mqueue getattr /foo,'), + (' priority = 12 audit mqueue (setattr getattr) 1234,', 'priority=12 audit mqueue (getattr setattr) 1234,'), + (' priority=0 mqueue getattr /foo,', 'priority=0 mqueue getattr /foo,'), + (' priority=+82 mqueue getattr /foo,', 'priority=82 mqueue getattr /foo,'), ) def _run_test(self, rawrule, expected): diff --git a/utils/test/test-network.py b/utils/test/test-network.py index db3b341e8..a74fa32c2 100644 --- a/utils/test/test-network.py +++ b/utils/test/test-network.py @@ -286,6 +286,10 @@ class WriteNetworkTestAATest(AATest): (' network stream peer = ( ip=::1 port=22 ) ,', 'network stream peer=(ip=::1 port=22),'), (' network ( bind , listen ) stream ip = ::1 port = 22 ,', 'network (bind, listen) stream ip=::1 port=22,'), (' allow network tcp ,# foo bar', 'allow network tcp, # foo bar'), + (' priority = -02 allow network tcp ,# foo bar', 'priority=-2 allow network tcp, # foo bar'), + (' priority = 0 allow network tcp ,# foo bar', 'priority=0 allow network tcp, # foo bar'), + (' priority = 43 allow network tcp ,# foo bar', 'priority=43 allow network tcp, # foo bar'), + (' priority=+123 allow network tcp ,# foo bar', 'priority=123 allow network tcp, # foo bar'), ) diff --git a/utils/test/test-parser-simple-tests.py b/utils/test/test-parser-simple-tests.py index 154c5e28d..04e03fb68 100644 --- a/utils/test/test-parser-simple-tests.py +++ b/utils/test/test-parser-simple-tests.py @@ -35,9 +35,6 @@ skip_startswith = ( # Pux and Cux (which actually mean PUx and CUx) get rejected by the tools 'generated_x/exact-', - - # don't handle rule priorities yet - 'file/priority/', ) # testcases that should raise an exception, but don't @@ -246,11 +243,16 @@ unknown_line = ( 'file/ok_other_1.sd', 'file/ok_other_2.sd', 'file/ok_other_3.sd', + 'file/priority/ok_other_1.sd', + 'file/priority/ok_other_2.sd', + 'file/priority/ok_other_3.sd', # 'unsafe' keyword 'file/file/front_perms_ok_2.sd', 'file/front_perms_ok_2.sd', 'xtrans/simple_ok_cx_1.sd', + 'file/priority/front_perms_ok_3.sd', + 'file/priority/front_perms_ok_4.sd', # owner / audit {...} blocks 'file/file/owner/ok_1.sd', @@ -355,6 +357,9 @@ syntax_failure = ( 'file/ok_5.sd', # Invalid mode UX 'file/ok_2.sd', # Invalid mode RWM 'file/ok_4.sd', # Invalid mode iX + 'file/priority/ok_5.sd', # Invalid mode UX + 'file/priority/ok_2.sd', # Invalid mode RWM + 'file/priority/ok_4.sd', # Invalid mode iX 'xtrans/simple_ok_pix_1.sd', # Invalid mode pIx 'xtrans/simple_ok_pux_1.sd', # Invalid mode rPux @@ -424,6 +429,8 @@ syntax_failure = ( 'file/ok_embedded_spaces_4.sd', # \-escaped space 'file/file/ok_embedded_spaces_4.sd', # \-escaped space 'file/ok_quoted_4.sd', # quoted string including \" + 'file/priority/ok_quoted_4.sd', # quoted string including \" + 'file/priority/ok_embedded_spaces_4.sd', # \-escaped space # mount rules with multiple 'options' or 'fstype' are not supported by the tools yet, and when writing them, only the last 'options'/'fstype' would survive. # Therefore MountRule intentionally raises an exception when parsing such a rule. diff --git a/utils/test/test-pivot_root.py b/utils/test/test-pivot_root.py index ceaf59ab7..1b6fcc816 100644 --- a/utils/test/test-pivot_root.py +++ b/utils/test/test-pivot_root.py @@ -261,6 +261,10 @@ class WritePivotRootTestAATest(AATest): (' pivot_root oldroot="/old" , # foo ', 'pivot_root oldroot=/old, # foo'), (' pivot_root oldroot=/old -> some_profile , ', 'pivot_root oldroot=/old -> some_profile,'), (' pivot_root oldroot=/old /new -> some_profile , ', 'pivot_root oldroot=/old /new -> some_profile,'), + ('priority=1 pivot_root oldroot=/old /new -> some_profile , ', 'priority=1 pivot_root oldroot=/old /new -> some_profile,'), + ('priority=0 pivot_root oldroot=/old /new -> some_profile , ', 'priority=0 pivot_root oldroot=/old /new -> some_profile,'), + ('priority=-1 pivot_root oldroot=/old /new -> some_profile , ', 'priority=-1 pivot_root oldroot=/old /new -> some_profile,'), + ('priority=+1 pivot_root oldroot=/old /new -> some_profile , ', 'priority=1 pivot_root oldroot=/old /new -> some_profile,'), ) def test_write_manually(self): diff --git a/utils/test/test-ptrace.py b/utils/test/test-ptrace.py index 18362f262..5193d99c5 100644 --- a/utils/test/test-ptrace.py +++ b/utils/test/test-ptrace.py @@ -260,6 +260,10 @@ class WritePtraceTestAATest(AATest): ('ptrace (read tracedby) peer=/usr/bin/bar,', 'ptrace (read tracedby) peer=/usr/bin/bar,'), ('ptrace (trace read) peer=/usr/bin/bar,', 'ptrace (read trace) peer=/usr/bin/bar,'), ('ptrace wr peer=/sbin/baz,', 'ptrace wr peer=/sbin/baz,'), + ('priority = 010 deny ptrace ( read ), ', 'priority=10 deny ptrace read,'), + ('priority = 0 deny ptrace ( read ), ', 'priority=0 deny ptrace read,'), + ('priority = -21 deny ptrace ( read ), ', 'priority=-21 deny ptrace read,'), + ('priority = +83 deny ptrace ( read ), ', 'priority=83 deny ptrace read,'), ) def test_write_manually(self): diff --git a/utils/test/test-regex_matches.py b/utils/test/test-regex_matches.py index 927f0ea6f..243707762 100644 --- a/utils/test/test-regex_matches.py +++ b/utils/test/test-regex_matches.py @@ -218,11 +218,16 @@ class AARegexCapability(AARegexTest): self.regex = RE_PROFILE_CAP tests = ( - (' capability net_raw,', (None, None, 'net_raw', 'net_raw', None)), - ('capability net_raw , ', (None, None, 'net_raw', 'net_raw', None)), - (' capability,', (None, None, None, None, None)), - (' capability , ', (None, None, None, None, None)), - (' capabilitynet_raw,', False) + (' capability net_raw,', (None, None, None, None, 'net_raw', 'net_raw', None)), + ('capability net_raw , ', (None, None, None, None, 'net_raw', 'net_raw', None)), + (' capability,', (None, None, None, None, None, None, None)), + (' capability , ', (None, None, None, None, None, None, None)), + (' capabilitynet_raw,', False), + (' priority=1 capability net_raw,', ('priority=1', '1', None, None, 'net_raw', 'net_raw', None)), + ('priority=1 capability net_raw , ', ('priority=1', '1', None, None, 'net_raw', 'net_raw', None)), + (' priority=1 capability,', ('priority=1', '1', None, None, None, None, None)), + (' priority=1 capability , ', ('priority=1', '1', None, None, None, None, None)), + (' priority=1 capabilitynet_raw,', False), ) @@ -233,13 +238,19 @@ class AARegexDbus(AARegexTest): self.regex = RE_PROFILE_DBUS tests = ( - (' dbus,', (None, None, 'dbus,', None, None)), - (' audit dbus,', ('audit', None, 'dbus,', None, None)), - (' dbus send member=no_comment,', (None, None, 'dbus send member=no_comment,', 'send member=no_comment', None)), - (' dbus send member=no_comment, # comment', (None, None, 'dbus send member=no_comment,', 'send member=no_comment', '# comment')), + (' dbus,', (None, None, None, None, 'dbus,', None, None)), + (' audit dbus,', (None, None, 'audit', None, 'dbus,', None, None)), + (' dbus send member=no_comment,', (None, None, None, None, 'dbus send member=no_comment,', 'send member=no_comment', None)), + (' dbus send member=no_comment, # comment', (None, None, None, None, 'dbus send member=no_comment,', 'send member=no_comment', '# comment')), + + (' priority=-11 dbus,', ('priority=-11', '-11', None, None, 'dbus,', None, None)), + (' priority=-11 audit dbus,', ('priority=-11', '-11', 'audit', None, 'dbus,', None, None)), + (' priority=-11 dbus send member=no_comment,', ('priority=-11', '-11', None, None, 'dbus send member=no_comment,', 'send member=no_comment', None)), + (' priority=-11 dbus send member=no_comment, # comment', ('priority=-11', '-11', None, None, 'dbus send member=no_comment,', 'send member=no_comment', '# comment')), (' dbusdriver,', False), (' audit dbusdriver,', False), + (' priority=-11 audit dbusdriver,', False), ) @@ -250,19 +261,30 @@ class AARegexMount(AARegexTest): self.regex = RE_PROFILE_MOUNT tests = ( - (' mount,', (None, None, 'mount,', 'mount', None, None)), - (' audit mount,', ('audit', None, 'mount,', 'mount', None, None)), - (' umount,', (None, None, 'umount,', 'umount', None, None)), - (' audit umount,', ('audit', None, 'umount,', 'umount', None, None)), - (' unmount,', (None, None, 'unmount,', 'unmount', None, None)), - (' audit unmount,', ('audit', None, 'unmount,', 'unmount', None, None)), - (' remount,', (None, None, 'remount,', 'remount', None, None)), - (' deny remount,', (None, 'deny', 'remount,', 'remount', None, None)), + (' mount,', (None, None, None, None, 'mount,', 'mount', None, None)), + (' audit mount,', (None, None, 'audit', None, 'mount,', 'mount', None, None)), + (' umount,', (None, None, None, None, 'umount,', 'umount', None, None)), + (' audit umount,', (None, None, 'audit', None, 'umount,', 'umount', None, None)), + (' unmount,', (None, None, None, None, 'unmount,', 'unmount', None, None)), + (' audit unmount,', (None, None, 'audit', None, 'unmount,', 'unmount', None, None)), + (' remount,', (None, None, None, None, 'remount,', 'remount', None, None)), + (' deny remount,', (None, None, None, 'deny', 'remount,', 'remount', None, None)), - (' mount, # comment', (None, None, 'mount,', 'mount', None, '# comment')), + (' priority = 0 mount,', ('priority = 0', '0', None, None, 'mount,', 'mount', None, None)), + (' priority = 0 audit mount,', ('priority = 0', '0', 'audit', None, 'mount,', 'mount', None, None)), + (' priority = 0 umount,', ('priority = 0', '0', None, None, 'umount,', 'umount', None, None)), + (' priority = 0 audit umount,', ('priority = 0', '0', 'audit', None, 'umount,', 'umount', None, None)), + (' priority = 0 unmount,', ('priority = 0', '0', None, None, 'unmount,', 'unmount', None, None)), + (' priority = 0 audit unmount,', ('priority = 0', '0', 'audit', None, 'unmount,', 'unmount', None, None)), + (' priority = 0 remount,', ('priority = 0', '0', None, None, 'remount,', 'remount', None, None)), + (' priority = 0 deny remount,', ('priority = 0', '0', None, 'deny', 'remount,', 'remount', None, None)), + + (' mount, # comment', (None, None, None, None, 'mount,', 'mount', None, '# comment')), + (' priority = 0 mount, # comment', ('priority = 0', '0', None, None, 'mount,', 'mount', None, '# comment')), (' mountain,', False), (' audit mountain,', False), + (' priority = 0 audit mountain,', False), ) @@ -273,16 +295,25 @@ class AARegexSignal(AARegexTest): self.regex = RE_PROFILE_SIGNAL tests = ( - (' signal,', (None, None, 'signal,', None, None)), - (' audit signal,', ('audit', None, 'signal,', None, None)), - (' signal receive,', (None, None, 'signal receive,', 'receive', None)), - (' signal (send, receive),', (None, None, 'signal (send, receive),', '(send, receive)', None)), - (' audit signal (receive),', ('audit', None, 'signal (receive),', '(receive)', None)), - (' signal (send, receive) set=(usr1 usr2),', (None, None, 'signal (send, receive) set=(usr1 usr2),', '(send, receive) set=(usr1 usr2)', None)), - (' signal send set=(hup, quit) peer=/usr/sbin/daemon,', (None, None, 'signal send set=(hup, quit) peer=/usr/sbin/daemon,', 'send set=(hup, quit) peer=/usr/sbin/daemon', None)), + (' signal,', (None, None, None, None, 'signal,', None, None)), + (' audit signal,', (None, None, 'audit', None, 'signal,', None, None)), + (' signal receive,', (None, None, None, None, 'signal receive,', 'receive', None)), + (' signal (send, receive),', (None, None, None, None, 'signal (send, receive),', '(send, receive)', None)), + (' audit signal (receive),', (None, None, 'audit', None, 'signal (receive),', '(receive)', None)), + (' signal (send, receive) set=(usr1 usr2),', (None, None, None, None, 'signal (send, receive) set=(usr1 usr2),', '(send, receive) set=(usr1 usr2)', None)), + (' signal send set=(hup, quit) peer=/usr/sbin/daemon,', (None, None, None, None, 'signal send set=(hup, quit) peer=/usr/sbin/daemon,', 'send set=(hup, quit) peer=/usr/sbin/daemon', None)), + + (' priority = -1 signal,', ('priority = -1', '-1', None, None, 'signal,', None, None)), + (' priority = -1 audit signal,', ('priority = -1', '-1', 'audit', None, 'signal,', None, None)), + (' priority = -1 signal receive,', ('priority = -1', '-1', None, None, 'signal receive,', 'receive', None)), + (' priority = -1 signal (send, receive),', ('priority = -1', '-1', None, None, 'signal (send, receive),', '(send, receive)', None)), + (' priority = -1 audit signal (receive),', ('priority = -1', '-1', 'audit', None, 'signal (receive),', '(receive)', None)), + (' priority = -1 signal (send, receive) set=(usr1 usr2),', ('priority = -1', '-1', None, None, 'signal (send, receive) set=(usr1 usr2),', '(send, receive) set=(usr1 usr2)', None)), + (' priority = -1 signal send set=(hup, quit) peer=/usr/sbin/daemon,', ('priority = -1', '-1', None, None, 'signal send set=(hup, quit) peer=/usr/sbin/daemon,', 'send set=(hup, quit) peer=/usr/sbin/daemon', None)), (' signalling,', False), (' audit signalling,', False), + (' priority = -1 audit signalling,', False), (' signalling receive,', False), ) @@ -294,16 +325,24 @@ class AARegexPtrace(AARegexTest): self.regex = RE_PROFILE_PTRACE tests = ( - # audit allow rule rule details comment - (' ptrace,', (None, None, 'ptrace,', None, None)), - (' audit ptrace,', ('audit', None, 'ptrace,', None, None)), - (' ptrace trace,', (None, None, 'ptrace trace,', 'trace', None)), - (' ptrace (tracedby, readby),', (None, None, 'ptrace (tracedby, readby),', '(tracedby, readby)', None)), - (' audit ptrace (read),', ('audit', None, 'ptrace (read),', '(read)', None)), - (' ptrace trace peer=/usr/sbin/daemon,', (None, None, 'ptrace trace peer=/usr/sbin/daemon,', 'trace peer=/usr/sbin/daemon', None)), + # priority audit allow rule rule details comment + (' ptrace,', (None, None, None, None, 'ptrace,', None, None)), + (' audit ptrace,', (None, None, 'audit', None, 'ptrace,', None, None)), + (' ptrace trace,', (None, None, None, None, 'ptrace trace,', 'trace', None)), + (' ptrace (tracedby, readby),', (None, None, None, None, 'ptrace (tracedby, readby),', '(tracedby, readby)', None)), + (' audit ptrace (read),', (None, None, 'audit', None, 'ptrace (read),', '(read)', None)), + (' ptrace trace peer=/usr/sbin/daemon,', (None, None, None, None, 'ptrace trace peer=/usr/sbin/daemon,', 'trace peer=/usr/sbin/daemon', None)), + + (' priority=100 ptrace,', ('priority=100', '100', None, None, 'ptrace,', None, None)), + (' priority=100 audit ptrace,', ('priority=100', '100', 'audit', None, 'ptrace,', None, None)), + (' priority=100 ptrace trace,', ('priority=100', '100', None, None, 'ptrace trace,', 'trace', None)), + (' priority=100 ptrace (tracedby, readby),', ('priority=100', '100', None, None, 'ptrace (tracedby, readby),', '(tracedby, readby)', None)), + (' priority=100 audit ptrace (read),', ('priority=100', '100', 'audit', None, 'ptrace (read),', '(read)', None)), + (' priority=100 ptrace trace peer=/usr/sbin/daemon,', ('priority=100', '100', None, None, 'ptrace trace peer=/usr/sbin/daemon,', 'trace peer=/usr/sbin/daemon', None)), (' ptraceback,', False), (' audit ptraceback,', False), + (' priority=100 audit ptraceback,', False), (' ptraceback trace,', False), ) @@ -315,12 +354,19 @@ class AARegexPivotRoot(AARegexTest): self.regex = RE_PROFILE_PIVOT_ROOT tests = ( - (' pivot_root,', (None, None, 'pivot_root,', None, None)), - (' audit pivot_root,', ('audit', None, 'pivot_root,', None, None)), - (' pivot_root oldroot=/new/old,', (None, None, 'pivot_root oldroot=/new/old,', 'oldroot=/new/old', None)), - (' pivot_root oldroot=/new/old /new,', (None, None, 'pivot_root oldroot=/new/old /new,', 'oldroot=/new/old /new', None)), - (' pivot_root oldroot=/new/old /new -> child,', (None, None, 'pivot_root oldroot=/new/old /new -> child,', 'oldroot=/new/old /new -> child', None)), - (' audit pivot_root oldroot=/new/old /new -> child,', ('audit', None, 'pivot_root oldroot=/new/old /new -> child,', 'oldroot=/new/old /new -> child', None)), + (' pivot_root,', (None, None, None, None, 'pivot_root,', None, None)), + (' audit pivot_root,', (None, None, 'audit', None, 'pivot_root,', None, None)), + (' pivot_root oldroot=/new/old,', (None, None, None, None, 'pivot_root oldroot=/new/old,', 'oldroot=/new/old', None)), + (' pivot_root oldroot=/new/old /new,', (None, None, None, None, 'pivot_root oldroot=/new/old /new,', 'oldroot=/new/old /new', None)), + (' pivot_root oldroot=/new/old /new -> child,', (None, None, None, None, 'pivot_root oldroot=/new/old /new -> child,', 'oldroot=/new/old /new -> child', None)), + (' audit pivot_root oldroot=/new/old /new -> child,', (None, None, 'audit', None, 'pivot_root oldroot=/new/old /new -> child,', 'oldroot=/new/old /new -> child', None)), + + (' priority=-100 pivot_root,', ('priority=-100', '-100', None, None, 'pivot_root,', None, None)), + (' priority=-100 audit pivot_root,', ('priority=-100', '-100', 'audit', None, 'pivot_root,', None, None)), + (' priority=-100 pivot_root oldroot=/new/old,', ('priority=-100', '-100', None, None, 'pivot_root oldroot=/new/old,', 'oldroot=/new/old', None)), + (' priority=-100 pivot_root oldroot=/new/old /new,', ('priority=-100', '-100', None, None, 'pivot_root oldroot=/new/old /new,', 'oldroot=/new/old /new', None)), + (' priority=-100 pivot_root oldroot=/new/old /new -> child,', ('priority=-100', '-100', None, None, 'pivot_root oldroot=/new/old /new -> child,', 'oldroot=/new/old /new -> child', None)), + (' priority=-100 audit pivot_root oldroot=/new/old /new -> child,', ('priority=-100', '-100', 'audit', None, 'pivot_root oldroot=/new/old /new -> child,', 'oldroot=/new/old /new -> child', None)), ('pivot_root', False), # comma missing @@ -329,6 +375,7 @@ class AARegexPivotRoot(AARegexTest): ('pivot_rootbeer, # comment', False), ('pivot_rootbeer /new, ', False), ('pivot_rootbeer /new, # comment', False), + ('priority=-100 pivot_rootbeer /new, # comment', False), ) @@ -339,20 +386,35 @@ class AARegexUnix(AARegexTest): self.regex = RE_PROFILE_UNIX tests = ( - (' unix,', (None, None, 'unix,', None, None)), - (' audit unix,', ('audit', None, 'unix,', None, None)), - (' unix accept,', (None, None, 'unix accept,', 'accept', None)), - (' allow unix connect,', (None, 'allow', 'unix connect,', 'connect', None)), - (' audit allow unix bind,', ('audit', 'allow', 'unix bind,', 'bind', None)), - (' deny unix bind,', (None, 'deny', 'unix bind,', 'bind', None)), - ('unix peer=(label=@{profile_name}),', (None, None, 'unix peer=(label=@{profile_name}),', 'peer=(label=@{profile_name})', None)), - ('unix (receive) peer=(label=unconfined),', (None, None, 'unix (receive) peer=(label=unconfined),', '(receive) peer=(label=unconfined)', None)), - (' unix (getattr, shutdown) peer=(addr=none),', (None, None, 'unix (getattr, shutdown) peer=(addr=none),', '(getattr, shutdown) peer=(addr=none)', None)), - ('unix (connect, receive, send) type=stream peer=(label=unconfined,addr="@/tmp/dbus-*"),', (None, None, 'unix (connect, receive, send) type=stream peer=(label=unconfined,addr="@/tmp/dbus-*"),', + (' unix,', (None, None, None, None, 'unix,', None, None)), + (' audit unix,', (None, None, 'audit', None, 'unix,', None, None)), + (' unix accept,', (None, None, None, None, 'unix accept,', 'accept', None)), + (' allow unix connect,', (None, None, None, 'allow', 'unix connect,', 'connect', None)), + (' audit allow unix bind,', (None, None, 'audit', 'allow', 'unix bind,', 'bind', None)), + (' deny unix bind,', (None, None, None, 'deny', 'unix bind,', 'bind', None)), + ('unix peer=(label=@{profile_name}),', (None, None, None, None, 'unix peer=(label=@{profile_name}),', 'peer=(label=@{profile_name})', None)), + ('unix (receive) peer=(label=unconfined),', (None, None, None, None, 'unix (receive) peer=(label=unconfined),', '(receive) peer=(label=unconfined)', None)), + (' unix (getattr, shutdown) peer=(addr=none),', (None, None, None, None, 'unix (getattr, shutdown) peer=(addr=none),', '(getattr, shutdown) peer=(addr=none)', None)), + ('unix (connect, receive, send) type=stream peer=(label=unconfined,addr="@/tmp/dbus-*"),', (None, None, None, None, 'unix (connect, receive, send) type=stream peer=(label=unconfined,addr="@/tmp/dbus-*"),', '(connect, receive, send) type=stream peer=(label=unconfined,addr="@/tmp/dbus-*")', # noqa: E127 None)), # noqa: E127 + + (' priority=1 unix,', ('priority=1', '1', None, None, 'unix,', None, None)), + (' priority=1 audit unix,', ('priority=1', '1', 'audit', None, 'unix,', None, None)), + (' priority=1 unix accept,', ('priority=1', '1', None, None, 'unix accept,', 'accept', None)), + (' priority=1 allow unix connect,', ('priority=1', '1', None, 'allow', 'unix connect,', 'connect', None)), + (' priority=1 audit allow unix bind,', ('priority=1', '1', 'audit', 'allow', 'unix bind,', 'bind', None)), + (' priority=1 deny unix bind,', ('priority=1', '1', None, 'deny', 'unix bind,', 'bind', None)), + ('priority=1 unix peer=(label=@{profile_name}),', ('priority=1', '1', None, None, 'unix peer=(label=@{profile_name}),', 'peer=(label=@{profile_name})', None)), + ('priority=1 unix (receive) peer=(label=unconfined),', ('priority=1', '1', None, None, 'unix (receive) peer=(label=unconfined),', '(receive) peer=(label=unconfined)', None)), + (' priority=1 unix (getattr, shutdown) peer=(addr=none),', ('priority=1', '1', None, None, 'unix (getattr, shutdown) peer=(addr=none),', '(getattr, shutdown) peer=(addr=none)', None)), + ('priority=1 unix (connect, receive, send) type=stream peer=(label=unconfined,addr="@/tmp/dbus-*"),', ('priority=1', '1', None, None, 'unix (connect, receive, send) type=stream peer=(label=unconfined,addr="@/tmp/dbus-*"),', + '(connect, receive, send) type=stream peer=(label=unconfined,addr="@/tmp/dbus-*")', # noqa: E127 + None)), # noqa: E127 + ('unixlike', False), ('deny unixlike,', False), + ('priority=1 deny unixlike,', False), ) diff --git a/utils/test/test-rlimit.py b/utils/test/test-rlimit.py index 532d53492..7bbd3a7b7 100644 --- a/utils/test/test-rlimit.py +++ b/utils/test/test-rlimit.py @@ -174,6 +174,10 @@ class InvalidRlimitInit(AATest): with self.assertRaises(AppArmorBug): RlimitRule('as', '1024MB', audit=True) + def test_priority_keyword(self): + with self.assertRaises(AppArmorBug): + RlimitRule('as', '1024MB', priority=0) + class InvalidRlimitTest(AATest): def _check_invalid_rawrule(self, rawrule): diff --git a/utils/test/test-signal.py b/utils/test/test-signal.py index 58c6af44e..92f7cf771 100644 --- a/utils/test/test-signal.py +++ b/utils/test/test-signal.py @@ -277,6 +277,10 @@ class WriteSignalTestAATest(AATest): ('signal receive peer=foo,', 'signal receive peer=foo,'), ('signal (send receive) peer=/usr/bin/bar,', 'signal (receive send) peer=/usr/bin/bar,'), ('signal wr set=(pipe, usr1) peer=/sbin/baz,', 'signal wr set=(pipe usr1) peer=/sbin/baz,'), + ('priority = 29 signal receive peer=foo,', 'priority=29 signal receive peer=foo,'), + ('priority = 0 signal receive peer=foo,', 'priority=0 signal receive peer=foo,'), + ('priority =-123 signal receive peer=foo,', 'priority=-123 signal receive peer=foo,'), + ('priority =+10 signal receive peer=foo,', 'priority=10 signal receive peer=foo,'), ) def test_write_manually(self): diff --git a/utils/test/test-unix.py b/utils/test/test-unix.py index 104abc1da..5fbf013c9 100644 --- a/utils/test/test-unix.py +++ b/utils/test/test-unix.py @@ -166,15 +166,18 @@ class UnixTestGlob(AATest): class UnixTestClean(AATest): tests = ( - (' audit unix , # foo ', 'audit unix, # foo'), - (' audit deny unix label = foo , ', 'audit deny unix label=foo,'), - (' audit allow unix peer = (addr = a) , # foo ', 'audit allow unix peer=(addr=a), # foo'), - (' deny unix type = foo , ', 'deny unix type=foo,'), - (' allow unix peer = (label=bb) , # foo ', 'allow unix peer=(label=bb), # foo'), - (' unix , # foo ', 'unix, # foo'), - (' unix addr = foo , ', 'unix addr=foo,'), - (' unix ( accept , rw) protocol = AA type = BB opt = myopt label = bb peer = (addr = a label = bb ) , ', 'unix (accept, rw) type=BB protocol=AA label=bb opt=myopt peer=(addr=a label=bb),'), - + (' audit unix , # foo ', 'audit unix, # foo'), + (' audit deny unix label = foo , ', 'audit deny unix label=foo,'), + (' audit allow unix peer = (addr = a) , # foo ', 'audit allow unix peer=(addr=a), # foo'), + (' deny unix type = foo , ', 'deny unix type=foo,'), + (' allow unix peer = (label=bb) , # foo ', 'allow unix peer=(label=bb), # foo'), + (' unix , # foo ', 'unix, # foo'), + (' unix addr = foo , ', 'unix addr=foo,'), + (' unix ( accept , rw) protocol = AA type = BB opt = myopt label = bb peer = (addr = a label = bb ) , ', 'unix (accept, rw) type=BB protocol=AA label=bb opt=myopt peer=(addr=a label=bb),'), + ('priority=-42 unix ( accept , rw) protocol = AA type = BB opt = myopt label = bb peer = (addr = a label = bb ), ', 'priority=-42 unix (accept, rw) type=BB protocol=AA label=bb opt=myopt peer=(addr=a label=bb),'), + ('priority = 0 unix ( accept , rw) protocol = AA type = BB opt = myopt label = bb peer = (addr = a label = bb ), ', 'priority=0 unix (accept, rw) type=BB protocol=AA label=bb opt=myopt peer=(addr=a label=bb),'), + ('priority=211 unix ( accept , rw) protocol = AA type = BB opt = myopt label = bb peer = (addr = a label = bb ), ', 'priority=211 unix (accept, rw) type=BB protocol=AA label=bb opt=myopt peer=(addr=a label=bb),'), + ('priority=+45 unix ( accept , rw) protocol = AA type = BB opt = myopt label = bb peer = (addr = a label = bb ), ', 'priority=45 unix (accept, rw) type=BB protocol=AA label=bb opt=myopt peer=(addr=a label=bb),'), ) def _run_test(self, rawrule, expected): diff --git a/utils/test/test-userns.py b/utils/test/test-userns.py index 82e523fd0..4d5419eed 100644 --- a/utils/test/test-userns.py +++ b/utils/test/test-userns.py @@ -59,10 +59,10 @@ class UserNamespaceTestParseInvalid(AATest): UserNamespaceRule.create_instance('foo,') def test_diff_non_usernsrule(self): - exp = namedtuple('exp', ('audit', 'deny')) + exp = namedtuple('exp', ('audit', 'deny', 'priority')) obj = UserNamespaceRule(('create')) with self.assertRaises(AppArmorBug): - obj.is_equal(exp(False, False), False) + obj.is_equal(exp(False, False, None), False) def test_diff_access(self): obj1 = UserNamespaceRule(UserNamespaceRule.ALL) @@ -98,6 +98,10 @@ class WriteUserNamespaceTestAATest(AATest): (' allow userns create ,# foo bar', 'allow userns create, # foo bar'), ('userns,', 'userns,'), ('userns create,', 'userns create,'), + (' priority = -1 allow userns create,', 'priority=-1 allow userns create,'), + (' priority = 0 allow userns create,', 'priority=0 allow userns create,'), + (' priority=+234 allow userns create,', 'priority=234 allow userns create,'), + (' priority = 65 allow userns create,', 'priority=65 allow userns create,'), ) def _run_test(self, rawrule, expected): diff --git a/utils/test/test-variable.py b/utils/test/test-variable.py index 1dcedc3dd..eba5b3f03 100644 --- a/utils/test/test-variable.py +++ b/utils/test/test-variable.py @@ -30,10 +30,11 @@ exp = namedtuple('exp', ('comment', 'varname', 'mode', 'values')) class VariableTest(AATest): def _compare_obj(self, obj, expected): - # variables don't support the allow, audit or deny keyword + # variables don't support the allow, audit, deny, or priority keyword self.assertEqual(False, obj.allow_keyword) self.assertEqual(False, obj.audit) self.assertEqual(False, obj.deny) + self.assertEqual(None, obj.priority) self.assertEqual(expected.varname, obj.varname) self.assertEqual(expected.mode, obj.mode) @@ -166,6 +167,14 @@ class InvalidVariableInit(AATest): with self.assertRaises(AppArmorBug): VariableRule('@{foo}', '=', '/bar', deny=True) + def test_invalid_priority_1(self): + with self.assertRaises(AppArmorBug): + VariableRule('@{foo}', '=', '/bar', priority=98) + + def test_invalid_priority_2(self): + with self.assertRaises(AppArmorBug): + VariableRule('@{foo}', '=', '/bar', priority=0) + class InvalidVariableTest(AATest): def _check_invalid_rawrule(self, rawrule, matches_regex=False):