parser: initial steps into encoding protocol properly

Before the inet patches, protocol was not handled, so the information
was ignored. This patch introduces the ability to start mediating
protocol.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
This commit is contained in:
Georgia Garcia 2024-03-14 17:06:12 -03:00
parent 25f21a0758
commit 989501428e
2 changed files with 52 additions and 28 deletions

View file

@ -252,6 +252,19 @@ const char *net_find_af_name(unsigned int af)
return NULL; return NULL;
} }
const char *net_find_protocol_name(unsigned int protocol)
{
size_t i;
for (i = 0; i < sizeof(network_mappings) / sizeof(*network_mappings); i++) {
if (network_mappings[i].protocol == protocol) {
return network_mappings[i].protocol_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,
const char *type, const char *type,
@ -374,13 +387,14 @@ void network_rule::move_conditionals(struct cond_entry *conds, ip_conds &ip_cond
} }
} }
void network_rule::set_netperm(unsigned int family, unsigned int type) void network_rule::set_netperm(unsigned int family, unsigned int type, unsigned int protocol)
{ {
if (type > SOCK_PACKET) { if (type > SOCK_PACKET) {
/* setting mask instead of a bit */ /* setting mask instead of a bit */
network_perms[family] |= type; network_perms[family].first |= type;
} else } else
network_perms[family] |= 1 << type; network_perms[family].first |= 1 << type;
network_perms[family].second |= protocol;
} }
network_rule::network_rule(perms_t perms_p, struct cond_entry *conds, network_rule::network_rule(perms_t perms_p, struct cond_entry *conds,
@ -390,7 +404,7 @@ network_rule::network_rule(perms_t perms_p, struct cond_entry *conds,
size_t family_index; size_t family_index;
for (family_index = AF_UNSPEC; family_index < get_af_max(); family_index++) { for (family_index = AF_UNSPEC; family_index < get_af_max(); family_index++) {
network_map[family_index].push_back({ family_index, 0xFFFFFFFF, 0xFFFFFFFF }); network_map[family_index].push_back({ family_index, 0xFFFFFFFF, 0xFFFFFFFF });
set_netperm(family_index, 0xFFFFFFFF); set_netperm(family_index, 0xFFFFFFFF, 0xFFFFFFFF);
} }
move_conditionals(conds, local); move_conditionals(conds, local);
@ -417,13 +431,13 @@ network_rule::network_rule(perms_t perms_p, const char *family, const char *type
const struct network_tuple *mapping = NULL; const struct network_tuple *mapping = NULL;
while ((mapping = net_find_mapping(mapping, family, type, protocol))) { while ((mapping = net_find_mapping(mapping, family, type, protocol))) {
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol }); network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
set_netperm(mapping->family, mapping->type); set_netperm(mapping->family, mapping->type, mapping->protocol);
} }
if (type == NULL && network_map.empty()) { if (type == NULL && network_map.empty()) {
while ((mapping = net_find_mapping(mapping, type, family, protocol))) { while ((mapping = net_find_mapping(mapping, type, family, protocol))) {
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol }); network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
set_netperm(mapping->family, mapping->type); set_netperm(mapping->family, mapping->type, mapping->protocol);
} }
} }
@ -450,7 +464,7 @@ network_rule::network_rule(perms_t perms_p, unsigned int family, unsigned int ty
dedup_perms_rule_t(AA_CLASS_NETV8) dedup_perms_rule_t(AA_CLASS_NETV8)
{ {
network_map[family].push_back({ family, type, 0xFFFFFFFF }); network_map[family].push_back({ family, type, 0xFFFFFFFF });
set_netperm(family, type); set_netperm(family, type, 0xFFFFFFFF);
if (perms_p) { if (perms_p) {
perms = perms_p; perms = perms_p;
@ -479,7 +493,8 @@ ostream &network_rule::dump(ostream &os)
for (const auto& perm : network_perms) { for (const auto& perm : network_perms) {
unsigned int family = perm.first; unsigned int family = perm.first;
unsigned int type = perm.second; unsigned int type = perm.second.first;
unsigned int protocol = perm.second.second;
const char *family_name = net_find_af_name(family); const char *family_name = net_find_af_name(family);
if (family_name) if (family_name)
@ -507,6 +522,12 @@ ostream &network_rule::dump(ostream &os)
os << " #" << std::hex << (type & mask); os << " #" << std::hex << (type & mask);
printf(" }"); printf(" }");
const char *protocol_name = net_find_protocol_name(protocol);
if (protocol_name)
os << " " << protocol_name;
else
os << " #" << protocol;
} }
os << ",\n"; os << ",\n";
@ -559,16 +580,6 @@ std::string gen_port_cond(uint16_t port)
void network_rule::gen_ip_conds(std::ostringstream &oss, ip_conds entry, bool is_peer, bool is_cmd) void network_rule::gen_ip_conds(std::ostringstream &oss, ip_conds entry, bool is_peer, bool is_cmd)
{ {
/* encode protocol */
if (!is_cmd) {
if (entry.is_ip) {
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ((entry.ip.family & 0xff00) >> 8);
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (entry.ip.family & 0xff);
} else {
oss << "..";
}
}
if (entry.is_port) { if (entry.is_port) {
/* encode port type (privileged - 1, remote - 2, unprivileged - 0) */ /* encode port type (privileged - 1, remote - 2, unprivileged - 0) */
if (!is_peer && perms & AA_NET_BIND && entry.port < IPPORT_RESERVED) if (!is_peer && perms & AA_NET_BIND && entry.port < IPPORT_RESERVED)
@ -598,7 +609,7 @@ void network_rule::gen_ip_conds(std::ostringstream &oss, ip_conds entry, bool is
oss << "\\x00"; /* null transition */ oss << "\\x00"; /* null transition */
} }
bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mask) { bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mask, unsigned int protocol) {
std::ostringstream buffer; std::ostringstream buffer;
std::string buf; std::string buf;
@ -621,6 +632,15 @@ bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mas
return true; return true;
} }
/* encode protocol */
if (protocol > 0xffff) {
buffer << "..";
} else {
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ((protocol & 0xff00) >> 8);
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (protocol & 0xff);
}
if (perms & AA_PEER_NET_PERMS) { if (perms & AA_PEER_NET_PERMS) {
gen_ip_conds(buffer, peer, true, false); gen_ip_conds(buffer, peer, true, false);
@ -679,17 +699,18 @@ int network_rule::gen_policy_re(Profile &prof)
for (const auto& perm : network_perms) { for (const auto& perm : network_perms) {
unsigned int family = perm.first; unsigned int family = perm.first;
unsigned int type = perm.second; unsigned int type = perm.second.first;
unsigned int protocol = perm.second.second;
if (type > 0xffff) { if (type > 0xffff) {
if (!gen_net_rule(prof, family, type)) if (!gen_net_rule(prof, family, type, protocol))
goto fail; goto fail;
} else { } else {
int t; int t;
/* generate rules for types that are set */ /* generate rules for types that are set */
for (t = 0; t < 16; t++) { for (t = 0; t < 16; t++) {
if (type & (1 << t)) { if (type & (1 << t)) {
if (!gen_net_rule(prof, family, t)) if (!gen_net_rule(prof, family, t, protocol))
goto fail; goto fail;
} }
} }
@ -760,13 +781,16 @@ void network_rule::update_compat_net(void)
} }
} }
static int cmp_network_map(std::unordered_map<unsigned int, perms_t> lhs, static int cmp_network_map(std::unordered_map<unsigned int, std::pair<unsigned int, unsigned int>> lhs,
std::unordered_map<unsigned int, perms_t> rhs) std::unordered_map<unsigned int, std::pair<unsigned int, unsigned int>> rhs)
{ {
int res; int res;
size_t family_index; size_t family_index;
for (family_index = AF_UNSPEC; family_index < get_af_max(); family_index++) { for (family_index = AF_UNSPEC; family_index < get_af_max(); family_index++) {
res = lhs[family_index] - rhs[family_index]; res = lhs[family_index].first - rhs[family_index].first;
if (res)
return res;
res = lhs[family_index].second - rhs[family_index].second;
if (res) if (res)
return res; return res;
} }

View file

@ -139,7 +139,7 @@ class network_rule: public dedup_perms_rule_t {
void move_conditionals(struct cond_entry *conds, ip_conds &ip_cond); void move_conditionals(struct cond_entry *conds, ip_conds &ip_cond);
public: public:
std::unordered_map<unsigned int, std::vector<struct aa_network_entry>> network_map; std::unordered_map<unsigned int, std::vector<struct aa_network_entry>> network_map;
std::unordered_map<unsigned int, perms_t> network_perms; std::unordered_map<unsigned int, std::pair<unsigned int, unsigned int>> network_perms;
ip_conds peer; ip_conds peer;
ip_conds local; ip_conds local;
@ -179,8 +179,8 @@ public:
}; };
void gen_ip_conds(std::ostringstream &oss, ip_conds entry, bool is_peer, bool is_cmd); void gen_ip_conds(std::ostringstream &oss, ip_conds entry, bool is_peer, bool is_cmd);
bool gen_net_rule(Profile &prof, u16 family, unsigned int type_mask); bool gen_net_rule(Profile &prof, u16 family, unsigned int type_mask, unsigned int protocol);
void set_netperm(unsigned int family, unsigned int type); void set_netperm(unsigned int family, unsigned int type, unsigned int protocol);
void update_compat_net(void); void update_compat_net(void);
bool parse_address(ip_conds &entry); bool parse_address(ip_conds &entry);
bool parse_port(ip_conds &entry); bool parse_port(ip_conds &entry);