diff options
Diffstat (limited to '0001-apparmor-patch-to-provide-compatibility-with-v2-net-rules.patch')
-rw-r--r-- | 0001-apparmor-patch-to-provide-compatibility-with-v2-net-rules.patch | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/0001-apparmor-patch-to-provide-compatibility-with-v2-net-rules.patch b/0001-apparmor-patch-to-provide-compatibility-with-v2-net-rules.patch new file mode 100644 index 000000000000..d83c54d08d9e --- /dev/null +++ b/0001-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"; |