diff --git a/parser/af_rule.cc b/parser/af_rule.cc index c974d5ce6..770b56e54 100644 --- a/parser/af_rule.cc +++ b/parser/af_rule.cc @@ -90,15 +90,6 @@ int af_rule::move_base_cond(struct cond_entry *ent, bool peer) return true; } -ostream &af_rule::dump_prefix(ostream &os) -{ - if (audit == AUDIT_FORCE) - os << "audit "; - if (deny) - os << "deny "; - return os; -} - ostream &af_rule::dump_local(ostream &os) { if (perms != AA_VALID_NET_PERMS) { @@ -148,7 +139,7 @@ ostream &af_rule::dump_peer(ostream &os) ostream &af_rule::dump(ostream &os) { - dump_prefix(os); + prefix_rule_t::dump(os); os << af_name; dump_local(os); if (has_peer_conds()) { diff --git a/parser/af_rule.h b/parser/af_rule.h index 99253a834..422bc6b69 100644 --- a/parser/af_rule.h +++ b/parser/af_rule.h @@ -35,7 +35,7 @@ struct supported_cond { enum cond_side side ; }; -class af_rule: public rule_t { +class af_rule: public perms_rule_t { public: std::string af_name; char *sock_type; @@ -44,13 +44,10 @@ public: int proto_n; char *label; char *peer_label; - perms_t perms; - audit_t audit; - bool deny; af_rule(const char *name): af_name(name), sock_type(NULL), sock_type_n(-1), proto(NULL), proto_n(0), label(NULL), - peer_label(NULL), perms(0), audit(AUDIT_UNSPECIFIED), deny(0) + peer_label(NULL) {} virtual ~af_rule() @@ -66,7 +63,6 @@ public: int move_base_cond(struct cond_entry *conds, bool peer); virtual bool has_peer_conds(void) { return peer_label ? true : false; } - virtual ostream &dump_prefix(ostream &os); virtual ostream &dump_local(ostream &os); virtual ostream &dump_peer(ostream &os); virtual ostream &dump(ostream &os); diff --git a/parser/af_unix.h b/parser/af_unix.h index 26615d26c..861b25ecc 100644 --- a/parser/af_unix.h +++ b/parser/af_unix.h @@ -46,6 +46,13 @@ public: free(peer_addr); }; + virtual bool valid_prefix(prefixes &p, const char *&error) { + if (p.owner) { + error = "owner prefix not allowed on unix rules"; + return false; + } + return true; + }; virtual bool has_peer_conds(void) { return af_rule::has_peer_conds() || peer_addr; } diff --git a/parser/dbus.cc b/parser/dbus.cc index e597d0338..bcd4536df 100644 --- a/parser/dbus.cc +++ b/parser/dbus.cc @@ -68,8 +68,7 @@ void dbus_rule::move_conditionals(struct cond_entry *conds) dbus_rule::dbus_rule(perms_t perms_p, struct cond_entry *conds, struct cond_entry *peer_conds): - bus(NULL), name(NULL), peer_label(NULL), path(NULL), interface(NULL), member(NULL), - perms(0), audit(AUDIT_UNSPECIFIED), deny(0) + bus(NULL), name(NULL), peer_label(NULL), path(NULL), interface(NULL), member(NULL) { int name_is_subject_cond = 0, message_rule = 0, service_rule = 0; @@ -122,13 +121,11 @@ dbus_rule::dbus_rule(perms_t perms_p, struct cond_entry *conds, ostream &dbus_rule::dump(ostream &os) { - if (audit == AUDIT_FORCE) - os << "audit "; - if (deny) - os << "deny "; + prefix_rule_t::dump(os); os << "dbus ( "; + /* override default perms */ if (perms & AA_DBUS_SEND) os << "send "; if (perms & AA_DBUS_RECEIVE) diff --git a/parser/dbus.h b/parser/dbus.h index cdd1f5cb1..f8da1d07d 100644 --- a/parser/dbus.h +++ b/parser/dbus.h @@ -25,7 +25,7 @@ extern int parse_dbus_perms(const char *str_mode, perms_t *mode, int fail); -class dbus_rule: public rule_t { +class dbus_rule: public perms_rule_t { void move_conditionals(struct cond_entry *conds); public: char *bus; @@ -39,9 +39,6 @@ public: char *path; char *interface; char *member; - perms_t perms; - audit_t audit; - int deny; dbus_rule(perms_t perms_p, struct cond_entry *conds, struct cond_entry *peer_conds); @@ -53,6 +50,13 @@ public: free(interface); free(member); }; + virtual bool valid_prefix(prefixes &p, const char *&error) { + if (p.owner) { + error = "owner prefix not allowed on dbus rules"; + return false; + } + return true; + }; virtual ostream &dump(ostream &os); virtual int expand_variables(void); diff --git a/parser/mount.cc b/parser/mount.cc index 3c2db1ecd..66b2bdc0d 100644 --- a/parser/mount.cc +++ b/parser/mount.cc @@ -469,7 +469,7 @@ mnt_rule::mnt_rule(struct cond_entry *src_conds, char *device_p, struct cond_entry *dst_conds unused, char *mnt_point_p, perms_t perms_p): mnt_point(mnt_point_p), device(device_p), trans(NULL), opts(NULL), - flagsv(0), opt_flagsv(0), audit(AUDIT_UNSPECIFIED), deny(0) + flagsv(0), opt_flagsv(0) { /* FIXME: dst_conds are ignored atm */ dev_type = extract_fstype(&src_conds); @@ -551,6 +551,8 @@ mnt_rule::mnt_rule(struct cond_entry *src_conds, char *device_p, ostream &mnt_rule::dump(ostream &os) { + prefix_rule_t::dump(os); + if (perms & AA_MAY_MOUNT) os << "mount"; else if (perms & AA_MAY_UMOUNT) @@ -580,8 +582,8 @@ ostream &mnt_rule::dump(ostream &os) if (trans) os << " -> " << trans; - const char *prefix = deny ? "deny" : ""; - os << " " << prefix << "(0x" << hex << perms << "/0x" << (audit != AUDIT_UNSPECIFIED ? perms : 0) << ")"; + + os << " " << "(0x" << hex << perms << "/0x" << (audit != AUDIT_UNSPECIFIED ? perms : 0) << ")"; os << ",\n"; return os; diff --git a/parser/mount.h b/parser/mount.h index 650628544..4eecee8eb 100644 --- a/parser/mount.h +++ b/parser/mount.h @@ -120,7 +120,7 @@ * remapped to a mount option*/ -class mnt_rule: public rule_t { +class mnt_rule: public perms_rule_t { int gen_policy_remount(Profile &prof, int &count, unsigned int flags, unsigned int opt_flags); int gen_policy_bind_mount(Profile &prof, int &count, unsigned int flags, @@ -143,9 +143,6 @@ public: std::vector flagsv, opt_flagsv; - perms_t perms; - audit_t audit; - int deny; mnt_rule(struct cond_entry *src_conds, char *device_p, struct cond_entry *dst_conds unused, char *mnt_point_p, @@ -159,6 +156,13 @@ public: free(trans); } + virtual bool valid_prefix(prefixes &p, const char *&error) { + if (p.owner) { + error = "owner prefix not allowed on mount rules"; + return false; + } + return true; + }; virtual ostream &dump(ostream &os); virtual int expand_variables(void); virtual int gen_policy_re(Profile &prof); diff --git a/parser/mqueue.cc b/parser/mqueue.cc index 5b9da33d8..47273580f 100644 --- a/parser/mqueue.cc +++ b/parser/mqueue.cc @@ -87,7 +87,7 @@ void mqueue_rule::move_conditionals(struct cond_entry *conds) } mqueue_rule::mqueue_rule(perms_t perms_p, struct cond_entry *conds, char *qname_p): - qtype(mqueue_unspecified), qname(qname_p), label(NULL), audit(AUDIT_UNSPECIFIED), deny(0) + qtype(mqueue_unspecified), qname(qname_p), label(NULL) { move_conditionals(conds); free_cond_list(conds); @@ -115,10 +115,7 @@ mqueue_rule::mqueue_rule(perms_t perms_p, struct cond_entry *conds, char *qname_ ostream &mqueue_rule::dump(ostream &os) { - if (audit == AUDIT_FORCE) - os << "audit "; - if (deny) - os << "deny "; + prefix_rule_t::dump(os); os << "mqueue "; diff --git a/parser/mqueue.h b/parser/mqueue.h index b7d827687..e9f0a4721 100644 --- a/parser/mqueue.h +++ b/parser/mqueue.h @@ -81,15 +81,12 @@ typedef enum mqueue_type { int parse_mqueue_perms(const char *str_perms, perms_t *perms, int fail); -class mqueue_rule: public rule_t { +class mqueue_rule: public perms_rule_t { void move_conditionals(struct cond_entry *conds); public: mqueue_type qtype; char *qname; char *label; - perms_t perms; - audit_t audit; - int deny; mqueue_rule(perms_t perms, struct cond_entry *conds, char *qname = NULL); virtual ~mqueue_rule() @@ -98,6 +95,14 @@ public: free(label); }; + virtual bool valid_prefix(prefixes &p, const char *&error) { + // not yet, but soon + if (p.owner) { + error = _("owner prefix not allowed on mqueue rules"); + return false; + } + return true; + }; virtual ostream &dump(ostream &os); virtual int expand_variables(void); virtual int gen_policy_re(Profile &prof); diff --git a/parser/parser.h b/parser/parser.h index 07ed75b73..a638d9a93 100644 --- a/parser/parser.h +++ b/parser/parser.h @@ -36,17 +36,14 @@ #include "immunix.h" #include "libapparmor_re/apparmor_re.h" #include "libapparmor_re/aare_rules.h" +#include "rule.h" #include using namespace std; #include -class Profile; -class rule_t; -typedef uint32_t perms_t; -typedef enum { AUDIT_UNSPECIFIED, AUDIT_FORCE, AUDIT_QUIET } audit_t; #define MODULE_NAME "apparmor" @@ -91,11 +88,6 @@ extern dfaflags_t werrflags; typedef enum pattern_t pattern_t; -struct prefixes { - audit_t audit; - int deny; - int owner; -}; struct cod_pattern { char *regex; // posix regex diff --git a/parser/parser_yacc.y b/parser/parser_yacc.y index b4101f090..7b71c8845 100644 --- a/parser/parser_yacc.y +++ b/parser/parser_yacc.y @@ -794,97 +794,54 @@ rules: rules opt_prefix network_rule rules: rules opt_prefix mnt_rule { - if ($2.owner) - yyerror(_("owner prefix not allowed on mount rules")); - if ($2.deny && $2.audit == AUDIT_FORCE) { - $3->deny = 1; - } else if ($2.deny) { - $3->deny = 1; - $3->audit = AUDIT_FORCE; - } else if ($2.audit != AUDIT_UNSPECIFIED) { - $3->audit = $2.audit; - } - + const char *error; + if (!$3->add_prefix($2, error)) + yyerror(error); $1->rule_ents.push_back($3); $$ = $1; } rules: rules opt_prefix dbus_rule { - if ($2.owner) - yyerror(_("owner prefix not allowed on dbus rules")); - if ($2.deny && $2.audit == AUDIT_FORCE) { - $3->deny = 1; - } else if ($2.deny) { - $3->deny = 1; - $3->audit = AUDIT_FORCE; - } else if ($2.audit != AUDIT_UNSPECIFIED) { - $3->audit = $2.audit; - } + const char *error; + if (!$3->add_prefix($2, error)) + yyerror(error); $1->rule_ents.push_back($3); $$ = $1; } rules: rules opt_prefix signal_rule { - if ($2.owner) - yyerror(_("owner prefix not allowed on signal rules")); - if ($2.deny && $2.audit == AUDIT_FORCE) { - $3->deny = 1; - } else if ($2.deny) { - $3->deny = 1; - $3->audit = AUDIT_FORCE; - } else if ($2.audit != AUDIT_UNSPECIFIED) { - $3->audit = $2.audit; - } + const char *error; + if (!$3->add_prefix($2, error)) + yyerror(error); $1->rule_ents.push_back($3); $$ = $1; } rules: rules opt_prefix ptrace_rule { - if ($2.owner) - yyerror(_("owner prefix not allowed on ptrace rules")); - if ($2.deny && $2.audit == AUDIT_FORCE) { - $3->deny = 1; - } else if ($2.deny) { - $3->deny = 1; - $3->audit = AUDIT_FORCE; - } else if ($2.audit != AUDIT_UNSPECIFIED) { - $3->audit = $2.audit; - } + const char *error; + if (!$3->add_prefix($2, error)) + yyerror(error); $1->rule_ents.push_back($3); $$ = $1; } rules: rules opt_prefix unix_rule { - if ($2.owner) - yyerror(_("owner prefix not allowed on unix rules")); - if ($2.deny && $2.audit == AUDIT_FORCE) { - $3->deny = 1; - } else if ($2.deny) { - $3->deny = 1; - $3->audit = AUDIT_FORCE; - } else if ($2.audit != AUDIT_UNSPECIFIED) { - $3->audit = $2.audit; - } + const char *error; + if (!$3->add_prefix($2, error)) + yyerror(error); $1->rule_ents.push_back($3); $$ = $1; } rules: rules opt_prefix userns_rule { - if ($2.owner) - yyerror(_("owner prefix not allowed on userns rules")); - if ($2.deny && $2.audit) { - $3->deny = 1; - } else if ($2.deny) { - $3->deny = 1; - $3->audit = AUDIT_FORCE; - } else if ($2.audit == AUDIT_FORCE) { - $3->audit = AUDIT_FORCE; - } + const char *error; + if (!$3->add_prefix($2, error)) + yyerror(error); $1->rule_ents.push_back($3); $$ = $1; } @@ -930,16 +887,9 @@ rules: rules opt_prefix capability rules: rules opt_prefix mqueue_rule { - if ($2.owner) - yyerror(_("owner prefix not allowed on mqueue rules")); //is this true? - if ($2.deny && $2.audit) { - $3->deny = 1; - } else if ($2.deny) { - $3->deny = 1; - $3->audit = AUDIT_FORCE; - } else if ($2.audit == AUDIT_FORCE) { - $3->audit = AUDIT_FORCE; - } + const char *error; + if (!$3->add_prefix($2, error)) + yyerror(error); $1->rule_ents.push_back($3); $$ = $1; }; diff --git a/parser/ptrace.cc b/parser/ptrace.cc index fda719705..9459ab3c5 100644 --- a/parser/ptrace.cc +++ b/parser/ptrace.cc @@ -48,7 +48,7 @@ void ptrace_rule::move_conditionals(struct cond_entry *conds) } ptrace_rule::ptrace_rule(perms_t perms_p, struct cond_entry *conds): - peer_label(NULL), audit(AUDIT_UNSPECIFIED), deny(0) + peer_label(NULL) { if (perms_p) { if (perms_p & ~AA_VALID_PTRACE_PERMS) @@ -64,13 +64,11 @@ ptrace_rule::ptrace_rule(perms_t perms_p, struct cond_entry *conds): ostream &ptrace_rule::dump(ostream &os) { - if (audit == AUDIT_FORCE) - os << "audit "; - if (deny) - os << "deny "; + prefix_rule_t::dump(os); os << "ptrace"; + /* override default perm dump */ if (perms != AA_VALID_PTRACE_PERMS) { os << " ("; diff --git a/parser/ptrace.h b/parser/ptrace.h index 2f54b0fd5..dbe1eb308 100644 --- a/parser/ptrace.h +++ b/parser/ptrace.h @@ -29,13 +29,10 @@ int parse_ptrace_perms(const char *str_perms, perms_t *perms, int fail); -class ptrace_rule: public rule_t { +class ptrace_rule: public perms_rule_t { void move_conditionals(struct cond_entry *conds); public: char *peer_label; - perms_t perms; - audit_t audit; - int deny; ptrace_rule(perms_t perms, struct cond_entry *conds); virtual ~ptrace_rule() @@ -48,6 +45,14 @@ public: virtual int gen_policy_re(Profile &prof); virtual void post_process(Profile &prof unused) { }; + virtual bool valid_prefix(prefixes &p, const char *&error) { + if (p.owner) { + error = "owner prefix not allowed on ptrace rules"; + return false; + } + return true; + }; + protected: virtual void warn_once(const char *name) override; }; diff --git a/parser/rule.h b/parser/rule.h index 73e0175af..ad307c66f 100644 --- a/parser/rule.h +++ b/parser/rule.h @@ -23,6 +23,8 @@ #include "policydb.h" +using namespace std; + class Profile; #define RULE_NOT_SUPPORTED 0 @@ -51,5 +53,113 @@ std::ostream &operator<<(std::ostream &os, rule_t &rule); typedef std::list RuleList; +/* Not classes so they can be used in the bison front end */ +typedef uint32_t perms_t; +typedef enum { AUDIT_UNSPECIFIED, AUDIT_FORCE, AUDIT_QUIET } audit_t; + +/* NOTE: we can not have a constructor for class prefixes. This is + * because it will break bison, and we would need to transition to + * the C++ bison bindings. Instead get around this by using a + * special rule class that inherits prefixes and handles the + * contruction + */ +class prefixes { +public: + audit_t audit; + int deny; + int owner; + + ostream &dump(ostream &os) + { + bool output = true; + + switch (audit) { + case AUDIT_FORCE: + os << "audit"; + break; + case AUDIT_QUIET: + os << "quiet"; + break; + default: + output = false; + } + + if (deny) { + if (output) + os << " "; + + os << "deny"; + output = true; + } + + if (owner) { + if (output) + os << " "; + os << "owner"; + output = true; + } + + if (output) + os << " "; + + return os; + } +}; + +class prefix_rule_t: public rule_t, public prefixes { +public: + prefix_rule_t() + { + /* Must construct prefix here see note on prefixes */ + audit = AUDIT_UNSPECIFIED; + deny = 0; + owner = 0; + }; + + virtual bool valid_prefix(prefixes &p, const char *&error) = 0; + + virtual bool add_prefix(prefixes &p, const char *&error) { + if (!valid_prefix(p, error)) + return false; + if (p.audit != AUDIT_UNSPECIFIED && audit != p.audit) { + if (audit != AUDIT_UNSPECIFIED) { + error = "conflicting audit prefix"; + return false; + } + } + if (p.deny && p.audit == AUDIT_FORCE) { + deny = 1; + } else if (p.deny) { + deny = 1; + audit = AUDIT_FORCE; + } else if (p.audit != AUDIT_UNSPECIFIED) { + audit = p.audit; + } + owner = p.owner; + return true; + } + + virtual ostream &dump(ostream &os) { + prefixes::dump(os); + + return os; + } + +}; + +class perms_rule_t: public prefix_rule_t { +public: + perms_rule_t(): perms(0) { }; + + /* defaut perms, override/mask off if none default used */ + virtual ostream &dump(ostream &os) { + + return os; + } + + perms_t perms; + +}; + #endif /* __AA_RULE_H */ diff --git a/parser/signal.cc b/parser/signal.cc index 0799ff5d4..461309be5 100644 --- a/parser/signal.cc +++ b/parser/signal.cc @@ -174,7 +174,7 @@ void signal_rule::move_conditionals(struct cond_entry *conds) } signal_rule::signal_rule(perms_t perms_p, struct cond_entry *conds): - signals(), peer_label(NULL), audit(AUDIT_UNSPECIFIED), deny(0) + signals(), peer_label(NULL) { if (perms_p) { perms = perms_p; @@ -191,10 +191,7 @@ signal_rule::signal_rule(perms_t perms_p, struct cond_entry *conds): ostream &signal_rule::dump(ostream &os) { - if (audit == AUDIT_FORCE) - os << "audit "; - if (deny) - os << "deny "; + prefix_rule_t::dump(os); os << "signal"; diff --git a/parser/signal.h b/parser/signal.h index 8e3526d89..b6ca7c9ee 100644 --- a/parser/signal.h +++ b/parser/signal.h @@ -33,21 +33,25 @@ typedef set Signals; int parse_signal_perms(const char *str_perms, perms_t *perms, int fail); -class signal_rule: public rule_t { +class signal_rule: public perms_rule_t { void extract_sigs(struct value_list **list); void move_conditionals(struct cond_entry *conds); public: Signals signals; char *peer_label; - perms_t perms; - audit_t audit; - int deny; signal_rule(perms_t perms, struct cond_entry *conds); virtual ~signal_rule() { signals.clear(); free(peer_label); }; + virtual bool valid_prefix(prefixes &p, const char *&error) { + if (p.owner) { + error = "owner prefix not allowed on signal rules"; + return false; + } + return true; + }; virtual ostream &dump(ostream &os); virtual int expand_variables(void); diff --git a/parser/userns.cc b/parser/userns.cc index e8b3b5320..84f0fe31d 100644 --- a/parser/userns.cc +++ b/parser/userns.cc @@ -40,8 +40,7 @@ void userns_rule::move_conditionals(struct cond_entry *conds) } } -userns_rule::userns_rule(perms_t perms_p, struct cond_entry *conds): - audit(AUDIT_UNSPECIFIED), deny(0) +userns_rule::userns_rule(perms_t perms_p, struct cond_entry *conds) { if (perms_p) { if (perms_p & ~AA_VALID_USERNS_PERMS) @@ -59,10 +58,7 @@ userns_rule::userns_rule(perms_t perms_p, struct cond_entry *conds): ostream &userns_rule::dump(ostream &os) { - if (audit == AUDIT_FORCE) - os << "audit "; - if (deny) - os << "deny "; + prefix_rule_t::dump(os); os << "userns "; diff --git a/parser/userns.h b/parser/userns.h index d7776dc5b..fb60f3d3c 100644 --- a/parser/userns.h +++ b/parser/userns.h @@ -23,18 +23,22 @@ #define AA_USERNS_CREATE 8 #define AA_VALID_USERNS_PERMS (AA_USERNS_CREATE) -class userns_rule: public rule_t { +class userns_rule: public perms_rule_t { void move_conditionals(struct cond_entry *conds); public: - perms_t perms; - audit_t audit; - int deny; userns_rule(perms_t perms, struct cond_entry *conds); virtual ~userns_rule() { }; + virtual bool valid_prefix(prefixes &p, const char *&error) { + if (p.owner) { + error = _("owner prefix not allowed on userns rules"); + return false; + } + return true; + }; virtual ostream &dump(ostream &os); virtual int expand_variables(void); virtual int gen_policy_re(Profile &prof);