parser: refactor network to use rule class as its base.

There is one significant difference in the encoding of the network
rules. Before this change, when the parser was encoding a "network,"
rule, it would generate an entry for every family and every
type/protocol. After this patch the parser should generate an entry
for every family, but the type/protocol is changed to .. in the pcre
syntax. There should be no difference in behavior.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
This commit is contained in:
Georgia Garcia 2023-06-26 14:39:39 -03:00 committed by John Johansen
parent 11976c42e3
commit 820f1fb5f2
10 changed files with 315 additions and 301 deletions

View file

@ -99,7 +99,7 @@ EXTRA_CFLAGS+=-DPACKAGE=\"${NAME}\" -DLOCALEDIR=\"${LOCALEDIR}\"
SRCS = parser_common.c parser_include.c parser_interface.c parser_lex.c \ SRCS = parser_common.c parser_include.c parser_interface.c parser_lex.c \
parser_main.c parser_misc.c parser_merge.c parser_symtab.c \ parser_main.c parser_misc.c parser_merge.c parser_symtab.c \
parser_yacc.c parser_regex.c parser_variable.c parser_policy.c \ parser_yacc.c parser_regex.c parser_variable.c parser_policy.c \
parser_alias.c common_optarg.c lib.c network.c \ parser_alias.c common_optarg.c lib.c network.cc \
mount.cc dbus.cc profile.cc rule.cc signal.cc ptrace.cc \ mount.cc dbus.cc profile.cc rule.cc signal.cc ptrace.cc \
af_rule.cc af_unix.cc policy_cache.c default_features.c userns.cc \ af_rule.cc af_unix.cc policy_cache.c default_features.c userns.cc \
mqueue.cc io_uring.cc mqueue.cc io_uring.cc
@ -295,7 +295,7 @@ signal.o: signal.cc $(HDRS)
ptrace.o: ptrace.cc $(HDRS) ptrace.o: ptrace.cc $(HDRS)
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $< $(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
network.o: network.c $(HDRS) network.o: network.cc $(HDRS)
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $< $(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
default_features.o: default_features.c $(HDRS) default_features.o: default_features.c $(HDRS)

View file

@ -108,6 +108,9 @@ unix_rule::unix_rule(unsigned int type_p, audit_t audit_p, rule_mode_t rule_mode
perms = AA_VALID_NET_PERMS; perms = AA_VALID_NET_PERMS;
audit = audit_p; audit = audit_p;
rule_mode = rule_mode_p; rule_mode = rule_mode_p;
/* if this constructor is used, then there's already a
* downgraded network_rule in profile */
downgrade = false;
} }
unix_rule::unix_rule(perms_t perms_p, struct cond_entry *conds, unix_rule::unix_rule(perms_t perms_p, struct cond_entry *conds,
@ -190,7 +193,7 @@ static void writeu16(std::ostringstream &o, int v)
void unix_rule::downgrade_rule(Profile &prof) { void unix_rule::downgrade_rule(Profile &prof) {
perms_t mask = (perms_t) -1; perms_t mask = (perms_t) -1;
if (!prof.net.allow && !prof.alloc_net_table()) if (!prof.net.allow && !prof.net.alloc_net_table())
yyerror(_("Memory allocation error.")); yyerror(_("Memory allocation error."));
if (sock_type_n != -1) if (sock_type_n != -1)
mask = 1 << sock_type_n; mask = 1 << sock_type_n;
@ -198,6 +201,11 @@ void unix_rule::downgrade_rule(Profile &prof) {
prof.net.allow[AF_UNIX] |= mask; prof.net.allow[AF_UNIX] |= mask;
if (audit == AUDIT_FORCE) if (audit == AUDIT_FORCE)
prof.net.audit[AF_UNIX] |= mask; prof.net.audit[AF_UNIX] |= mask;
const char *error;
network_rule *netv8 = new network_rule(AF_UNIX, sock_type_n);
if(!netv8->add_prefix({audit, rule_mode, owner}, error))
yyerror(error);
prof.rule_ents.push_back(netv8);
} else { } else {
/* deny rules have to be dropped because the downgrade makes /* deny rules have to be dropped because the downgrade makes
* the rule less specific meaning it will make the profile more * the rule less specific meaning it will make the profile more
@ -317,7 +325,8 @@ int unix_rule::gen_policy_re(Profile &prof)
* older kernels and be enforced to the best of the old network * older kernels and be enforced to the best of the old network
* rules ability * rules ability
*/ */
downgrade_rule(prof); if (downgrade)
downgrade_rule(prof);
if (!features_supports_unix) { if (!features_supports_unix) {
if (features_supports_network || features_supports_networkv8) { if (features_supports_network || features_supports_networkv8) {
/* only warn if we are building against a kernel /* only warn if we are building against a kernel

View file

@ -36,6 +36,7 @@ class unix_rule: public af_rule {
public: public:
char *addr; char *addr;
char *peer_addr; char *peer_addr;
bool downgrade = true;
unix_rule(unsigned int type_p, audit_t audit_p, rule_mode_t rule_mode_p); unix_rule(unsigned int type_p, audit_t audit_p, rule_mode_t rule_mode_p);
unix_rule(perms_t perms, struct cond_entry *conds, unix_rule(perms_t perms, struct cond_entry *conds,

View file

@ -16,10 +16,6 @@
* Ltd. * Ltd.
*/ */
#include <stdlib.h>
#include <string.h>
#include <sys/apparmor.h>
#include <iomanip> #include <iomanip>
#include <string> #include <string>
#include <sstream> #include <sstream>
@ -28,9 +24,9 @@
#include "lib.h" #include "lib.h"
#include "parser.h" #include "parser.h"
#include "profile.h" #include "profile.h"
#include "parser_yacc.h"
#include "network.h" #include "network.h"
#define ALL_TYPES 0x43e
int parse_net_perms(const char *str_mode, perms_t *mode, int fail) int parse_net_perms(const char *str_mode, perms_t *mode, int fail)
{ {
@ -119,7 +115,7 @@ static struct network_tuple network_mappings[] = {
/* FIXME: af_names.h is missing AF_LLC, AF_TIPC */ /* FIXME: af_names.h is missing AF_LLC, AF_TIPC */
/* mapped types */ /* mapped types */
{"inet", AF_INET, "raw", SOCK_RAW, {"inet", AF_INET, "raw", SOCK_RAW,
"tcp", 1 << RAW_TCP}, "tcp", 1 << RAW_TCP},
{"inet", AF_INET, "raw", SOCK_RAW, {"inet", AF_INET, "raw", SOCK_RAW,
"udp", 1 << RAW_UDP}, "udp", 1 << RAW_UDP},
{"inet", AF_INET, "raw", SOCK_RAW, {"inet", AF_INET, "raw", SOCK_RAW,
@ -239,21 +235,21 @@ size_t get_af_max() {
return af_max; return af_max;
} }
struct aa_network_entry *new_network_ent(unsigned int family,
unsigned int type,
unsigned int protocol)
{
struct aa_network_entry *new_entry;
new_entry = (struct aa_network_entry *) calloc(1, sizeof(struct aa_network_entry));
if (new_entry) {
new_entry->family = family;
new_entry->type = type;
new_entry->protocol = protocol;
new_entry->next = NULL;
}
return new_entry;
}
const char *net_find_af_name(unsigned int af)
{
size_t i;
if (af < 0 || af > get_af_max())
return NULL;
for (i = 0; i < sizeof(network_mappings) / sizeof(*network_mappings); i++) {
if (network_mappings[i].family == af)
return network_mappings[i].family_name;
}
return NULL;
}
const struct network_tuple *net_find_mapping(const struct network_tuple *map, const struct network_tuple *net_find_mapping(const struct network_tuple *map,
const char *family, const char *family,
@ -302,95 +298,225 @@ const struct network_tuple *net_find_mapping(const struct network_tuple *map,
return NULL; return NULL;
} }
struct aa_network_entry *network_entry(const char *family, const char *type, void network_rule::set_netperm(unsigned int family, unsigned int type)
const char *protocol)
{ {
struct aa_network_entry *new_entry, *entry = NULL; if (type > SOCK_PACKET) {
const struct network_tuple *mapping = NULL; /* setting mask instead of a bit */
network_perms[family] |= type;
while ((mapping = net_find_mapping(mapping, family, type, protocol))) { } else
new_entry = new_network_ent(mapping->family, mapping->type, network_perms[family] |= 1 << type;
mapping->protocol);
if (!new_entry)
yyerror(_("Memory allocation error."));
new_entry->next = entry;
entry = new_entry;
}
return entry;
};
#define ALL_TYPES 0x43e
const char *net_find_af_name(unsigned int af)
{
size_t i;
if (af < 0 || af > get_af_max())
return NULL;
for (i = 0; i < sizeof(network_mappings) / sizeof(*network_mappings); i++) {
if (network_mappings[i].family == af)
return network_mappings[i].family_name;
}
return NULL;
} }
void __debug_network(unsigned int *array, const char *name) network_rule::network_rule(const char *family, const char *type,
const char *protocol):
perms_rule_t(AA_CLASS_NETV8)
{ {
if (!family && !type && !protocol) {
size_t family_index;
for (family_index = AF_UNSPEC; family_index < get_af_max(); family_index++) {
network_map[family_index].push_back({ family_index, 0xFFFFFFFF, 0xFFFFFFFF });
set_netperm(family_index, 0xFFFFFFFF);
}
} else {
const struct network_tuple *mapping = NULL;
while ((mapping = net_find_mapping(mapping, family, type, protocol))) {
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
set_netperm(mapping->family, mapping->type);
}
if (type == NULL && network_map.empty()) {
while ((mapping = net_find_mapping(mapping, type, family, protocol))) {
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
set_netperm(mapping->family, mapping->type);
}
}
if (network_map.empty())
yyerror(_("Invalid network entry."));
}
}
network_rule::network_rule(unsigned int family, unsigned int type):
perms_rule_t(AA_CLASS_NETV8)
{
network_map[family].push_back({ family, type, 0xFFFFFFFF });
set_netperm(family, type);
}
ostream &network_rule::dump(ostream &os)
{
class_rule_t::dump(os);
unsigned int count = sizeof(sock_types)/sizeof(sock_types[0]); unsigned int count = sizeof(sock_types)/sizeof(sock_types[0]);
unsigned int mask = ~((1 << count) -1); unsigned int mask = ~((1 << count) -1);
unsigned int i, j; unsigned int j;
int none = 1;
size_t af_max = get_af_max();
for (i = AF_UNSPEC; i < af_max; i++)
if (array[i]) {
none = 0;
break;
}
if (none)
return;
printf("%s: ", name);
/* This can only be set by an unqualified network rule */ /* This can only be set by an unqualified network rule */
if (array[AF_UNSPEC]) { if (network_map.find(AF_UNSPEC) != network_map.end()) {
printf("<all>\n"); os << ",\n";
return; return os;
} }
for (i = 0; i < af_max; i++) { for (const auto& perm : network_perms) {
if (array[i]) { unsigned int family = perm.first;
const char *fam = net_find_af_name(i); unsigned int type = perm.second;
if (fam)
printf("%s ", fam);
else
printf("#%u ", i);
/* All types/protocols */ const char *family_name = net_find_af_name(family);
if (array[i] == 0xffffffff || array[i] == ALL_TYPES) if (family_name)
continue; os << " " << family_name;
else
os << " #" << family;
printf("{ "); /* All types/protocols */
if (type == 0xffffffff || type == ALL_TYPES)
continue;
for (j = 0; j < count; j++) { printf(" {");
const char *type;
if (array[i] & (1 << j)) { for (j = 0; j < count; j++) {
type = sock_types[j].name; const char *type_name;
if (type) if (type & (1 << j)) {
printf("%s ", type); type_name = sock_types[j].name;
else if (type_name)
printf("#%u ", j); os << " " << type_name;
else
os << " #" << j;
}
}
if (type & mask)
os << " #" << std::hex << (type & mask);
printf(" }");
}
os << ",\n";
return os;
}
int network_rule::expand_variables(void)
{
return 0;
}
void network_rule::warn_once(const char *name)
{
rule_t::warn_once(name, "network rules not enforced");
}
bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mask) {
std::ostringstream buffer;
std::string buf;
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_NETV8;
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ((family & 0xff00) >> 8);
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (family & 0xff);
if (type_mask > 0xffff) {
buffer << "..";
} else {
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ((type_mask & 0xff00) >> 8);
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (type_mask & 0xff);
}
buf = buffer.str();
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(AA_VALID_NET_PERMS),
perms_rule_t::audit == AUDIT_FORCE ? map_perms(AA_VALID_NET_PERMS) : 0,
parseopts))
return false;
return true;
}
int network_rule::gen_policy_re(Profile &prof)
{
std::ostringstream buffer;
std::string buf;
if (!features_supports_networkv8) {
warn_once(prof.name);
return RULE_NOT_SUPPORTED;
}
for (const auto& perm : network_perms) {
unsigned int family = perm.first;
unsigned int type = perm.second;
if (type > 0xffff) {
if (!gen_net_rule(prof, family, type))
goto fail;
} else {
int t;
/* generate rules for types that are set */
for (t = 0; t < 16; t++) {
if (type & (1 << t)) {
if (!gen_net_rule(prof, family, t))
goto fail;
} }
} }
if (array[i] & mask) }
printf("#%x ", array[i] & mask);
printf("} "); }
return RULE_OK;
fail:
return RULE_ERROR;
}
/* initialize static members */
unsigned int *network_rule::allow = NULL;
unsigned int *network_rule::audit = NULL;
unsigned int *network_rule::deny = NULL;
unsigned int *network_rule::quiet = NULL;
bool network_rule::alloc_net_table()
{
if (allow)
return true;
allow = (unsigned int *) calloc(get_af_max(), sizeof(unsigned int));
audit = (unsigned int *) calloc(get_af_max(), sizeof(unsigned int));
deny = (unsigned int *) calloc(get_af_max(), sizeof(unsigned int));
quiet = (unsigned int *) calloc(get_af_max(), sizeof(unsigned int));
if (!allow || !audit || !deny || !quiet)
return false;
return true;
}
/* update is required because at the point of the creation of the
* network_rule object, we don't have owner, rule_mode, or audit
* set.
*/
void network_rule::update_compat_net(void)
{
if (!alloc_net_table())
yyerror(_("Memory allocation error."));
for (auto& nm: network_map) {
for (auto& entry : nm.second) {
if (entry.type > SOCK_PACKET) {
/* setting mask instead of a bit */
if (rule_mode == RULE_DENY) {
deny[entry.family] |= entry.type;
if (dedup_perms_rule_t::audit != AUDIT_FORCE)
quiet[entry.family] |= entry.type;
} else {
allow[entry.family] |= entry.type;
if (dedup_perms_rule_t::audit == AUDIT_FORCE)
audit[entry.family] |= entry.type;
}
} else {
if (rule_mode == RULE_DENY) {
deny[entry.family] |= 1 << entry.type;
if (dedup_perms_rule_t::audit != AUDIT_FORCE)
quiet[entry.family] |= 1 << entry.type;
} else {
allow[entry.family] |= 1 << entry.type;
if (dedup_perms_rule_t::audit == AUDIT_FORCE)
audit[entry.family] |= 1 << entry.type;
}
}
} }
} }
printf("\n");
} }

View file

@ -29,6 +29,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <unordered_map>
#include <vector>
#include "parser.h" #include "parser.h"
#include "rule.h" #include "rule.h"
@ -82,13 +84,10 @@ struct network_tuple {
unsigned int protocol; unsigned int protocol;
}; };
/* supported AF protocols */
struct aa_network_entry { struct aa_network_entry {
unsigned int family; long unsigned int family;
unsigned int type; unsigned int type;
unsigned int protocol; unsigned int protocol;
struct aa_network_entry *next;
}; };
static inline uint32_t map_perms(uint32_t mask) static inline uint32_t map_perms(uint32_t mask)
@ -99,45 +98,70 @@ static inline uint32_t map_perms(uint32_t mask)
((mask & (AA_NET_SETOPT | AA_NET_GETOPT)) >> 5); /* 5 + (AA_OTHER_SHIFT - 24) */ ((mask & (AA_NET_SETOPT | AA_NET_GETOPT)) >> 5); /* 5 + (AA_OTHER_SHIFT - 24) */
}; };
int parse_net_perms(const char *str_mode, perms_t *perms, int fail); int parse_net_perms(const char *str_mode, perms_t *perms, int fail);
extern struct aa_network_entry *new_network_ent(unsigned int family, size_t get_af_max();
unsigned int type,
unsigned int protocol);
extern struct aa_network_entry *network_entry(const char *family,
const char *type,
const char *protocol);
extern size_t get_af_max(void);
void __debug_network(unsigned int *array, const char *name);
struct network {
unsigned int *allow; /* array of type masks
* indexed by AF_FAMILY */
unsigned int *audit;
unsigned int *deny;
unsigned int *quiet;
network(void) { allow = audit = deny = quiet = NULL; }
void dump(void) {
if (allow)
__debug_network(allow, "Network");
if (audit)
__debug_network(audit, "Audit Net");
if (deny)
__debug_network(deny, "Deny Net");
if (quiet)
__debug_network(quiet, "Quiet Net");
}
};
int net_find_type_val(const char *type); int net_find_type_val(const char *type);
const char *net_find_type_name(int type); const char *net_find_type_name(int type);
const char *net_find_af_name(unsigned int af); const char *net_find_af_name(unsigned int af);
const struct network_tuple *net_find_mapping(const struct network_tuple *map,
const char *family, class network_rule: public perms_rule_t {
const char *type, public:
const char *protocol); std::unordered_map<unsigned int, std::vector<struct aa_network_entry>> network_map;
std::unordered_map<unsigned int, perms_t> network_perms;
/* empty constructor used only for the profile to access
* static elements to maintain compatibility with
* AA_CLASS_NET */
network_rule(): perms_rule_t(AA_CLASS_NETV8) { }
network_rule(const char *family, const char *type,
const char *protocol);
network_rule(unsigned int family, unsigned int type);
virtual ~network_rule()
{
if (allow) {
free(allow);
allow = NULL;
}
if (audit) {
free(audit);
audit = NULL;
}
if (deny) {
free(deny);
deny = NULL;
}
if (quiet) {
free(quiet);
quiet = NULL;
}
};
bool gen_net_rule(Profile &prof, u16 family, unsigned int type_mask);
void set_netperm(unsigned int family, unsigned int type);
void update_compat_net(void);
virtual bool valid_prefix(const prefixes &p, const char *&error) {
if (p.owner) {
error = _("owner prefix not allowed on network rules");
return false;
}
return true;
};
virtual ostream &dump(ostream &os);
virtual int expand_variables(void);
virtual int gen_policy_re(Profile &prof);
// TODO: implement rule dedup cmp member function
/* array of type masks indexed by AF_FAMILY */
/* allow, audit, deny and quiet are used for compatibility with AA_CLASS_NET */
static unsigned int *allow;
static unsigned int *audit;
static unsigned int *deny;
static unsigned int *quiet;
bool alloc_net_table(void);
protected:
virtual void warn_once(const char *name) override;
};
#endif /* __AA_NETWORK_H */ #endif /* __AA_NETWORK_H */

View file

@ -33,6 +33,7 @@
#include "parser.h" #include "parser.h"
#include "profile.h" #include "profile.h"
#include "parser_yacc.h" #include "parser_yacc.h"
#include "network.h"
/* #define DEBUG */ /* #define DEBUG */
#ifdef DEBUG #ifdef DEBUG

View file

@ -857,80 +857,6 @@ int post_process_policydb_ents(Profile *prof)
return TRUE; return TRUE;
} }
static bool gen_net_rule(Profile *prof, u16 family, unsigned int type_mask,
bool audit, bool deny) {
std::ostringstream buffer;
std::string buf;
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_NETV8;
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ((family & 0xff00) >> 8);
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (family & 0xff);
if (type_mask > 0xffff) {
buffer << "..";
} else {
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ((type_mask & 0xff00) >> 8);
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (type_mask & 0xff);
}
buf = buffer.str();
if (!prof->policy.rules->add_rule(buf.c_str(), deny, map_perms(AA_VALID_NET_PERMS),
audit ? map_perms(AA_VALID_NET_PERMS) : 0,
parseopts))
return false;
return true;
}
static bool gen_af_rules(Profile *prof, u16 family, unsigned int type_mask,
unsigned int audit_mask, bool deny)
{
if (type_mask > 0xffff && audit_mask > 0xffff) {
/* instead of generating multiple rules wild card type */
return gen_net_rule(prof, family, type_mask, audit_mask, deny);
} else {
int t;
/* generate rules for types that are set */
for (t = 0; t < 16; t++) {
if (type_mask & (1 << t)) {
if (!gen_net_rule(prof, family, t,
audit_mask & (1 << t),
deny))
return false;
}
}
}
return true;
}
bool post_process_policydb_net(Profile *prof)
{
u16 af;
/* no network rules defined so we don't have generate them */
if (!prof->net.allow)
return true;
/* generate rules if the af has something set */
for (af = AF_UNSPEC; af < get_af_max(); af++) {
if (prof->net.allow[af] ||
prof->net.deny[af] ||
prof->net.audit[af] ||
prof->net.quiet[af]) {
if (!gen_af_rules(prof, af, prof->net.allow[af],
prof->net.audit[af],
false))
return false;
if (!gen_af_rules(prof, af, prof->net.deny[af],
prof->net.quiet[af],
true))
return false;
}
}
return true;
}
#define MAKE_STR(X) #X #define MAKE_STR(X) #X
#define CLASS_STR(X) "\\d" MAKE_STR(X) #define CLASS_STR(X) "\\d" MAKE_STR(X)
#define MAKE_SUB_STR(X) "\\000" MAKE_STR(X) #define MAKE_SUB_STR(X) "\\000" MAKE_STR(X)
@ -959,9 +885,6 @@ int process_profile_policydb(Profile *prof)
if (!post_process_policydb_ents(prof)) if (!post_process_policydb_ents(prof))
goto out; goto out;
/* TODO: move to network class */
if (features_supports_networkv8 && !post_process_policydb_net(prof))
goto out;
/* insert entries to show indicate what compiler/policy expects /* insert entries to show indicate what compiler/policy expects
* to be supported * to be supported

View file

@ -187,13 +187,14 @@ bool check_x_qualifier(struct cod_entry *entry, const char *&errror);
#include "userns.h" #include "userns.h"
#include "mqueue.h" #include "mqueue.h"
#include "io_uring.h" #include "io_uring.h"
#include "network.h"
} }
%union { %union {
char *id; char *id;
char *flag_id; char *flag_id;
char *mode; char *mode;
struct aa_network_entry *network_entry; network_rule *network_entry;
Profile *prof; Profile *prof;
struct cod_net_entry *net_entry; struct cod_net_entry *net_entry;
struct cod_entry *user_entry; struct cod_entry *user_entry;
@ -693,51 +694,23 @@ rules: rules opt_prefix block
rules: rules opt_prefix network_rule rules: rules opt_prefix network_rule
{ {
struct aa_network_entry *entry, *tmp; const char *error;
if (!$3->add_prefix($2, error))
yyerror(error);
/* class members need to be updated after prefix is added */
$3->update_compat_net();
PDEBUG("Matched: network rule\n"); auto nm_af_unix = $3->network_map.find(AF_UNIX);
if ($2.owner) if (nm_af_unix != $3->network_map.end()) {
yyerror(_("owner prefix not allowed")); for (auto& entry : nm_af_unix->second) {
if (!$3) unix_rule *rule = new unix_rule(entry.type,
yyerror(_("Assert: `network_rule' return invalid protocol.")); $2.audit, $2.rule_mode);
if (!$1->alloc_net_table())
yyerror(_("Memory allocation error."));
list_for_each_safe($3, entry, tmp) {
/* map to extended mediation, let rule backend do
* downgrade if needed
*/
if (entry->family == AF_UNIX) {
unix_rule *rule = new unix_rule(entry->type, $2.audit, $2.rule_mode);
if (!rule) if (!rule)
yyerror(_("Memory allocation error.")); yyerror(_("Memory allocation error."));
$1->rule_ents.push_back(rule); $1->rule_ents.push_back(rule);
} }
if (entry->type > SOCK_PACKET) {
/* setting mask instead of a bit */
if ($2.rule_mode == RULE_DENY) {
$1->net.deny[entry->family] |= entry->type;
if ($2.audit != AUDIT_FORCE)
$1->net.quiet[entry->family] |= entry->type;
} else {
$1->net.allow[entry->family] |= entry->type;
if ($2.audit == AUDIT_FORCE)
$1->net.audit[entry->family] |= entry->type;
}
} else {
if ($2.rule_mode == RULE_DENY) {
$1->net.deny[entry->family] |= 1 << entry->type;
if ($2.audit != AUDIT_FORCE)
$1->net.quiet[entry->family] |= 1 << entry->type;
} else {
$1->net.allow[entry->family] |= 1 << entry->type;
if ($2.audit == AUDIT_FORCE)
$1->net.audit[entry->family] |= 1 << entry->type;
}
}
free(entry);
} }
$1->rule_ents.push_back($3);
$$ = $1; $$ = $1;
} }
@ -1109,38 +1082,20 @@ link_rule: TOK_LINK opt_subset_flag id_or_var TOK_ARROW id_or_var TOK_END_OF_RUL
network_rule: TOK_NETWORK TOK_END_OF_RULE network_rule: TOK_NETWORK TOK_END_OF_RULE
{ {
size_t family; network_rule *entry = new network_rule(NULL, NULL, NULL);
struct aa_network_entry *new_entry, *entry = NULL;
for (family = AF_UNSPEC; family < get_af_max(); family++) {
new_entry = new_network_ent(family, 0xffffffff,
0xffffffff);
if (!new_entry)
yyerror(_("Memory allocation error."));
new_entry->next = entry;
entry = new_entry;
}
$$ = entry; $$ = entry;
} }
network_rule: TOK_NETWORK TOK_ID TOK_END_OF_RULE network_rule: TOK_NETWORK TOK_ID TOK_END_OF_RULE
{ {
struct aa_network_entry *entry; network_rule *entry = new network_rule($2, NULL, NULL);
entry = network_entry($2, NULL, NULL);
if (!entry)
/* test for short circuiting of family */
entry = network_entry(NULL, $2, NULL);
if (!entry)
yyerror(_("Invalid network entry."));
free($2); free($2);
$$ = entry; $$ = entry;
} }
network_rule: TOK_NETWORK TOK_ID TOK_ID TOK_END_OF_RULE network_rule: TOK_NETWORK TOK_ID TOK_ID TOK_END_OF_RULE
{ {
struct aa_network_entry *entry; network_rule *entry = new network_rule($2, $3, NULL);
entry = network_entry($2, $3, NULL);
if (!entry)
yyerror(_("Invalid network entry."));
free($2); free($2);
free($3); free($3);
$$ = entry; $$ = entry;

View file

@ -72,20 +72,6 @@ void ProfileList::dump_profile_names(bool children)
} }
} }
bool Profile::alloc_net_table()
{
if (net.allow)
return true;
net.allow = (unsigned int *) calloc(get_af_max(), sizeof(unsigned int));
net.audit = (unsigned int *) calloc(get_af_max(), sizeof(unsigned int));
net.deny = (unsigned int *) calloc(get_af_max(), sizeof(unsigned int));
net.quiet = (unsigned int *) calloc(get_af_max(), sizeof(unsigned int));
if (!net.allow || !net.audit || !net.deny || !net.quiet)
return false;
return true;
}
Profile::~Profile() Profile::~Profile()
{ {
hat_table.clear(); hat_table.clear();
@ -115,14 +101,6 @@ Profile::~Profile()
for (int i = (AA_EXEC_LOCAL >> 10) + 1; i < AA_EXEC_COUNT; i++) for (int i = (AA_EXEC_LOCAL >> 10) + 1; i < AA_EXEC_COUNT; i++)
if (exec_table[i]) if (exec_table[i])
free(exec_table[i]); free(exec_table[i]);
if (net.allow)
free(net.allow);
if (net.audit)
free(net.audit);
if (net.deny)
free(net.deny);
if (net.quiet)
free(net.quiet);
} }
static bool comp (rule_t *lhs, rule_t *rhs) static bool comp (rule_t *lhs, rule_t *rhs)

View file

@ -311,7 +311,7 @@ public:
flagvals flags; flagvals flags;
struct capabilities caps; struct capabilities caps;
struct network net; network_rule net;
struct aa_rlimits rlimits; struct aa_rlimits rlimits;
@ -384,7 +384,6 @@ public:
flags.dump(cerr); flags.dump(cerr);
caps.dump(); caps.dump();
net.dump();
if (entries) if (entries)
debug_cod_entries(entries); debug_cod_entries(entries);
@ -397,8 +396,6 @@ public:
hat_table.dump(); hat_table.dump();
} }
bool alloc_net_table();
std::string hname(void) std::string hname(void)
{ {
if (!parent) if (!parent)