2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 14:25:52 +00:00

parser: add support for kernel 4.17 v8 networking

Make it so the parser can properly support network socket mediation
in the upstream kernel,

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/521
Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
John Johansen
2018-07-24 04:40:25 -07:00
parent 82cfc9ccc5
commit e92478a9c5
8 changed files with 104 additions and 13 deletions

View File

@@ -196,17 +196,11 @@ void unix_rule::downgrade_rule(Profile &prof) {
}
}
static uint32_t map_perms(uint32_t mask)
{
return (mask & 0x7f) |
((mask & (AA_NET_GETATTR | AA_NET_SETATTR)) << (AA_OTHER_SHIFT - 8)) |
((mask & (AA_NET_ACCEPT | AA_NET_BIND | AA_NET_LISTEN)) >> 4) | /* 2 + (AA_OTHER_SHIFT - 20) */
((mask & (AA_NET_SETOPT | AA_NET_GETOPT)) >> 5); /* 5 + (AA_OTHER_SHIFT - 24) */
}
void unix_rule::write_to_prot(std::ostringstream &buffer)
{
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_NET;
int c = features_supports_networkv8 ? AA_CLASS_NETV8 : AA_CLASS_NET;
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << c;
writeu16(buffer, AF_UNIX);
if (sock_type)
writeu16(buffer, sock_type_n);
@@ -306,7 +300,7 @@ int unix_rule::gen_policy_re(Profile &prof)
*/
downgrade_rule(prof);
if (!features_supports_unix) {
if (features_supports_network) {
if (features_supports_network || features_supports_networkv8) {
/* only warn if we are building against a kernel
* that requires downgrading */
if (warnflags & WARN_RULE_DOWNGRADED)

View File

@@ -91,6 +91,15 @@ struct aa_network_entry {
struct aa_network_entry *next;
};
static inline uint32_t map_perms(uint32_t mask)
{
return (mask & 0x7f) |
((mask & (AA_NET_GETATTR | AA_NET_SETATTR)) << (AA_OTHER_SHIFT - 8)) |
((mask & (AA_NET_ACCEPT | AA_NET_BIND | AA_NET_LISTEN)) >> 4) | /* 2 + (AA_OTHER_SHIFT - 20) */
((mask & (AA_NET_SETOPT | AA_NET_GETOPT)) >> 5); /* 5 + (AA_OTHER_SHIFT - 24) */
};
int parse_net_mode(const char *str_mode, int *mode, int fail);
extern struct aa_network_entry *new_network_ent(unsigned int family,
unsigned int type,

View File

@@ -330,6 +330,7 @@ extern int net_af_max_override;
extern int kernel_load;
extern int kernel_supports_setload;
extern int features_supports_network;
extern int features_supports_networkv8;
extern int kernel_supports_policydb;
extern int kernel_supports_diff_encode;
extern int features_supports_mount;

View File

@@ -67,6 +67,7 @@ int net_af_max_override = -1; /* use kernel to determine af_max */
int kernel_load = 1;
int kernel_supports_setload = 0; /* kernel supports atomic set loads */
int features_supports_network = 0; /* kernel supports network rules */
int features_supports_networkv8 = 0; /* kernel supports 4.17 network rules */
int features_supports_unix = 0; /* kernel supports unix socket rules */
int kernel_supports_policydb = 0; /* kernel supports new policydb */
int features_supports_mount = 0; /* kernel supports mount rules */

View File

@@ -459,7 +459,9 @@ void sd_serialize_profile(std::ostringstream &buf, Profile *profile,
sd_serialize_rlimits(buf, &profile->rlimits);
/* choice to support / downgrade needs to already have been made */
if (profile->net.allow && features_supports_network) {
if (features_supports_networkv8) {
/* nothing - encoded in policydb */
} else if (profile->net.allow && features_supports_network) {
size_t i;
sd_write_array(buf, "net_allowed_af", get_af_max());
for (i = 0; i < get_af_max(); i++) {
@@ -470,7 +472,7 @@ void sd_serialize_profile(std::ostringstream &buf, Profile *profile,
sd_write_uint16(buf, profile->net.deny[i] & profile->net.quiet[i]);
}
sd_write_arrayend(buf);
} else if (profile->net.allow && (warnflags & WARN_RULE_NOT_ENFORCED))
} else if (profile->net.allow)
pwarn(WARN_RULE_NOT_ENFORCED, _("profile %s network rules not enforced\n"), profile->name);
if (profile->policy.dfa) {

View File

@@ -881,6 +881,9 @@ void set_supported_features()
features_supports_network = features_intersect(kernel_features,
policy_features,
"network");
features_supports_networkv8 = features_intersect(kernel_features,
policy_features,
"network_v8");
features_supports_unix = features_intersect(kernel_features,
policy_features,
"network/af_unix");

View File

@@ -840,6 +840,80 @@ int post_process_policydb_ents(Profile *prof)
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,
dfaflags))
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 CLASS_STR(X) "\\d" MAKE_STR(X)
#define MAKE_SUB_STR(X) "\\000" MAKE_STR(X)
@@ -851,6 +925,7 @@ static const char *mediates_dbus = CLASS_STR(AA_CLASS_DBUS);
static const char *mediates_signal = CLASS_STR(AA_CLASS_SIGNAL);
static const char *mediates_ptrace = CLASS_STR(AA_CLASS_PTRACE);
static const char *mediates_extended_net = CLASS_STR(AA_CLASS_NET);
static const char *mediates_netv8 = CLASS_STR(AA_CLASS_NETV8);
static const char *mediates_net_unix = CLASS_SUB_STR(AA_CLASS_NET, AF_UNIX);
int process_profile_policydb(Profile *prof)
@@ -863,6 +938,9 @@ int process_profile_policydb(Profile *prof)
if (!post_process_policydb_ents(prof))
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
* to be supported
@@ -884,6 +962,9 @@ int process_profile_policydb(Profile *prof)
if (features_supports_ptrace &&
!prof->policy.rules->add_rule(mediates_ptrace, 0, AA_MAY_READ, 0, dfaflags))
goto out;
if (features_supports_networkv8 &&
!prof->policy.rules->add_rule(mediates_netv8, 0, AA_MAY_READ, 0, dfaflags))
goto out;
if (features_supports_unix &&
(!prof->policy.rules->add_rule(mediates_extended_net, 0, AA_MAY_READ, 0, dfaflags) ||
!prof->policy.rules->add_rule(mediates_net_unix, 0, AA_MAY_READ, 0, dfaflags)))

View File

@@ -32,7 +32,7 @@
#define AA_CLASS_NS_DOMAIN 8
#define AA_CLASS_PTRACE 9
#define AA_CLASS_SIGNAL 10
#define AA_CLASS_NETV8 14
#define AA_CLASS_LABEL 16
/* defined in libapparmor's apparmor.h #define AA_CLASS_DBUS 32 */