From 769c9a47195d1110212c4a4b94428b282bd4232b Mon Sep 17 00:00:00 2001 From: ajs124 <git@ajs124.de> Date: Wed, 17 Feb 2021 01:15:53 +0100 Subject: [PATCH] 5.7: drop --- ...armor-add-use-fns-to-print-hash-stri.patch | 75 -- ...armor-patch-to-provide-compatibility.patch | 251 ---- ...NTU-SAUCE-apparmor-af_unix-mediation.patch | 1169 ----------------- ...armor-fix-use-after-free-in-sk_peer_.patch | 59 - 4 files changed, 1554 deletions(-) delete mode 100644 5.7/0001-UBUNTU-SAUCE-apparmor-add-use-fns-to-print-hash-stri.patch delete mode 100644 5.7/0002-UBUNTU-SAUCE-apparmor-patch-to-provide-compatibility.patch delete mode 100644 5.7/0003-UBUNTU-SAUCE-apparmor-af_unix-mediation.patch delete mode 100644 5.7/0004-UBUNTU-SAUCE-apparmor-fix-use-after-free-in-sk_peer_.patch diff --git a/5.7/0001-UBUNTU-SAUCE-apparmor-add-use-fns-to-print-hash-stri.patch b/5.7/0001-UBUNTU-SAUCE-apparmor-add-use-fns-to-print-hash-stri.patch deleted file mode 100644 index bd63caf..0000000 --- a/5.7/0001-UBUNTU-SAUCE-apparmor-add-use-fns-to-print-hash-stri.patch +++ /dev/null @@ -1,75 +0,0 @@ -From b1c569056cb1d56c56f2dbf8b55f01ca66b1f878 Mon Sep 17 00:00:00 2001 -From: John Johansen <john.johansen@canonical.com> -Date: Mon, 1 May 2017 18:20:25 -0700 -Subject: [PATCH 1/4] UBUNTU: SAUCE: apparmor: add/use fns to print hash string - hex value - -Signed-off-by: John Johansen <john.johansen@canonical.com> -Signed-off-by: Seth Forshee <seth.forshee@canonical.com> ---- - security/apparmor/crypto.c | 19 +++++++++++++++++++ - security/apparmor/include/crypto.h | 11 +++++++++++ - 2 files changed, 30 insertions(+) - -diff --git a/security/apparmor/crypto.c b/security/apparmor/crypto.c -index b498ed302461..82d56bd204b0 100644 ---- a/security/apparmor/crypto.c -+++ b/security/apparmor/crypto.c -@@ -25,6 +25,25 @@ unsigned int aa_hash_size(void) - return apparmor_hash_size; - } - -+void aa_snprint_hashstr(char *out, unsigned char *hash, unsigned int hsize) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < hsize; i++) -+ sprintf(out + i*2, "%.2x", hash[i]); -+ out[hsize*2] = 0; -+} -+ -+char *aa_asprint_hashstr(unsigned char *hash, unsigned int hsize, gfp_t gfp) -+{ -+ char *buffer = kmalloc(hsize*2 + 1, gfp); -+ if (!buffer) -+ return NULL; -+ aa_snprint_hashstr(buffer, hash, hsize); -+ -+ return buffer; -+} -+ - char *aa_calc_hash(void *data, size_t len) - { - SHASH_DESC_ON_STACK(desc, apparmor_tfm); -diff --git a/security/apparmor/include/crypto.h b/security/apparmor/include/crypto.h -index 636a04e20d91..ceee04f4b428 100644 ---- a/security/apparmor/include/crypto.h -+++ b/security/apparmor/include/crypto.h -@@ -14,6 +14,8 @@ - - #ifdef CONFIG_SECURITY_APPARMOR_HASH - unsigned int aa_hash_size(void); -+void aa_snprint_hashstr(char *out, unsigned char *hash, unsigned int hsize); -+char *aa_asprint_hashstr(unsigned char *hash, unsigned int hsize, gfp_t gfp); - char *aa_calc_hash(void *data, size_t len); - int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start, - size_t len); -@@ -32,6 +34,15 @@ static inline unsigned int aa_hash_size(void) - { - return 0; - } -+ -+void aa_snprint_hashstr(char *out, unsigned char *hash, unsigned int hsize) -+{ -+} -+ -+char *aa_asprint_hashstr(unsigned char *hash, unsigned int hsize, gfp_t gfp); -+{ -+ return NULL; -+} - #endif - - #endif /* __APPARMOR_CRYPTO_H */ --- -2.25.4 - diff --git a/5.7/0002-UBUNTU-SAUCE-apparmor-patch-to-provide-compatibility.patch b/5.7/0002-UBUNTU-SAUCE-apparmor-patch-to-provide-compatibility.patch deleted file mode 100644 index 9ef7072..0000000 --- a/5.7/0002-UBUNTU-SAUCE-apparmor-patch-to-provide-compatibility.patch +++ /dev/null @@ -1,251 +0,0 @@ -From a76a68b73c6c316662ed1a8910b22afb2e924e37 Mon Sep 17 00:00:00 2001 -From: John Johansen <john.johansen@canonical.com> -Date: Sun, 17 Jun 2018 03:56:25 -0700 -Subject: [PATCH 2/4] UBUNTU: SAUCE: apparmor: patch to provide compatibility - with v2.x net rules - -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> -[ saf: resolve conflicts when rebasing to 4.20 ] -Signed-off-by: Seth Forshee <seth.forshee@canonical.com> ---- - security/apparmor/apparmorfs.c | 1 + - security/apparmor/include/apparmor.h | 2 +- - security/apparmor/include/net.h | 11 ++++++ - security/apparmor/include/policy.h | 2 ++ - security/apparmor/net.c | 31 ++++++++++++---- - security/apparmor/policy.c | 1 + - security/apparmor/policy_unpack.c | 54 ++++++++++++++++++++++++++-- - 7 files changed, 92 insertions(+), 10 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 47e4f2d91df7..636ecb8043b0 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -2276,6 +2276,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 6b7e6e13176e..70de52565857 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 2431c011800d..74768db94066 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 b5b4b8190e65..f904105f48de 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 d8afc39f663a..1d8f5ff53cd4 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 06355717ee84..58ff956aa6b3 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 8cfc9493eefc..c09425262d43 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 */ - - /* -@@ -311,6 +311,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) - { - void *pos = e->pos; -@@ -673,7 +686,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; -@@ -816,6 +829,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"; --- -2.25.4 - diff --git a/5.7/0003-UBUNTU-SAUCE-apparmor-af_unix-mediation.patch b/5.7/0003-UBUNTU-SAUCE-apparmor-af_unix-mediation.patch deleted file mode 100644 index 2879f31..0000000 --- a/5.7/0003-UBUNTU-SAUCE-apparmor-af_unix-mediation.patch +++ /dev/null @@ -1,1169 +0,0 @@ -From 125ca4b782b7659dab5c55a2dcae4b6922bff6f0 Mon Sep 17 00:00:00 2001 -From: John Johansen <john.johansen@canonical.com> -Date: Tue, 18 Jul 2017 23:27:23 -0700 -Subject: [PATCH 3/4] UBUNTU: SAUCE: apparmor: af_unix mediation - -af_socket mediation did not make it into 4.17 so add remaining out -of tree patch - -Signed-off-by: John Johansen <john.johansen@canonical.com> -Signed-off-by: Seth Forshee <seth.forshee@canonical.com> ---- - security/apparmor/Makefile | 3 +- - security/apparmor/af_unix.c | 652 ++++++++++++++++++++++++++++ - security/apparmor/apparmorfs.c | 6 + - security/apparmor/file.c | 4 +- - security/apparmor/include/af_unix.h | 114 +++++ - security/apparmor/include/net.h | 4 + - security/apparmor/include/path.h | 1 + - security/apparmor/include/policy.h | 10 +- - security/apparmor/lsm.c | 112 +++++ - security/apparmor/net.c | 53 ++- - 10 files changed, 953 insertions(+), 6 deletions(-) - create mode 100644 security/apparmor/af_unix.c - create mode 100644 security/apparmor/include/af_unix.h - -diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile -index ff23fcfefe19..fad407f6f62c 100644 ---- a/security/apparmor/Makefile -+++ b/security/apparmor/Makefile -@@ -5,7 +5,8 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o - - apparmor-y := apparmorfs.o audit.o capability.o task.o ipc.o lib.o match.o \ - path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ -- resource.o secid.o file.o policy_ns.o label.o mount.o net.o -+ resource.o secid.o file.o policy_ns.o label.o mount.o net.o \ -+ af_unix.o - apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o - - clean-files := capability_names.h rlim_names.h net_names.h -diff --git a/security/apparmor/af_unix.c b/security/apparmor/af_unix.c -new file mode 100644 -index 000000000000..54b3796f63d0 ---- /dev/null -+++ b/security/apparmor/af_unix.c -@@ -0,0 +1,652 @@ -+/* -+ * AppArmor security module -+ * -+ * This file contains AppArmor af_unix fine grained mediation -+ * -+ * Copyright 2018 Canonical Ltd. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation, version 2 of the -+ * License. -+ */ -+ -+#include <net/tcp_states.h> -+ -+#include "include/audit.h" -+#include "include/af_unix.h" -+#include "include/apparmor.h" -+#include "include/file.h" -+#include "include/label.h" -+#include "include/path.h" -+#include "include/policy.h" -+#include "include/cred.h" -+ -+static inline struct sock *aa_sock(struct unix_sock *u) -+{ -+ return &u->sk; -+} -+ -+static inline int unix_fs_perm(const char *op, u32 mask, struct aa_label *label, -+ struct unix_sock *u, int flags) -+{ -+ AA_BUG(!label); -+ AA_BUG(!u); -+ AA_BUG(!UNIX_FS(aa_sock(u))); -+ -+ if (unconfined(label) || !LABEL_MEDIATES(label, AA_CLASS_FILE)) -+ return 0; -+ -+ mask &= NET_FS_PERMS; -+ if (!u->path.dentry) { -+ struct path_cond cond = { }; -+ struct aa_perms perms = { }; -+ struct aa_profile *profile; -+ -+ /* socket path has been cleared because it is being shutdown -+ * can only fall back to original sun_path request -+ */ -+ struct aa_sk_ctx *ctx = SK_CTX(&u->sk); -+ if (ctx->path.dentry) -+ return aa_path_perm(op, label, &ctx->path, flags, mask, -+ &cond); -+ return fn_for_each_confined(label, profile, -+ ((flags | profile->path_flags) & PATH_MEDIATE_DELETED) ? -+ __aa_path_perm(op, profile, -+ u->addr->name->sun_path, mask, -+ &cond, flags, &perms) : -+ aa_audit_file(profile, &nullperms, op, mask, -+ u->addr->name->sun_path, NULL, -+ NULL, cond.uid, -+ "Failed name lookup - " -+ "deleted entry", -EACCES)); -+ } else { -+ /* the sunpath may not be valid for this ns so use the path */ -+ struct path_cond cond = { u->path.dentry->d_inode->i_uid, -+ u->path.dentry->d_inode->i_mode -+ }; -+ -+ return aa_path_perm(op, label, &u->path, flags, mask, &cond); -+ } -+ -+ return 0; -+} -+ -+/* passing in state returned by PROFILE_MEDIATES_AF */ -+static unsigned int match_to_prot(struct aa_profile *profile, -+ unsigned int state, int type, int protocol, -+ const char **info) -+{ -+ __be16 buffer[2]; -+ buffer[0] = cpu_to_be16(type); -+ buffer[1] = cpu_to_be16(protocol); -+ state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &buffer, -+ 4); -+ if (!state) -+ *info = "failed type and protocol match"; -+ return state; -+} -+ -+static unsigned int match_addr(struct aa_profile *profile, unsigned int state, -+ struct sockaddr_un *addr, int addrlen) -+{ -+ if (addr) -+ /* include leading \0 */ -+ state = aa_dfa_match_len(profile->policy.dfa, state, -+ addr->sun_path, -+ unix_addr_len(addrlen)); -+ else -+ /* anonymous end point */ -+ state = aa_dfa_match_len(profile->policy.dfa, state, "\x01", -+ 1); -+ /* todo change to out of band */ -+ state = aa_dfa_null_transition(profile->policy.dfa, state); -+ return state; -+} -+ -+static unsigned int match_to_local(struct aa_profile *profile, -+ unsigned int state, int type, int protocol, -+ struct sockaddr_un *addr, int addrlen, -+ const char **info) -+{ -+ state = match_to_prot(profile, state, type, protocol, info); -+ if (state) { -+ state = match_addr(profile, state, addr, addrlen); -+ if (state) { -+ /* todo: local label matching */ -+ state = aa_dfa_null_transition(profile->policy.dfa, -+ state); -+ if (!state) -+ *info = "failed local label match"; -+ } else -+ *info = "failed local address match"; -+ } -+ -+ return state; -+} -+ -+static unsigned int match_to_sk(struct aa_profile *profile, -+ unsigned int state, struct unix_sock *u, -+ const char **info) -+{ -+ struct sockaddr_un *addr = NULL; -+ int addrlen = 0; -+ -+ if (u->addr) { -+ addr = u->addr->name; -+ addrlen = u->addr->len; -+ } -+ -+ return match_to_local(profile, state, u->sk.sk_type, u->sk.sk_protocol, -+ addr, addrlen, info); -+} -+ -+#define CMD_ADDR 1 -+#define CMD_LISTEN 2 -+#define CMD_OPT 4 -+ -+static inline unsigned int match_to_cmd(struct aa_profile *profile, -+ unsigned int state, struct unix_sock *u, -+ char cmd, const char **info) -+{ -+ state = match_to_sk(profile, state, u, info); -+ if (state) { -+ state = aa_dfa_match_len(profile->policy.dfa, state, &cmd, 1); -+ if (!state) -+ *info = "failed cmd selection match"; -+ } -+ -+ return state; -+} -+ -+static inline unsigned int match_to_peer(struct aa_profile *profile, -+ unsigned int state, -+ struct unix_sock *u, -+ struct sockaddr_un *peer_addr, -+ int peer_addrlen, -+ const char **info) -+{ -+ state = match_to_cmd(profile, state, u, CMD_ADDR, info); -+ if (state) { -+ state = match_addr(profile, state, peer_addr, peer_addrlen); -+ if (!state) -+ *info = "failed peer address match"; -+ } -+ return state; -+} -+ -+static int do_perms(struct aa_profile *profile, unsigned int state, u32 request, -+ struct common_audit_data *sa) -+{ -+ struct aa_perms perms; -+ -+ AA_BUG(!profile); -+ -+ 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); -+} -+ -+static int match_label(struct aa_profile *profile, struct aa_profile *peer, -+ unsigned int state, u32 request, -+ struct common_audit_data *sa) -+{ -+ AA_BUG(!profile); -+ AA_BUG(!peer); -+ -+ aad(sa)->peer = &peer->label; -+ -+ if (state) { -+ state = aa_dfa_match(profile->policy.dfa, state, -+ peer->base.hname); -+ if (!state) -+ aad(sa)->info = "failed peer label match"; -+ } -+ return do_perms(profile, state, request, sa); -+} -+ -+ -+/* unix sock creation comes before we know if the socket will be an fs -+ * socket -+ * v6 - semantics are handled by mapping in profile load -+ * v7 - semantics require sock create for tasks creating an fs socket. -+ */ -+static int profile_create_perm(struct aa_profile *profile, int family, -+ int type, int protocol) -+{ -+ unsigned int state; -+ DEFINE_AUDIT_NET(sa, OP_CREATE, NULL, family, type, protocol); -+ -+ AA_BUG(!profile); -+ AA_BUG(profile_unconfined(profile)); -+ -+ if ((state = PROFILE_MEDIATES_AF(profile, AF_UNIX))) { -+ state = match_to_prot(profile, state, type, protocol, -+ &aad(&sa)->info); -+ return do_perms(profile, state, AA_MAY_CREATE, &sa); -+ } -+ -+ return aa_profile_af_perm(profile, &sa, AA_MAY_CREATE, family, type); -+} -+ -+int aa_unix_create_perm(struct aa_label *label, int family, int type, -+ int protocol) -+{ -+ struct aa_profile *profile; -+ -+ if (unconfined(label)) -+ return 0; -+ -+ return fn_for_each_confined(label, profile, -+ profile_create_perm(profile, family, type, protocol)); -+} -+ -+ -+static inline int profile_sk_perm(struct aa_profile *profile, const char *op, -+ u32 request, struct sock *sk) -+{ -+ unsigned int state; -+ DEFINE_AUDIT_SK(sa, op, sk); -+ -+ AA_BUG(!profile); -+ AA_BUG(!sk); -+ AA_BUG(UNIX_FS(sk)); -+ AA_BUG(profile_unconfined(profile)); -+ -+ state = PROFILE_MEDIATES_AF(profile, AF_UNIX); -+ if (state) { -+ state = match_to_sk(profile, state, unix_sk(sk), -+ &aad(&sa)->info); -+ return do_perms(profile, state, request, &sa); -+ } -+ -+ return aa_profile_af_sk_perm(profile, &sa, request, sk); -+} -+ -+int aa_unix_label_sk_perm(struct aa_label *label, const char *op, u32 request, -+ struct sock *sk) -+{ -+ struct aa_profile *profile; -+ -+ return fn_for_each_confined(label, profile, -+ profile_sk_perm(profile, op, request, sk)); -+} -+ -+static int unix_label_sock_perm(struct aa_label *label, const char *op, u32 request, -+ struct socket *sock) -+{ -+ if (unconfined(label)) -+ return 0; -+ if (UNIX_FS(sock->sk)) -+ return unix_fs_perm(op, request, label, unix_sk(sock->sk), 0); -+ -+ return aa_unix_label_sk_perm(label, op, request, sock->sk); -+} -+ -+/* revaliation, get/set attr */ -+int aa_unix_sock_perm(const char *op, u32 request, struct socket *sock) -+{ -+ struct aa_label *label; -+ int error; -+ -+ label = begin_current_label_crit_section(); -+ error = unix_label_sock_perm(label, op, request, sock); -+ end_current_label_crit_section(label); -+ -+ return error; -+} -+ -+static int profile_bind_perm(struct aa_profile *profile, struct sock *sk, -+ struct sockaddr *addr, int addrlen) -+{ -+ unsigned int state; -+ DEFINE_AUDIT_SK(sa, OP_BIND, sk); -+ -+ AA_BUG(!profile); -+ AA_BUG(!sk); -+ AA_BUG(addr->sa_family != AF_UNIX); -+ AA_BUG(profile_unconfined(profile)); -+ AA_BUG(unix_addr_fs(addr, addrlen)); -+ -+ state = PROFILE_MEDIATES_AF(profile, AF_UNIX); -+ if (state) { -+ /* bind for abstract socket */ -+ aad(&sa)->net.addr = unix_addr(addr); -+ aad(&sa)->net.addrlen = addrlen; -+ -+ state = match_to_local(profile, state, -+ sk->sk_type, sk->sk_protocol, -+ unix_addr(addr), addrlen, -+ &aad(&sa)->info); -+ return do_perms(profile, state, AA_MAY_BIND, &sa); -+ } -+ -+ return aa_profile_af_sk_perm(profile, &sa, AA_MAY_BIND, sk); -+} -+ -+int aa_unix_bind_perm(struct socket *sock, struct sockaddr *address, -+ int addrlen) -+{ -+ struct aa_profile *profile; -+ struct aa_label *label; -+ int error = 0; -+ -+ label = begin_current_label_crit_section(); -+ /* fs bind is handled by mknod */ -+ if (!(unconfined(label) || unix_addr_fs(address, addrlen))) -+ error = fn_for_each_confined(label, profile, -+ profile_bind_perm(profile, sock->sk, address, -+ addrlen)); -+ end_current_label_crit_section(label); -+ -+ return error; -+} -+ -+int aa_unix_connect_perm(struct socket *sock, struct sockaddr *address, -+ int addrlen) -+{ -+ /* unix connections are covered by the -+ * - unix_stream_connect (stream) and unix_may_send hooks (dgram) -+ * - fs connect is handled by open -+ */ -+ return 0; -+} -+ -+static int profile_listen_perm(struct aa_profile *profile, struct sock *sk, -+ int backlog) -+{ -+ unsigned int state; -+ DEFINE_AUDIT_SK(sa, OP_LISTEN, sk); -+ -+ AA_BUG(!profile); -+ AA_BUG(!sk); -+ AA_BUG(UNIX_FS(sk)); -+ AA_BUG(profile_unconfined(profile)); -+ -+ state = PROFILE_MEDIATES_AF(profile, AF_UNIX); -+ if (state) { -+ __be16 b = cpu_to_be16(backlog); -+ -+ state = match_to_cmd(profile, state, unix_sk(sk), CMD_LISTEN, -+ &aad(&sa)->info); -+ if (state) { -+ state = aa_dfa_match_len(profile->policy.dfa, state, -+ (char *) &b, 2); -+ if (!state) -+ aad(&sa)->info = "failed listen backlog match"; -+ } -+ return do_perms(profile, state, AA_MAY_LISTEN, &sa); -+ } -+ -+ return aa_profile_af_sk_perm(profile, &sa, AA_MAY_LISTEN, sk); -+} -+ -+int aa_unix_listen_perm(struct socket *sock, int backlog) -+{ -+ struct aa_profile *profile; -+ struct aa_label *label; -+ int error = 0; -+ -+ label = begin_current_label_crit_section(); -+ if (!(unconfined(label) || UNIX_FS(sock->sk))) -+ error = fn_for_each_confined(label, profile, -+ profile_listen_perm(profile, sock->sk, -+ backlog)); -+ end_current_label_crit_section(label); -+ -+ return error; -+} -+ -+ -+static inline int profile_accept_perm(struct aa_profile *profile, -+ struct sock *sk, -+ struct sock *newsk) -+{ -+ unsigned int state; -+ DEFINE_AUDIT_SK(sa, OP_ACCEPT, sk); -+ -+ AA_BUG(!profile); -+ AA_BUG(!sk); -+ AA_BUG(UNIX_FS(sk)); -+ AA_BUG(profile_unconfined(profile)); -+ -+ state = PROFILE_MEDIATES_AF(profile, AF_UNIX); -+ if (state) { -+ state = match_to_sk(profile, state, unix_sk(sk), -+ &aad(&sa)->info); -+ return do_perms(profile, state, AA_MAY_ACCEPT, &sa); -+ } -+ -+ return aa_profile_af_sk_perm(profile, &sa, AA_MAY_ACCEPT, sk); -+} -+ -+/* ability of sock to connect, not peer address binding */ -+int aa_unix_accept_perm(struct socket *sock, struct socket *newsock) -+{ -+ struct aa_profile *profile; -+ struct aa_label *label; -+ int error = 0; -+ -+ label = begin_current_label_crit_section(); -+ if (!(unconfined(label) || UNIX_FS(sock->sk))) -+ error = fn_for_each_confined(label, profile, -+ profile_accept_perm(profile, sock->sk, -+ newsock->sk)); -+ end_current_label_crit_section(label); -+ -+ return error; -+} -+ -+ -+/* dgram handled by unix_may_sendmsg, right to send on stream done at connect -+ * could do per msg unix_stream here -+ */ -+/* sendmsg, recvmsg */ -+int aa_unix_msg_perm(const char *op, u32 request, struct socket *sock, -+ struct msghdr *msg, int size) -+{ -+ return 0; -+} -+ -+ -+static int profile_opt_perm(struct aa_profile *profile, const char *op, u32 request, -+ struct sock *sk, int level, int optname) -+{ -+ unsigned int state; -+ DEFINE_AUDIT_SK(sa, op, sk); -+ -+ AA_BUG(!profile); -+ AA_BUG(!sk); -+ AA_BUG(UNIX_FS(sk)); -+ AA_BUG(profile_unconfined(profile)); -+ -+ state = PROFILE_MEDIATES_AF(profile, AF_UNIX); -+ if (state) { -+ __be16 b = cpu_to_be16(optname); -+ -+ state = match_to_cmd(profile, state, unix_sk(sk), CMD_OPT, -+ &aad(&sa)->info); -+ if (state) { -+ state = aa_dfa_match_len(profile->policy.dfa, state, -+ (char *) &b, 2); -+ if (!state) -+ aad(&sa)->info = "failed sockopt match"; -+ } -+ return do_perms(profile, state, request, &sa); -+ } -+ -+ return aa_profile_af_sk_perm(profile, &sa, request, sk); -+} -+ -+int aa_unix_opt_perm(const char *op, u32 request, struct socket *sock, int level, -+ int optname) -+{ -+ struct aa_profile *profile; -+ struct aa_label *label; -+ int error = 0; -+ -+ label = begin_current_label_crit_section(); -+ if (!(unconfined(label) || UNIX_FS(sock->sk))) -+ error = fn_for_each_confined(label, profile, -+ profile_opt_perm(profile, op, request, -+ sock->sk, level, optname)); -+ end_current_label_crit_section(label); -+ -+ return error; -+} -+ -+/* null peer_label is allowed, in which case the peer_sk label is used */ -+static int profile_peer_perm(struct aa_profile *profile, const char *op, u32 request, -+ struct sock *sk, struct sock *peer_sk, -+ struct aa_label *peer_label, -+ struct common_audit_data *sa) -+{ -+ unsigned int state; -+ -+ AA_BUG(!profile); -+ AA_BUG(profile_unconfined(profile)); -+ AA_BUG(!sk); -+ AA_BUG(!peer_sk); -+ AA_BUG(UNIX_FS(peer_sk)); -+ -+ state = PROFILE_MEDIATES_AF(profile, AF_UNIX); -+ if (state) { -+ struct aa_sk_ctx *peer_ctx = SK_CTX(peer_sk); -+ struct aa_profile *peerp; -+ struct sockaddr_un *addr = NULL; -+ int len = 0; -+ if (unix_sk(peer_sk)->addr) { -+ addr = unix_sk(peer_sk)->addr->name; -+ len = unix_sk(peer_sk)->addr->len; -+ } -+ state = match_to_peer(profile, state, unix_sk(sk), -+ addr, len, &aad(sa)->info); -+ if (!peer_label) -+ peer_label = peer_ctx->label; -+ return fn_for_each_in_ns(peer_label, peerp, -+ match_label(profile, peerp, state, request, -+ sa)); -+ } -+ -+ return aa_profile_af_sk_perm(profile, sa, request, sk); -+} -+ -+/** -+ * -+ * Requires: lock held on both @sk and @peer_sk -+ */ -+int aa_unix_peer_perm(struct aa_label *label, const char *op, u32 request, -+ struct sock *sk, struct sock *peer_sk, -+ struct aa_label *peer_label) -+{ -+ struct unix_sock *peeru = unix_sk(peer_sk); -+ struct unix_sock *u = unix_sk(sk); -+ -+ AA_BUG(!label); -+ AA_BUG(!sk); -+ AA_BUG(!peer_sk); -+ -+ if (UNIX_FS(aa_sock(peeru))) -+ return unix_fs_perm(op, request, label, peeru, 0); -+ else if (UNIX_FS(aa_sock(u))) -+ return unix_fs_perm(op, request, label, u, 0); -+ else { -+ struct aa_profile *profile; -+ DEFINE_AUDIT_SK(sa, op, sk); -+ aad(&sa)->net.peer_sk = peer_sk; -+ -+ /* TODO: ns!!! */ -+ if (!net_eq(sock_net(sk), sock_net(peer_sk))) { -+ ; -+ } -+ -+ if (unconfined(label)) -+ return 0; -+ -+ return fn_for_each_confined(label, profile, -+ profile_peer_perm(profile, op, request, sk, -+ peer_sk, peer_label, &sa)); -+ } -+} -+ -+ -+/* from net/unix/af_unix.c */ -+static void unix_state_double_lock(struct sock *sk1, struct sock *sk2) -+{ -+ if (unlikely(sk1 == sk2) || !sk2) { -+ unix_state_lock(sk1); -+ return; -+ } -+ if (sk1 < sk2) { -+ unix_state_lock(sk1); -+ unix_state_lock_nested(sk2); -+ } else { -+ unix_state_lock(sk2); -+ unix_state_lock_nested(sk1); -+ } -+} -+ -+static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2) -+{ -+ if (unlikely(sk1 == sk2) || !sk2) { -+ unix_state_unlock(sk1); -+ return; -+ } -+ unix_state_unlock(sk1); -+ unix_state_unlock(sk2); -+} -+ -+int aa_unix_file_perm(struct aa_label *label, const char *op, u32 request, -+ struct socket *sock) -+{ -+ struct sock *peer_sk = NULL; -+ u32 sk_req = request & ~NET_PEER_MASK; -+ int error = 0; -+ -+ AA_BUG(!label); -+ AA_BUG(!sock); -+ AA_BUG(!sock->sk); -+ AA_BUG(sock->sk->sk_family != AF_UNIX); -+ -+ /* TODO: update sock label with new task label */ -+ unix_state_lock(sock->sk); -+ peer_sk = unix_peer(sock->sk); -+ if (peer_sk) -+ sock_hold(peer_sk); -+ if (!unix_connected(sock) && sk_req) { -+ error = unix_label_sock_perm(label, op, sk_req, sock); -+ if (!error) { -+ // update label -+ } -+ } -+ unix_state_unlock(sock->sk); -+ if (!peer_sk) -+ return error; -+ -+ unix_state_double_lock(sock->sk, peer_sk); -+ if (UNIX_FS(sock->sk)) { -+ error = unix_fs_perm(op, request, label, unix_sk(sock->sk), -+ PATH_SOCK_COND); -+ } else if (UNIX_FS(peer_sk)) { -+ error = unix_fs_perm(op, request, label, unix_sk(peer_sk), -+ PATH_SOCK_COND); -+ } else { -+ struct aa_sk_ctx *pctx = SK_CTX(peer_sk); -+ if (sk_req) -+ error = aa_unix_label_sk_perm(label, op, sk_req, -+ sock->sk); -+ last_error(error, -+ xcheck(aa_unix_peer_perm(label, op, -+ MAY_READ | MAY_WRITE, -+ sock->sk, peer_sk, NULL), -+ aa_unix_peer_perm(pctx->label, op, -+ MAY_READ | MAY_WRITE, -+ peer_sk, sock->sk, label))); -+ } -+ -+ unix_state_double_unlock(sock->sk, peer_sk); -+ sock_put(peer_sk); -+ -+ return error; -+} -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 636ecb8043b0..f154def01597 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -2260,6 +2260,11 @@ static struct aa_sfs_entry aa_sfs_entry_ns[] = { - { } - }; - -+static struct aa_sfs_entry aa_sfs_entry_dbus[] = { -+ AA_SFS_FILE_STRING("mask", "acquire send receive"), -+ { } -+}; -+ - static struct aa_sfs_entry aa_sfs_entry_query_label[] = { - AA_SFS_FILE_STRING("perms", "allow deny audit quiet"), - AA_SFS_FILE_BOOLEAN("data", 1), -@@ -2284,6 +2289,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = { - AA_SFS_DIR("caps", aa_sfs_entry_caps), - AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace), - AA_SFS_DIR("signal", aa_sfs_entry_signal), -+ AA_SFS_DIR("dbus", aa_sfs_entry_dbus), - AA_SFS_DIR("query", aa_sfs_entry_query), - { } - }; -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index 4c1b05eb130c..8aa7af54b70a 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -12,6 +12,7 @@ - #include <linux/fdtable.h> - #include <linux/file.h> - -+#include "include/af_unix.h" - #include "include/apparmor.h" - #include "include/audit.h" - #include "include/cred.h" -@@ -280,7 +281,8 @@ int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name, - { - int e = 0; - -- if (profile_unconfined(profile)) -+ if (profile_unconfined(profile) || -+ ((flags & PATH_SOCK_COND) && !PROFILE_MEDIATES_AF(profile, AF_UNIX))) - return 0; - aa_str_perms(profile->file.dfa, profile->file.start, name, cond, perms); - if (request & ~perms->allow) -diff --git a/security/apparmor/include/af_unix.h b/security/apparmor/include/af_unix.h -new file mode 100644 -index 000000000000..d1b7f2316be4 ---- /dev/null -+++ b/security/apparmor/include/af_unix.h -@@ -0,0 +1,114 @@ -+/* -+ * AppArmor security module -+ * -+ * This file contains AppArmor af_unix fine grained mediation -+ * -+ * Copyright 2014 Canonical Ltd. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation, version 2 of the -+ * License. -+ */ -+#ifndef __AA_AF_UNIX_H -+ -+#include <net/af_unix.h> -+ -+#include "label.h" -+//#include "include/net.h" -+ -+#define unix_addr_len(L) ((L) - sizeof(sa_family_t)) -+#define unix_abstract_name_len(L) (unix_addr_len(L) - 1) -+#define unix_abstract_len(U) (unix_abstract_name_len((U)->addr->len)) -+#define addr_unix_abstract_name(B) ((B)[0] == 0) -+#define addr_unix_anonymous(U) (addr_unix_len(U) <= 0) -+#define addr_unix_abstract(U) (!addr_unix_anonymous(U) && addr_unix_abstract_name((U)->addr)) -+//#define unix_addr_fs(U) (!unix_addr_anonymous(U) && !unix_addr_abstract_name((U)->addr)) -+ -+#define unix_addr(A) ((struct sockaddr_un *)(A)) -+#define unix_addr_anon(A, L) ((A) && unix_addr_len(L) <= 0) -+#define unix_addr_fs(A, L) (!unix_addr_anon(A, L) && !addr_unix_abstract_name(unix_addr(A)->sun_path)) -+ -+#define UNIX_ANONYMOUS(U) (!unix_sk(U)->addr) -+/* from net/unix/af_unix.c */ -+#define UNIX_ABSTRACT(U) (!UNIX_ANONYMOUS(U) && \ -+ unix_sk(U)->addr->hash < UNIX_HASH_SIZE) -+#define UNIX_FS(U) (!UNIX_ANONYMOUS(U) && unix_sk(U)->addr->name->sun_path[0]) -+#define unix_peer(sk) (unix_sk(sk)->peer) -+#define unix_connected(S) ((S)->state == SS_CONNECTED) -+ -+static inline void print_unix_addr(struct sockaddr_un *A, int L) -+{ -+ char *buf = (A) ? (char *) &(A)->sun_path : NULL; -+ int len = unix_addr_len(L); -+ if (!buf || len <= 0) -+ printk(" <anonymous>"); -+ else if (buf[0]) -+ printk(" %s", buf); -+ else -+ /* abstract name len includes leading \0 */ -+ printk(" %d @%.*s", len - 1, len - 1, buf+1); -+}; -+ -+/* -+ printk("%s: %s: f %d, t %d, p %d", __FUNCTION__, \ -+ #SK , \ -+*/ -+#define print_unix_sk(SK) \ -+do { \ -+ struct unix_sock *u = unix_sk(SK); \ -+ printk("%s: f %d, t %d, p %d", #SK , \ -+ (SK)->sk_family, (SK)->sk_type, (SK)->sk_protocol); \ -+ if (u->addr) \ -+ print_unix_addr(u->addr->name, u->addr->len); \ -+ else \ -+ print_unix_addr(NULL, sizeof(sa_family_t)); \ -+ /* printk("\n");*/ \ -+} while (0) -+ -+#define print_sk(SK) \ -+do { \ -+ if (!(SK)) { \ -+ printk("%s: %s is null\n", __FUNCTION__, #SK); \ -+ } else if ((SK)->sk_family == PF_UNIX) { \ -+ print_unix_sk(SK); \ -+ printk("\n"); \ -+ } else { \ -+ printk("%s: %s: family %d\n", __FUNCTION__, #SK , \ -+ (SK)->sk_family); \ -+ } \ -+} while (0) -+ -+#define print_sock_addr(U) \ -+do { \ -+ printk("%s:\n", __FUNCTION__); \ -+ printk(" sock %s:", sock_ctx && sock_ctx->label ? aa_label_printk(sock_ctx->label, GFP_ATOMIC); : "<null>"); print_sk(sock); \ -+ printk(" other %s:", other_ctx && other_ctx->label ? aa_label_printk(other_ctx->label, GFP_ATOMIC); : "<null>"); print_sk(other); \ -+ printk(" new %s", new_ctx && new_ctx->label ? aa_label_printk(new_ctx->label, GFP_ATOMIC); : "<null>"); print_sk(newsk); \ -+} while (0) -+ -+ -+ -+ -+int aa_unix_peer_perm(struct aa_label *label, const char *op, u32 request, -+ struct sock *sk, struct sock *peer_sk, -+ struct aa_label *peer_label); -+int aa_unix_label_sk_perm(struct aa_label *label, const char *op, u32 request, -+ struct sock *sk); -+int aa_unix_sock_perm(const char *op, u32 request, struct socket *sock); -+int aa_unix_create_perm(struct aa_label *label, int family, int type, -+ int protocol); -+int aa_unix_bind_perm(struct socket *sock, struct sockaddr *address, -+ int addrlen); -+int aa_unix_connect_perm(struct socket *sock, struct sockaddr *address, -+ int addrlen); -+int aa_unix_listen_perm(struct socket *sock, int backlog); -+int aa_unix_accept_perm(struct socket *sock, struct socket *newsock); -+int aa_unix_msg_perm(const char *op, u32 request, struct socket *sock, -+ struct msghdr *msg, int size); -+int aa_unix_opt_perm(const char *op, u32 request, struct socket *sock, int level, -+ int optname); -+int aa_unix_file_perm(struct aa_label *label, const char *op, u32 request, -+ struct socket *sock); -+ -+#endif /* __AA_AF_UNIX_H */ -diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h -index 74768db94066..4ff96fa0b0b5 100644 ---- a/security/apparmor/include/net.h -+++ b/security/apparmor/include/net.h -@@ -49,6 +49,7 @@ - struct aa_sk_ctx { - struct aa_label *label; - struct aa_label *peer; -+ struct path path; - }; - - #define SK_CTX(X) ((X)->sk_security) -@@ -83,6 +84,9 @@ struct aa_net_compat { - ({ \ - int __e; \ - switch ((FAMILY)) { \ -+ case AF_UNIX: \ -+ __e = aa_unix_ ## FN; \ -+ break; \ - default: \ - __e = DEF_FN; \ - } \ -diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h -index 35a8295e8f3a..de8000331953 100644 ---- a/security/apparmor/include/path.h -+++ b/security/apparmor/include/path.h -@@ -14,6 +14,7 @@ - - enum path_flags { - PATH_IS_DIR = 0x1, /* path is a directory */ -+ PATH_SOCK_COND = 0x2, - PATH_CONNECT_PATH = 0x4, /* connect disconnected paths to / */ - PATH_CHROOT_REL = 0x8, /* do path lookup relative to chroot */ - PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */ -diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h -index f904105f48de..f1c9cdc49a0d 100644 ---- a/security/apparmor/include/policy.h -+++ b/security/apparmor/include/policy.h -@@ -230,9 +230,13 @@ static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile, - unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET); - __be16 be_af = cpu_to_be16(AF); - -- if (!state) -- return 0; -- return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2); -+ if (!state) { -+ state = PROFILE_MEDIATES(profile, AA_CLASS_NET_COMPAT); -+ if (!state) -+ return 0; -+ } -+ state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2); -+ return state; - } - - /** -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index e31965dc6dd1..227cff21fb95 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -24,6 +24,7 @@ - #include <net/sock.h> - #include <uapi/linux/mount.h> - -+#include "include/af_unix.h" - #include "include/apparmor.h" - #include "include/apparmorfs.h" - #include "include/audit.h" -@@ -779,6 +780,7 @@ static void apparmor_sk_free_security(struct sock *sk) - SK_CTX(sk) = NULL; - aa_put_label(ctx->label); - aa_put_label(ctx->peer); -+ path_put(&ctx->path); - kfree(ctx); - } - -@@ -798,6 +800,99 @@ static void apparmor_sk_clone_security(const struct sock *sk, - if (new->peer) - aa_put_label(new->peer); - new->peer = aa_get_label(ctx->peer); -+ new->path = ctx->path; -+ path_get(&new->path); -+} -+ -+static struct path *UNIX_FS_CONN_PATH(struct sock *sk, struct sock *newsk) -+{ -+ if (sk->sk_family == PF_UNIX && UNIX_FS(sk)) -+ return &unix_sk(sk)->path; -+ else if (newsk->sk_family == PF_UNIX && UNIX_FS(newsk)) -+ return &unix_sk(newsk)->path; -+ return NULL; -+} -+ -+/** -+ * apparmor_unix_stream_connect - check perms before making unix domain conn -+ * -+ * peer is locked when this hook is called -+ */ -+static int apparmor_unix_stream_connect(struct sock *sk, struct sock *peer_sk, -+ struct sock *newsk) -+{ -+ struct aa_sk_ctx *sk_ctx = SK_CTX(sk); -+ struct aa_sk_ctx *peer_ctx = SK_CTX(peer_sk); -+ struct aa_sk_ctx *new_ctx = SK_CTX(newsk); -+ struct aa_label *label; -+ struct path *path; -+ int error; -+ -+ label = __begin_current_label_crit_section(); -+ error = aa_unix_peer_perm(label, OP_CONNECT, -+ (AA_MAY_CONNECT | AA_MAY_SEND | AA_MAY_RECEIVE), -+ sk, peer_sk, NULL); -+ if (!UNIX_FS(peer_sk)) { -+ last_error(error, -+ aa_unix_peer_perm(peer_ctx->label, OP_CONNECT, -+ (AA_MAY_ACCEPT | AA_MAY_SEND | AA_MAY_RECEIVE), -+ peer_sk, sk, label)); -+ } -+ __end_current_label_crit_section(label); -+ -+ if (error) -+ return error; -+ -+ /* label newsk if it wasn't labeled in post_create. Normally this -+ * would be done in sock_graft, but because we are directly looking -+ * at the peer_sk to obtain peer_labeling for unix socks this -+ * does not work -+ */ -+ if (!new_ctx->label) -+ new_ctx->label = aa_get_label(peer_ctx->label); -+ -+ /* Cross reference the peer labels for SO_PEERSEC */ -+ if (new_ctx->peer) -+ aa_put_label(new_ctx->peer); -+ -+ if (sk_ctx->peer) -+ aa_put_label(sk_ctx->peer); -+ -+ new_ctx->peer = aa_get_label(sk_ctx->label); -+ sk_ctx->peer = aa_get_label(peer_ctx->label); -+ -+ path = UNIX_FS_CONN_PATH(sk, peer_sk); -+ if (path) { -+ new_ctx->path = *path; -+ sk_ctx->path = *path; -+ path_get(path); -+ path_get(path); -+ } -+ return 0; -+} -+ -+/** -+ * apparmor_unix_may_send - check perms before conn or sending unix dgrams -+ * -+ * other is locked when this hook is called -+ * -+ * dgram connect calls may_send, peer setup but path not copied????? -+ */ -+static int apparmor_unix_may_send(struct socket *sock, struct socket *peer) -+{ -+ struct aa_sk_ctx *peer_ctx = SK_CTX(peer->sk); -+ struct aa_label *label; -+ int error; -+ -+ label = __begin_current_label_crit_section(); -+ error = xcheck(aa_unix_peer_perm(label, OP_SENDMSG, AA_MAY_SEND, -+ sock->sk, peer->sk, NULL), -+ aa_unix_peer_perm(peer_ctx->label, OP_SENDMSG, -+ AA_MAY_RECEIVE, -+ peer->sk, sock->sk, label)); -+ __end_current_label_crit_section(label); -+ -+ return error; - } - - /** -@@ -1043,11 +1138,25 @@ static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) - - static struct aa_label *sk_peer_label(struct sock *sk) - { -+ struct sock *peer_sk; - struct aa_sk_ctx *ctx = SK_CTX(sk); - - if (ctx->peer) - return ctx->peer; - -+ if (sk->sk_family != PF_UNIX) -+ return ERR_PTR(-ENOPROTOOPT); -+ -+ /* check for sockpair peering which does not go through -+ * security_unix_stream_connect -+ */ -+ peer_sk = unix_peer(sk); -+ if (peer_sk) { -+ ctx = SK_CTX(peer_sk); -+ if (ctx->label) -+ return ctx->label; -+ } -+ - return ERR_PTR(-ENOPROTOOPT); - } - -@@ -1194,6 +1303,9 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { - LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security), - LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security), - -+ LSM_HOOK_INIT(unix_stream_connect, apparmor_unix_stream_connect), -+ LSM_HOOK_INIT(unix_may_send, apparmor_unix_may_send), -+ - LSM_HOOK_INIT(socket_create, apparmor_socket_create), - LSM_HOOK_INIT(socket_post_create, apparmor_socket_post_create), - LSM_HOOK_INIT(socket_bind, apparmor_socket_bind), -diff --git a/security/apparmor/net.c b/security/apparmor/net.c -index 1d8f5ff53cd4..297589c6dc95 100644 ---- a/security/apparmor/net.c -+++ b/security/apparmor/net.c -@@ -8,6 +8,7 @@ - * Copyright 2009-2017 Canonical Ltd. - */ - -+#include "include/af_unix.h" - #include "include/apparmor.h" - #include "include/audit.h" - #include "include/cred.h" -@@ -26,6 +27,7 @@ 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), -+ AA_SFS_FILE_BOOLEAN("af_unix", 1), - { } - }; - -@@ -71,6 +73,36 @@ static const char * const net_mask_names[] = { - "unknown", - }; - -+static void audit_unix_addr(struct audit_buffer *ab, const char *str, -+ struct sockaddr_un *addr, int addrlen) -+{ -+ int len = unix_addr_len(addrlen); -+ -+ if (!addr || len <= 0) { -+ audit_log_format(ab, " %s=none", str); -+ } else if (addr->sun_path[0]) { -+ audit_log_format(ab, " %s=", str); -+ audit_log_untrustedstring(ab, addr->sun_path); -+ } else { -+ audit_log_format(ab, " %s=\"@", str); -+ if (audit_string_contains_control(&addr->sun_path[1], len - 1)) -+ audit_log_n_hex(ab, &addr->sun_path[1], len - 1); -+ else -+ audit_log_format(ab, "%.*s", len - 1, -+ &addr->sun_path[1]); -+ audit_log_format(ab, "\""); -+ } -+} -+ -+static void audit_unix_sk_addr(struct audit_buffer *ab, const char *str, -+ struct sock *sk) -+{ -+ struct unix_sock *u = unix_sk(sk); -+ if (u && u->addr) -+ audit_unix_addr(ab, str, u->addr->name, u->addr->len); -+ else -+ audit_unix_addr(ab, str, NULL, 0); -+} - - /* audit callback for net specific fields */ - void audit_net_cb(struct audit_buffer *ab, void *va) -@@ -100,6 +132,23 @@ void audit_net_cb(struct audit_buffer *ab, void *va) - net_mask_names, NET_PERMS_MASK); - } - } -+ if (sa->u.net->family == AF_UNIX) { -+ if ((aad(sa)->request & ~NET_PEER_MASK) && aad(sa)->net.addr) -+ audit_unix_addr(ab, "addr", -+ unix_addr(aad(sa)->net.addr), -+ aad(sa)->net.addrlen); -+ else -+ audit_unix_sk_addr(ab, "addr", sa->u.net->sk); -+ if (aad(sa)->request & NET_PEER_MASK) { -+ if (aad(sa)->net.addr) -+ audit_unix_addr(ab, "peer_addr", -+ unix_addr(aad(sa)->net.addr), -+ aad(sa)->net.addrlen); -+ else -+ audit_unix_sk_addr(ab, "peer_addr", -+ aad(sa)->net.peer_sk); -+ } -+ } - if (aad(sa)->peer) { - audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, -@@ -200,7 +249,9 @@ int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, - AA_BUG(!sock); - AA_BUG(!sock->sk); - -- return aa_label_sk_perm(label, op, request, sock->sk); -+ return af_select(sock->sk->sk_family, -+ file_perm(label, op, request, sock), -+ aa_label_sk_perm(label, op, request, sock->sk)); - } - - #ifdef CONFIG_NETWORK_SECMARK --- -2.25.4 - diff --git a/5.7/0004-UBUNTU-SAUCE-apparmor-fix-use-after-free-in-sk_peer_.patch b/5.7/0004-UBUNTU-SAUCE-apparmor-fix-use-after-free-in-sk_peer_.patch deleted file mode 100644 index 39ec87b..0000000 --- a/5.7/0004-UBUNTU-SAUCE-apparmor-fix-use-after-free-in-sk_peer_.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 2982ea862b37d7420836b9ff579352b282748a83 Mon Sep 17 00:00:00 2001 -From: John Johansen <john.johansen@canonical.com> -Date: Tue, 26 Jun 2018 20:19:19 -0700 -Subject: [PATCH 4/4] UBUNTU: SAUCE: apparmor: fix use after free in - sk_peer_label - -BugLink: http://bugs.launchpad.net/bugs/1778646 -Signed-off-by: John Johansen <john.johansen@canonical.com> -Signed-off-by: Seth Forshee <seth.forshee@canonical.com> ---- - security/apparmor/lsm.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index 227cff21fb95..12d5c4f186c0 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -1140,9 +1140,10 @@ static struct aa_label *sk_peer_label(struct sock *sk) - { - struct sock *peer_sk; - struct aa_sk_ctx *ctx = SK_CTX(sk); -+ struct aa_label *label = ERR_PTR(-ENOPROTOOPT); - - if (ctx->peer) -- return ctx->peer; -+ return aa_get_label(ctx->peer); - - if (sk->sk_family != PF_UNIX) - return ERR_PTR(-ENOPROTOOPT); -@@ -1150,14 +1151,15 @@ static struct aa_label *sk_peer_label(struct sock *sk) - /* check for sockpair peering which does not go through - * security_unix_stream_connect - */ -- peer_sk = unix_peer(sk); -+ peer_sk = unix_peer_get(sk); - if (peer_sk) { - ctx = SK_CTX(peer_sk); - if (ctx->label) -- return ctx->label; -+ label = aa_get_label(ctx->label); -+ sock_put(peer_sk); - } - -- return ERR_PTR(-ENOPROTOOPT); -+ return label; - } - - /** -@@ -1201,6 +1203,7 @@ static int apparmor_socket_getpeersec_stream(struct socket *sock, - - } - -+ aa_put_label(peer); - done: - end_current_label_crit_section(label); - --- -2.25.4 - -- GitLab