2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 01:57:43 +00:00

parser: make base classes for rules using prefixes and perms and use them

Cleanup the parse code by making shared prefix and perms classes for
rules and convert rules to use them.

Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
John Johansen 2021-09-04 03:28:18 -07:00
parent fdf5b062a9
commit d371458533
18 changed files with 209 additions and 150 deletions

View File

@ -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()) {

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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<unsigned int> 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);

View File

@ -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 ";

View File

@ -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);

View File

@ -36,17 +36,14 @@
#include "immunix.h"
#include "libapparmor_re/apparmor_re.h"
#include "libapparmor_re/aare_rules.h"
#include "rule.h"
#include <string>
using namespace std;
#include <set>
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

View File

@ -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;
};

View File

@ -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 << " (";

View File

@ -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;
};

View File

@ -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<rule_t *> 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 */

View File

@ -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";

View File

@ -33,21 +33,25 @@ typedef set<int> 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);

View File

@ -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 ";

View File

@ -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);