summarylogtreecommitdiffstats
path: root/0201-apparmor-patch-to-provide-compatibility-with-v2-net-rules.patch
diff options
context:
space:
mode:
Diffstat (limited to '0201-apparmor-patch-to-provide-compatibility-with-v2-net-rules.patch')
-rw-r--r--0201-apparmor-patch-to-provide-compatibility-with-v2-net-rules.patch222
1 files changed, 222 insertions, 0 deletions
diff --git a/0201-apparmor-patch-to-provide-compatibility-with-v2-net-rules.patch b/0201-apparmor-patch-to-provide-compatibility-with-v2-net-rules.patch
new file mode 100644
index 00000000000..d83c54d08d9
--- /dev/null
+++ b/0201-apparmor-patch-to-provide-compatibility-with-v2-net-rules.patch
@@ -0,0 +1,222 @@
+diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
+index 66d0b4245ef6fd11ed1c59fea64e570de6de4015..a4ed6163c03737d90e64e50b4bc4c24c031e7799 100644
+--- a/security/apparmor/apparmorfs.c
++++ b/security/apparmor/apparmorfs.c
+@@ -2265,6 +2265,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),
+diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
+index 6b7e6e13176ed4f11ff3cd43d17e004b977a5ed7..70de52565857845075dccd2fd5d27467b7d97329 100644
+--- a/security/apparmor/include/apparmor.h
++++ b/security/apparmor/include/apparmor.h
+@@ -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
+diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
+index 2431c011800dd012307630e1ce23ae3114479542..74768db9406656cb5ac080cd23d3a4faafd9e1ea 100644
+--- a/security/apparmor/include/net.h
++++ b/security/apparmor/include/net.h
+@@ -68,6 +68,16 @@ struct aa_sk_ctx {
+ 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) \
+ ({ \
+@@ -87,6 +97,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, struct common_audit_data *sa,
+diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
+index 1ce4e9bdac48191ac859a31919ec4eac12a29b98..6515a9174835c7d41279da92e6cafd72868ef181 100644
+--- a/security/apparmor/include/policy.h
++++ b/security/apparmor/include/policy.h
+@@ -108,6 +108,7 @@ struct aa_data {
+ * @policy: general match rules governing policy
+ * @file: The set of rules governing basic file access and domain transitions
+ * @caps: capabilities for the profile
++ * @net_compat: v2 compat network controls for the profile
+ * @rlimits: rlimits for the profile
+ *
+ * @dents: dentries for the profiles file entries in apparmorfs
+@@ -145,6 +146,7 @@ struct aa_profile {
+ struct aa_policydb policy;
+ struct aa_file_rules file;
+ struct aa_caps caps;
++ struct aa_net_compat *net_compat;
+
+ int xattr_count;
+ char **xattrs;
+diff --git a/security/apparmor/net.c b/security/apparmor/net.c
+index d8afc39f663ac6d5b54d2508bc6e3d2a0b78d42e..1d8f5ff53cd4c19b73532387accb034589ef1122 100644
+--- a/security/apparmor/net.c
++++ b/security/apparmor/net.c
+@@ -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",
+@@ -116,14 +121,26 @@ int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
+ if (profile_unconfined(profile))
+ return 0;
+ state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
+- if (!state)
++ if (state) {
++ if (!state)
++ return 0;
++ buffer[0] = cpu_to_be16(family);
++ buffer[1] = cpu_to_be16((u16) type);
++ state = aa_dfa_match_len(profile->policy.dfa, state,
++ (char *) &buffer, 4);
++ aa_compute_perms(profile->policy.dfa, state, &perms);
++ } 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;
++
++ } else {
+ return 0;
+-
+- buffer[0] = cpu_to_be16(family);
+- buffer[1] = cpu_to_be16((u16) type);
+- state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &buffer,
+- 4);
+- aa_compute_perms(profile->policy.dfa, state, &perms);
++ }
+ aa_apply_modes_to_perms(profile, &perms);
+
+ return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
+diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
+index ade333074c8ed50263999e231b9750842ef2ef6d..32f617df3d98120883643378549280c085a99be4 100644
+--- a/security/apparmor/policy.c
++++ b/security/apparmor/policy.c
+@@ -222,6 +222,7 @@ void aa_free_profile(struct aa_profile *profile)
+ aa_free_file_rules(&profile->file);
+ aa_free_cap_rules(&profile->caps);
+ aa_free_rlimit_rules(&profile->rlimits);
++ kzfree(profile->net_compat);
+
+ for (i = 0; i < profile->xattr_count; i++)
+ kzfree(profile->xattrs[i]);
+diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
+index 01957ce9252b52d436da3f057ec5c97687106431..8a93a3dc87e1bca791843eefe28511a2a3cd8200 100644
+--- a/security/apparmor/policy_unpack.c
++++ b/security/apparmor/policy_unpack.c
+@@ -33,7 +33,7 @@
+
+ #define v5 5 /* base version */
+ #define v6 6 /* per entry policydb mediation check */
+-#define v7 7
++#define v7 7 /* v2 compat networking */
+ #define v8 8 /* full network masking */
+
+ /*
+@@ -301,6 +301,19 @@ static bool unpack_u8(struct aa_ext *e, u8 *data, const char *name)
+ return 0;
+ }
+
++static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
++{
++ if (unpack_nameX(e, AA_U16, name)) {
++ if (!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;
++}
++
+ static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
+ {
+ if (unpack_nameX(e, AA_U32, name)) {
+@@ -642,7 +655,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";
+- size_t ns_len;
++ size_t size = 0, ns_len;
+ struct rhashtable_params params = { 0 };
+ char *key = NULL;
+ struct aa_data *data;
+@@ -785,6 +798,43 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
+ goto fail;
+ }
+
++ size = unpack_array(e, "net_allowed_af");
++ if (size || VERSION_LT(e->version, v8)) {
++ 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 && !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 (unpack_nameX(e, AA_STRUCT, "policydb")) {
+ /* generic policy dfa - optional and may be NULL */
+ info = "failed to unpack policydb";