UBUNTU: SAUCE: apparmor4.0.0 [44/90]: patch to provide compatibility with v2.x net rules

BugLink: http://bugs.launchpad.net/bugs/2028253

The networking rules upstreamed in 4.17 have a deliberate abi break
with the older 2.x network rules.

This patch provides compatibility with the older rules for those
still using an apparmor 2.x userspace and still want network rules
to work on a newer kernel.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from https://gitlab.com/jjohansen/apparmor-kernel)
Signed-off-by: Andrea Righi <andrea.righi@canonical.com>
(cherry picked from commit fdb71a3190842ca72ca1a84db6b5d6fb6e73b1fc
https://git.launchpad.net/~apparmor-dev/ubuntu-kernel-next)
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
This commit is contained in:
John Johansen
2018-06-17 03:56:25 -07:00
committed by Paolo Pisati
parent 77811af4f0
commit f1e158f349
7 changed files with 91 additions and 8 deletions
+1
View File
@@ -2401,6 +2401,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
AA_SFS_DIR("domain", aa_sfs_entry_domain),
AA_SFS_DIR("file", aa_sfs_entry_file),
AA_SFS_DIR("network_v8", aa_sfs_entry_network),
AA_SFS_DIR("network", aa_sfs_entry_network_compat),
AA_SFS_DIR("mount", aa_sfs_entry_mount),
AA_SFS_DIR("namespaces", aa_sfs_entry_ns),
AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
+1 -1
View File
@@ -20,7 +20,7 @@
#define AA_CLASS_UNKNOWN 1
#define AA_CLASS_FILE 2
#define AA_CLASS_CAP 3
#define AA_CLASS_DEPRECATED 4
#define AA_CLASS_NET_COMPAT 4
#define AA_CLASS_RLIMITS 5
#define AA_CLASS_DOMAIN 6
#define AA_CLASS_MOUNT 7
+11
View File
@@ -77,6 +77,16 @@ static inline struct aa_sk_ctx *aa_sock(const struct sock *sk)
DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \
(SK)->sk_protocol)
/* struct aa_net - network confinement data
* @allow: basic network families permissions
* @audit: which network permissions to force audit
* @quiet: which network permissions to quiet rejects
*/
struct aa_net_compat {
u16 allow[AF_MAX];
u16 audit[AF_MAX];
u16 quiet[AF_MAX];
};
#define af_select(FAMILY, FN, DEF_FN) \
({ \
@@ -96,6 +106,7 @@ struct aa_secmark {
};
extern struct aa_sfs_entry aa_sfs_entry_network[];
extern struct aa_sfs_entry aa_sfs_entry_network_compat[];
void audit_net_cb(struct audit_buffer *ab, void *va);
int aa_profile_af_perm(struct aa_profile *profile,
+2
View File
@@ -204,6 +204,7 @@ struct aa_attachment {
* @disconnected: what to prepend if attach_disconnected is specified
* @attach: attachment rules for the profile
* @rules: rules to be enforced
* @net_compat: v2 compat network controls for the profile
*
* @dents: dentries for the profiles file entries in apparmorfs
* @dirname: name of the profile dir in apparmorfs
@@ -235,6 +236,7 @@ struct aa_profile {
struct aa_attachment attach;
struct list_head rules;
struct aa_net_compat *net_compat;
struct aa_loaddata *rawdata;
unsigned char *hash;
+22 -7
View File
@@ -24,6 +24,11 @@ struct aa_sfs_entry aa_sfs_entry_network[] = {
{ }
};
struct aa_sfs_entry aa_sfs_entry_network_compat[] = {
AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK),
{ }
};
static const char * const net_mask_names[] = {
"unknown",
"send",
@@ -122,14 +127,24 @@ int aa_profile_af_perm(struct aa_profile *profile,
if (profile_unconfined(profile))
return 0;
state = RULE_MEDIATES(rules, AA_CLASS_NET);
if (!state)
return 0;
if (state) {
buffer[0] = cpu_to_be16(family);
buffer[1] = cpu_to_be16((u16) type);
state = aa_dfa_match_len(rules->policy->dfa, state,
(char *) &buffer, 4);
perms = *aa_lookup_perms(rules->policy, state);
} else if (profile->net_compat) {
/* 2.x socket mediation compat */
perms.allow = (profile->net_compat->allow[family] & (1 << type)) ?
ALL_PERMS_MASK : 0;
perms.audit = (profile->net_compat->audit[family] & (1 << type)) ?
ALL_PERMS_MASK : 0;
perms.quiet = (profile->net_compat->quiet[family] & (1 << type)) ?
ALL_PERMS_MASK : 0;
buffer[0] = cpu_to_be16(family);
buffer[1] = cpu_to_be16((u16) type);
state = aa_dfa_match_len(rules->policy->dfa, state, (char *) &buffer,
4);
perms = *aa_lookup_perms(rules->policy, state);
} else {
return 0;
}
aa_apply_modes_to_perms(profile, &perms);
return aa_check_perms(profile, &perms, request, ad, audit_net_cb);
+1
View File
@@ -295,6 +295,7 @@ void aa_free_profile(struct aa_profile *profile)
kfree_sensitive(profile->disconnected);
free_attachment(&profile->attach);
kfree_sensitive(profile->net_compat);
/*
* at this point there are no tasks that can have a reference
+53
View File
@@ -270,6 +270,19 @@ fail:
return false;
}
VISIBLE_IF_KUNIT bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
{
if (aa_unpack_nameX(e, AA_U16, name)) {
if (!aa_inbounds(e, sizeof(u16)))
return 0;
if (data)
*data = le16_to_cpu(get_unaligned((__le16 *) e->pos));
e->pos += sizeof(u16);
return 1;
}
return 0;
}
VISIBLE_IF_KUNIT bool aa_unpack_u32(struct aa_ext *e, u32 *data, const char *name)
{
void *pos = e->pos;
@@ -812,6 +825,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
struct aa_profile *profile = NULL;
const char *tmpname, *tmpns = NULL, *name = NULL;
const char *info = "failed to unpack profile";
u16 size = 0;
size_t ns_len;
struct rhashtable_params params = { 0 };
char *key = NULL, *disconnected = NULL;
@@ -984,6 +998,45 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
goto fail;
}
if (aa_unpack_array(e, "net_allowed_af", &size) ||
VERSION_LT(e->version, v8)) {
u16 i;
profile->net_compat = kzalloc(sizeof(struct aa_net_compat),
GFP_KERNEL);
if (!profile->net_compat) {
info = "out of memory";
goto fail;
}
for (i = 0; i < size; i++) {
/* discard extraneous rules that this kernel will
* never request
*/
if (i >= AF_MAX) {
u16 tmp;
if (!unpack_u16(e, &tmp, NULL) ||
!unpack_u16(e, &tmp, NULL) ||
!unpack_u16(e, &tmp, NULL))
goto fail;
continue;
}
if (!unpack_u16(e, &profile->net_compat->allow[i], NULL))
goto fail;
if (!unpack_u16(e, &profile->net_compat->audit[i], NULL))
goto fail;
if (!unpack_u16(e, &profile->net_compat->quiet[i], NULL))
goto fail;
}
if (size && !aa_unpack_nameX(e, AA_ARRAYEND, NULL))
goto fail;
if (VERSION_LT(e->version, v7)) {
/* pre v7 policy always allowed these */
profile->net_compat->allow[AF_UNIX] = 0xffff;
profile->net_compat->allow[AF_NETLINK] = 0xffff;
}
}
if (aa_unpack_nameX(e, AA_STRUCT, "policydb")) {
/* generic policy dfa - optional and may be NULL */
info = "failed to unpack policydb";