From c1ca0286e88595a8691648c044499032e67ed76e Mon Sep 17 00:00:00 2001 From: Georgia Garcia Date: Wed, 10 Apr 2024 15:04:44 -0300 Subject: [PATCH] parser: inet conditionals should only generate rules for inet family When a family is specified in the network rules, we have to make sure the conditionals match the family. A netlink rule should not be able to specify ip and port for local and remote (peer) sockets, for example. When type or protocol is specified in network rules along with inet conditionals, we should only generate rules for the families that support those conditionals. Signed-off-by: Georgia Garcia --- parser/network.cc | 50 +++++++++++++++---- .../simple_tests/network/network_bad_83.sd | 8 +++ .../simple_tests/network/network_bad_84.sd | 8 +++ .../simple_tests/network/network_bad_85.sd | 8 +++ .../tst/simple_tests/network/network_ok_43.sd | 2 + 5 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 parser/tst/simple_tests/network/network_bad_83.sd create mode 100644 parser/tst/simple_tests/network/network_bad_84.sd create mode 100644 parser/tst/simple_tests/network/network_bad_85.sd diff --git a/parser/network.cc b/parser/network.cc index e90ae0033..268dc812d 100644 --- a/parser/network.cc +++ b/parser/network.cc @@ -405,17 +405,31 @@ network_rule::network_rule(perms_t perms_p, struct cond_entry *conds, struct cond_entry *peer_conds): dedup_perms_rule_t(AA_CLASS_NETV8), label(NULL) { - 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, 0xFFFFFFFF); - } + size_t family_index, i; move_conditionals(conds, local); move_conditionals(peer_conds, peer); free_cond_list(conds); free_cond_list(peer_conds); + if (has_local_conds() || has_peer_conds()) { + const char *family[] = { "inet", "inet6" }; + for (i = 0; i < sizeof(family)/sizeof(family[0]); i++) { + const struct network_tuple *mapping = NULL; + while ((mapping = net_find_mapping(mapping, family[i], NULL, NULL))) { + network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol }); + set_netperm(mapping->family, mapping->type, mapping->protocol); + } + } + } else { + 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, 0xFFFFFFFF); + } + } + + + if (perms_p) { perms = perms_p; if (perms & ~AA_VALID_NET_PERMS) @@ -433,13 +447,34 @@ network_rule::network_rule(perms_t perms_p, const char *family, const char *type dedup_perms_rule_t(AA_CLASS_NETV8), label(NULL) { const struct network_tuple *mapping = NULL; + + move_conditionals(conds, local); + move_conditionals(peer_conds, peer); + free_cond_list(conds); + free_cond_list(peer_conds); + while ((mapping = net_find_mapping(mapping, family, type, protocol))) { + /* if inet conds and family are specified, fail if + * family is not af_inet or af_inet6 + */ + if ((has_local_conds() || has_peer_conds()) && + mapping->family != AF_INET && mapping->family != AF_INET6) { + yyerror("network family does not support local or peer conditionals\n"); + } network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol }); set_netperm(mapping->family, mapping->type, mapping->protocol); } if (type == NULL && network_map.empty()) { while ((mapping = net_find_mapping(mapping, type, family, protocol))) { + /* if inet conds and type/protocol are + * specified, only add rules for af_inet and + * af_inet6 + */ + if ((has_local_conds() || has_peer_conds()) && + mapping->family != AF_INET && mapping->family != AF_INET6) + continue; + network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol }); set_netperm(mapping->family, mapping->type, mapping->protocol); } @@ -448,11 +483,6 @@ network_rule::network_rule(perms_t perms_p, const char *family, const char *type if (network_map.empty()) yyerror(_("Invalid network entry.")); - move_conditionals(conds, local); - move_conditionals(peer_conds, peer); - free_cond_list(conds); - free_cond_list(peer_conds); - if (perms_p) { perms = perms_p; if (perms & ~AA_VALID_NET_PERMS) diff --git a/parser/tst/simple_tests/network/network_bad_83.sd b/parser/tst/simple_tests/network/network_bad_83.sd new file mode 100644 index 000000000..dd2e1acd3 --- /dev/null +++ b/parser/tst/simple_tests/network/network_bad_83.sd @@ -0,0 +1,8 @@ +# +#=DESCRIPTION invalid family for inet conditionals +#=EXRESULT FAIL +# +/usr/bin/foo { + network unix ip=127.0.0.1 port=1234 peer=(ip=127.0.0.1 port=1234), + +} diff --git a/parser/tst/simple_tests/network/network_bad_84.sd b/parser/tst/simple_tests/network/network_bad_84.sd new file mode 100644 index 000000000..97ca0ce1a --- /dev/null +++ b/parser/tst/simple_tests/network/network_bad_84.sd @@ -0,0 +1,8 @@ +# +#=DESCRIPTION invalid family for inet conditionals +#=EXRESULT FAIL +# +/usr/bin/foo { + network netlink ip=127.0.0.1, + +} diff --git a/parser/tst/simple_tests/network/network_bad_85.sd b/parser/tst/simple_tests/network/network_bad_85.sd new file mode 100644 index 000000000..ccb326aff --- /dev/null +++ b/parser/tst/simple_tests/network/network_bad_85.sd @@ -0,0 +1,8 @@ +# +#=DESCRIPTION invalid family for inet conditionals +#=EXRESULT FAIL +# +/usr/bin/foo { + network packet peer=(port=1234), + +} diff --git a/parser/tst/simple_tests/network/network_ok_43.sd b/parser/tst/simple_tests/network/network_ok_43.sd index 78dba8c10..81d31a9be 100644 --- a/parser/tst/simple_tests/network/network_ok_43.sd +++ b/parser/tst/simple_tests/network/network_ok_43.sd @@ -5,5 +5,7 @@ /usr/bin/foo { network inet ip=10.0.2.1 peer=(ip=10.0.2.1), network inet tcp ip=192.168.2.254 peer=(ip=192.168.2.254), + network stream ip=192.168.2.254 peer=(ip=192.168.2.254), + network raw ip=10.0.2.1 peer=(ip=10.0.2.1), }