diff --git a/kernel-patches/for-mainline/apparmor-audit.diff b/kernel-patches/for-mainline/apparmor-audit.diff index f06a2cd5b..7dc1bb225 100644 --- a/kernel-patches/for-mainline/apparmor-audit.diff +++ b/kernel-patches/for-mainline/apparmor-audit.diff @@ -27,7 +27,7 @@ Signed-off-by: John Johansen * 1600 - 1699 kernel crypto events * 1700 - 1799 kernel anomaly records * 1800 - 1999 future kernel use (maybe integrity labels and related events) -@@ -113,6 +113,13 @@ +@@ -109,6 +109,13 @@ #define AUDIT_MAC_IPSEC_ADDSPD 1413 /* Add a XFRM policy */ #define AUDIT_MAC_IPSEC_DELSPD 1414 /* Delete a XFRM policy */ @@ -41,7 +41,7 @@ Signed-off-by: John Johansen #define AUDIT_FIRST_KERN_ANOM_MSG 1700 #define AUDIT_LAST_KERN_ANOM_MSG 1799 #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ -@@ -509,6 +516,9 @@ extern void audit_log(struct audit_ +@@ -499,6 +506,9 @@ extern void audit_log(struct audit_ __attribute__((format(printf,4,5))); extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type); @@ -53,7 +53,7 @@ Signed-off-by: John Johansen __attribute__((format(printf,2,3))); --- a/kernel/audit.c +++ b/kernel/audit.c -@@ -1136,8 +1136,7 @@ static inline int audit_expand(struct au +@@ -1054,8 +1054,7 @@ static inline int audit_expand(struct au * will be called a second time. Currently, we assume that a printk * can't format message larger than 1024 bytes, so we don't either. */ @@ -63,7 +63,7 @@ Signed-off-by: John Johansen { int len, avail; struct sk_buff *skb; -@@ -1392,3 +1391,6 @@ EXPORT_SYMBOL(audit_log_start); +@@ -1311,3 +1310,6 @@ EXPORT_SYMBOL(audit_log_start); EXPORT_SYMBOL(audit_log_end); EXPORT_SYMBOL(audit_log_format); EXPORT_SYMBOL(audit_log); diff --git a/kernel-patches/for-mainline/apparmor-lsm.diff b/kernel-patches/for-mainline/apparmor-lsm.diff index 548392a0a..3195e26a8 100644 --- a/kernel-patches/for-mainline/apparmor-lsm.diff +++ b/kernel-patches/for-mainline/apparmor-lsm.diff @@ -7,12 +7,12 @@ Signed-off-by: John Johansen Signed-off-by: Andreas Gruenbacher --- - security/apparmor/lsm.c | 817 ++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 817 insertions(+) + security/apparmor/lsm.c | 841 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 841 insertions(+) --- /dev/null +++ b/security/apparmor/lsm.c -@@ -0,0 +1,817 @@ +@@ -0,0 +1,841 @@ +/* + * Copyright (C) 1998-2007 Novell/SUSE + * @@ -298,7 +298,7 @@ Signed-off-by: Andreas Gruenbacher + return error; +} + -+static int aa_permission(struct inode *inode, const char *operation, ++static int aa_permission(const char *operation, struct inode *inode, + struct dentry *dentry, struct vfsmount *mnt, + int mask, int check) +{ @@ -316,10 +316,20 @@ Signed-off-by: Andreas Gruenbacher + return error; +} + ++static inline int aa_mask_permissions(int mask) ++{ ++ if (mask & MAY_APPEND) ++ mask &= (MAY_READ | MAY_APPEND | MAY_EXEC); ++ else ++ mask &= (MAY_READ | MAY_WRITE | MAY_EXEC); ++ return mask; ++} ++ +static int apparmor_inode_create(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mask) +{ -+ return aa_permission(dir, "inode_create", dentry, mnt, MAY_WRITE, 0); ++ /* FIXME: may move to MAY_APPEND later */ ++ return aa_permission("inode_create", dir, dentry, mnt, MAY_WRITE, 0); +} + +static int apparmor_inode_link(struct dentry *old_dentry, @@ -352,20 +362,20 @@ Signed-off-by: Andreas Gruenbacher + + if (S_ISDIR(dentry->d_inode->i_mode)) + check |= AA_CHECK_DIR; -+ return aa_permission(dir, "inode_unlink", dentry, mnt, MAY_WRITE, ++ return aa_permission("inode_unlink", dir, dentry, mnt, MAY_WRITE, + check); +} + +static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, const char *old_name) +{ -+ return aa_permission(dir, "inode_symlink", dentry, mnt, MAY_WRITE, 0); ++ return aa_permission("inode_symlink", dir, dentry, mnt, MAY_WRITE, 0); +} + +static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode, dev_t dev) +{ -+ return aa_permission(dir, "inode_mknod", dentry, mnt, MAY_WRITE, 0); ++ return aa_permission("inode_mknod", dir, dentry, mnt, MAY_WRITE, 0); +} + +static int apparmor_inode_rename(struct inode *old_dir, @@ -412,13 +422,13 @@ Signed-off-by: Andreas Gruenbacher + + if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE)) + return 0; -+ mask &= (MAY_READ | MAY_WRITE | MAY_EXEC); ++ mask = aa_mask_permissions(mask); + if (S_ISDIR(inode->i_mode)) { + check |= AA_CHECK_DIR; + /* allow traverse accesses to directories */ + mask &= ~MAY_EXEC; + } -+ return aa_permission(inode, "inode_permission", nd->dentry, nd->mnt, ++ return aa_permission("inode_permission", inode, nd->dentry, nd->mnt, + mask, check); +} + @@ -494,7 +504,7 @@ Signed-off-by: Andreas Gruenbacher + file); +} + -+static int apparmor_file_permission(struct file *file, int mask) ++static int aa_file_permission(const char *op, struct file *file, int mask) +{ + struct aa_profile *profile; + struct aa_profile *file_profile = (struct aa_profile*)file->f_security; @@ -508,7 +518,7 @@ Signed-off-by: Andreas Gruenbacher + * revalidate the access against the current profile. + */ + profile = aa_get_profile(current); -+ if (profile && file_profile != profile) { ++ if (profile && (file_profile != profile || mask & AA_MAY_LOCK)) { + struct dentry *dentry = file->f_dentry; + struct vfsmount *mnt = file->f_vfsmnt; + struct inode *inode = dentry->d_inode; @@ -520,9 +530,7 @@ Signed-off-by: Andreas Gruenbacher + */ + if (S_ISDIR(inode->i_mode)) + check |= AA_CHECK_DIR; -+ mask &= (MAY_READ | MAY_WRITE | MAY_EXEC); -+ error = aa_permission(inode, "file_permission", dentry, mnt, -+ mask, check); ++ error = aa_permission(op, inode, dentry, mnt, mask, check); + } + aa_put_profile(profile); + @@ -530,6 +538,20 @@ Signed-off-by: Andreas Gruenbacher + return error; +} + ++static int apparmor_file_permission(struct file *file, int mask) ++{ ++ return aa_file_permission("file_permission", file, ++ aa_mask_permissions(mask)); ++} ++ ++static inline int apparmor_file_lock (struct file *file, unsigned int cmd) ++{ ++ int mask = AA_MAY_LOCK; ++ if (cmd == F_WRLCK) ++ mask |= MAY_WRITE; ++ return aa_file_permission("file_lock", file, mask); ++} ++ +static int apparmor_file_alloc_security(struct file *file) +{ + struct aa_profile *profile; @@ -567,12 +589,13 @@ Signed-off-by: Andreas Gruenbacher + mask |= AA_EXEC_MMAP; + + dentry = file->f_dentry; -+ return aa_permission(dentry->d_inode, operation, dentry, ++ return aa_permission(operation, dentry->d_inode, dentry, + file->f_vfsmnt, mask, AA_CHECK_FD); +} + +static int apparmor_file_mmap(struct file *file, unsigned long reqprot, -+ unsigned long prot, unsigned long flags) ++ unsigned long prot, unsigned long flags, ++ unsigned long addr, unsigned long addr_only) +{ + return aa_mmap(file, "file_mmap", prot, flags); +} @@ -726,6 +749,7 @@ Signed-off-by: Andreas Gruenbacher + .file_free_security = apparmor_file_free_security, + .file_mmap = apparmor_file_mmap, + .file_mprotect = apparmor_file_mprotect, ++ .file_lock = apparmor_file_lock, + + .task_alloc_security = apparmor_task_alloc_security, + .task_free_security = apparmor_task_free_security, diff --git a/kernel-patches/for-mainline/apparmor-main.diff b/kernel-patches/for-mainline/apparmor-main.diff index 88230287b..280258296 100644 --- a/kernel-patches/for-mainline/apparmor-main.diff +++ b/kernel-patches/for-mainline/apparmor-main.diff @@ -7,12 +7,12 @@ Signed-off-by: John Johansen Signed-off-by: Andreas Gruenbacher --- - security/apparmor/main.c | 1246 +++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 1246 insertions(+) + security/apparmor/main.c | 1251 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 1251 insertions(+) --- /dev/null +++ b/security/apparmor/main.c -@@ -0,0 +1,1246 @@ +@@ -0,0 +1,1251 @@ +/* + * Copyright (C) 2002-2007 Novell/SUSE + * @@ -91,20 +91,21 @@ Signed-off-by: Andreas Gruenbacher + *request_mask = l_mode | AA_MAY_LINK; + + /* Link always requires 'l' on the link, a subset of the -+ * target's 'r', 'w', 'x', and 'm' permissions on the link, and -+ * if the link has 'x', an exact match of all the execute flags ++ * target's 'r', 'w', 'x', 'a', 'z', and 'm' permissions on the link, ++ * and if the link has 'x', an exact match of all the execute flags + * ('i', 'u', 'U', 'p', 'P'). + */ -+#define RWXM (MAY_READ | MAY_WRITE | MAY_EXEC | AA_EXEC_MMAP) ++#define RWXAZM (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND | AA_MAY_LOCK | \ ++ AA_EXEC_MMAP) + denied_mask = ~l_mode & AA_MAY_LINK; -+ if (l_mode & RWXM) ++ if (l_mode & RWXAZM) + denied_mask |= (l_mode & ~ AA_MAY_LINK) & ~t_mode; + else + denied_mask |= t_mode | AA_MAY_LINK; + if (denied_mask & AA_EXEC_MODIFIERS) + denied_mask |= MAY_EXEC; + -+#undef RWXM ++#undef RWXAZM + + return denied_mask; +} @@ -267,6 +268,8 @@ Signed-off-by: Andreas Gruenbacher + *m++ = 'r'; + if (mask & MAY_WRITE) + *m++ = 'w'; ++ else if (mask & MAY_APPEND) ++ *m++ = 'a'; + if (mask & (MAY_EXEC | AA_EXEC_MODIFIERS)) { + if (mask & AA_EXEC_UNSAFE) { + if (mask & AA_EXEC_INHERIT) @@ -288,6 +291,8 @@ Signed-off-by: Andreas Gruenbacher + } + if (mask & AA_MAY_LINK) + *m++ = 'l'; ++ if (mask & AA_MAY_LOCK) ++ *m++ = 'k'; + *m++ = '\0'; + + audit_log_format(ab, " %s=\"%s\"", name, mask_str); @@ -744,7 +749,7 @@ Signed-off-by: Andreas Gruenbacher + sa->denied_mask = MAY_EXEC; + if (complain) { + aa_audit_hint(profile, sa); -+ profile = aa_dup_profile(null_complain_profile); ++ new_profile = aa_dup_profile(null_complain_profile); + } else { + aa_audit_reject(profile, sa); + return ERR_PTR(-EACCES); /* was -EPERM */ diff --git a/kernel-patches/for-mainline/apparmor-misc.diff b/kernel-patches/for-mainline/apparmor-misc.diff index 9660a28e7..a5280dc60 100644 --- a/kernel-patches/for-mainline/apparmor-misc.diff +++ b/kernel-patches/for-mainline/apparmor-misc.diff @@ -13,13 +13,13 @@ Signed-off-by: Andreas Gruenbacher --- security/apparmor/Kconfig | 9 + security/apparmor/Makefile | 13 ++ - security/apparmor/apparmor.h | 254 +++++++++++++++++++++++++++++++++++++++++ + security/apparmor/apparmor.h | 257 +++++++++++++++++++++++++++++++++++++++++ security/apparmor/apparmorfs.c | 252 ++++++++++++++++++++++++++++++++++++++++ - security/apparmor/inline.h | 211 ++++++++++++++++++++++++++++++++++ - security/apparmor/list.c | 94 +++++++++++++++ + security/apparmor/inline.h | 211 +++++++++++++++++++++++++++++++++ + security/apparmor/list.c | 94 ++++++++++++++ security/apparmor/locking.txt | 68 ++++++++++ - security/apparmor/procattr.c | 155 +++++++++++++++++++++++++ - 8 files changed, 1056 insertions(+) + security/apparmor/procattr.c | 155 ++++++++++++++++++++++++ + 8 files changed, 1059 insertions(+) --- /dev/null +++ b/security/apparmor/Kconfig @@ -51,7 +51,7 @@ Signed-off-by: Andreas Gruenbacher + $(call cmd,make-caps) --- /dev/null +++ b/security/apparmor/apparmor.h -@@ -0,0 +1,254 @@ +@@ -0,0 +1,257 @@ +/* + * Copyright (C) 1998-2007 Novell/SUSE + * @@ -72,25 +72,28 @@ Signed-off-by: Andreas Gruenbacher +#include + +/* -+ * We use MAY_READ, MAY_WRITE, MAY_EXEC, and the following flags for -+ * profile permissions (we don't use MAY_APPEND): ++ * We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags ++ * for profile permissions + */ +#define AA_MAY_LINK 0x0010 -+#define AA_EXEC_INHERIT 0x0020 -+#define AA_EXEC_UNCONFINED 0x0040 -+#define AA_EXEC_PROFILE 0x0080 -+#define AA_EXEC_MMAP 0x0100 -+#define AA_EXEC_UNSAFE 0x0200 -+#define AA_CHANGE_PROFILE 0x40000000 ++#define AA_MAY_LOCK 0x0020 ++#define AA_EXEC_MMAP 0x0040 ++ ++#define AA_CHANGE_PROFILE 0x04000000 ++#define AA_EXEC_INHERIT 0x08000000 ++#define AA_EXEC_UNCONFINED 0x10000000 ++#define AA_EXEC_PROFILE 0x20000000 ++#define AA_EXEC_UNSAFE 0x40000000 + +#define AA_EXEC_MODIFIERS (AA_EXEC_INHERIT | \ + AA_EXEC_UNCONFINED | \ + AA_EXEC_PROFILE) + +#define AA_VALID_PERM_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | \ -+ AA_MAY_LINK | AA_EXEC_MODIFIERS | \ -+ AA_EXEC_MMAP | AA_EXEC_UNSAFE | \ -+ AA_CHANGE_PROFILE) ++ MAY_APPEND | AA_MAY_LINK | \ ++ AA_MAY_LOCK | \ ++ AA_EXEC_MODIFIERS | AA_EXEC_MMAP | \ ++ AA_EXEC_UNSAFE | AA_CHANGE_PROFILE) + +#define AA_SECURE_EXEC_NEEDED 1 + @@ -400,7 +403,7 @@ Signed-off-by: Andreas Gruenbacher +static ssize_t aa_matching_read(struct file *file, char __user *buf, + size_t size, loff_t *ppos) +{ -+ const char *matching = "pattern=aadfa"; ++ const char *matching = "pattern=aadfa perms=rwxamlz"; + + return simple_read_from_buffer(buf, size, ppos, matching, + strlen(matching)); diff --git a/kernel-patches/for-mainline/apparmor-module_interface.diff b/kernel-patches/for-mainline/apparmor-module_interface.diff index b65262e94..69b5c77b1 100644 --- a/kernel-patches/for-mainline/apparmor-module_interface.diff +++ b/kernel-patches/for-mainline/apparmor-module_interface.diff @@ -8,10 +8,10 @@ Signed-off-by: John Johansen Signed-off-by: Andreas Gruenbacher --- - security/apparmor/match.c | 248 ++++++++++++++ + security/apparmor/match.c | 248 +++++++++++++ security/apparmor/match.h | 83 ++++ - security/apparmor/module_interface.c | 589 +++++++++++++++++++++++++++++++++++ - 3 files changed, 920 insertions(+) + security/apparmor/module_interface.c | 623 +++++++++++++++++++++++++++++++++++ + 3 files changed, 954 insertions(+) --- /dev/null +++ b/security/apparmor/match.c @@ -352,7 +352,7 @@ Signed-off-by: Andreas Gruenbacher +#endif /* __MATCH_H */ --- /dev/null +++ b/security/apparmor/module_interface.c -@@ -0,0 +1,589 @@ +@@ -0,0 +1,623 @@ +/* + * Copyright (C) 1998-2007 Novell/SUSE + * @@ -399,6 +399,8 @@ Signed-off-by: Andreas Gruenbacher + AA_STRUCTEND, + AA_LIST, + AA_LISTEND, ++ AA_ARRAY, ++ AA_ARRAYEND, +}; + +/* @@ -497,6 +499,22 @@ Signed-off-by: Andreas Gruenbacher + return 0; +} + ++static int aa_is_u16(struct aa_ext *e, u16 *data, const char *name) ++{ ++ void *pos = e->pos; ++ if (aa_is_nameX(e, AA_U16, name)) { ++ if (!aa_inbounds(e, sizeof(u16))) ++ goto fail; ++ if (data) ++ *data = le16_to_cpu(get_unaligned((u16 *)e->pos)); ++ e->pos += sizeof(u16); ++ return 1; ++ } ++fail: ++ e->pos = pos; ++ return 0; ++} ++ +static int aa_is_u32(struct aa_ext *e, u32 *data, const char *name) +{ + void *pos = e->pos; @@ -513,6 +531,22 @@ Signed-off-by: Andreas Gruenbacher + return 0; +} + ++static size_t aa_is_array(struct aa_ext *e, const char *name) ++{ ++ void *pos = e->pos; ++ if (aa_is_nameX(e, AA_ARRAY, name)) { ++ int size; ++ if (!aa_inbounds(e, sizeof(u16))) ++ goto fail; ++ size = (int) le16_to_cpu(get_unaligned((u16 *)e->pos)); ++ e->pos += sizeof(u16); ++ return size; ++ } ++fail: ++ e->pos = pos; ++ return 0; ++} ++ +static size_t aa_is_blob(struct aa_ext *e, char **blob, const char *name) +{ + void *pos = e->pos; diff --git a/kernel-patches/for-mainline/apparmor-network.diff b/kernel-patches/for-mainline/apparmor-network.diff new file mode 100644 index 000000000..c33470ceb --- /dev/null +++ b/kernel-patches/for-mainline/apparmor-network.diff @@ -0,0 +1,399 @@ +--- + security/apparmor/Makefile | 7 + + security/apparmor/apparmor.h | 7 + + security/apparmor/lsm.c | 147 ++++++++++++++++++++++++++++++++++- + security/apparmor/main.c | 96 ++++++++++++++++++++++ + security/apparmor/module_interface.c | 20 ++++ + 5 files changed, 273 insertions(+), 4 deletions(-) + +--- a/security/apparmor/Makefile ++++ b/security/apparmor/Makefile +@@ -8,6 +8,11 @@ apparmor-y := main.o list.o procattr.o l + quiet_cmd_make-caps = GEN $@ + cmd_make-caps = sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@ + +-$(obj)/main.o : $(obj)/capability_names.h ++quiet_cmd_make-af = GEN $@ ++cmd_make-af = sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@ ++ ++$(obj)/main.o : $(obj)/capability_names.h $(obj)/af_names.h + $(obj)/capability_names.h : $(srctree)/include/linux/capability.h + $(call cmd,make-caps) ++$(obj)/af_names.h : $(srctree)/include/linux/socket.h ++ $(call cmd,make-af) +--- a/security/apparmor/apparmor.h ++++ b/security/apparmor/apparmor.h +@@ -16,6 +16,8 @@ + #include + #include + #include ++#include ++#include + + /* + * We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags +@@ -114,6 +116,7 @@ struct aa_profile { + struct list_head task_contexts; + spinlock_t lock; + unsigned long int_flags; ++ u16 network_families[AF_MAX]; + }; + + extern struct list_head profile_list; +@@ -159,6 +162,7 @@ struct aa_audit { + int requested_mask, denied_mask; + struct iattr *iattr; + pid_t task, parent; ++ int family, type, protocol; + int error_code; + }; + +@@ -223,6 +227,9 @@ extern void aa_change_task_context(struc + struct aa_profile *previous_profile); + extern int aa_may_ptrace(struct aa_task_context *cxt, + struct aa_profile *tracee); ++extern int aa_net_perm(struct aa_profile *profile, char *operation, ++ int family, int type, int protocol); ++extern int aa_revalidate_sk(struct sock *sk, char *operation); + + /* list.c */ + extern void aa_profilelist_release(void); +--- a/security/apparmor/lsm.c ++++ b/security/apparmor/lsm.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include "apparmor.h" + #include "inline.h" +@@ -605,6 +606,133 @@ static void apparmor_task_free_security( + aa_release(task); + } + ++static int apparmor_socket_create(int family, int type, int protocol, int kern) ++{ ++ struct aa_profile *profile; ++ int error = 0; ++ ++ if (kern) ++ return 0; ++ ++ profile = aa_get_profile(current); ++ if (profile) ++ error = aa_net_perm(profile, "socket_create", family, ++ type, protocol); ++ aa_put_profile(profile); ++ ++ return error; ++} ++ ++static int apparmor_socket_post_create(struct socket * sock, int family, ++ int type, int protocol, int kern) ++{ ++ struct sock *sk = sock->sk; ++ ++ if (kern) ++ return 0; ++ ++ return aa_revalidate_sk(sk, "socket_post_create"); ++} ++ ++static int apparmor_socket_bind(struct socket * sock, ++ struct sockaddr * address, int addrlen) ++{ ++ struct sock *sk = sock->sk; ++ ++ return aa_revalidate_sk(sk, "socket_bind"); ++} ++ ++static int apparmor_socket_connect(struct socket * sock, ++ struct sockaddr * address, int addrlen) ++{ ++ struct sock *sk = sock->sk; ++ ++ return aa_revalidate_sk(sk, "socket_connect"); ++} ++ ++static int apparmor_socket_listen(struct socket * sock, int backlog) ++{ ++ struct sock *sk = sock->sk; ++ ++ return aa_revalidate_sk(sk, "socket_listen"); ++} ++ ++static int apparmor_socket_accept(struct socket * sock, struct socket * newsock) ++{ ++ struct sock *sk = sock->sk; ++ ++ return aa_revalidate_sk(sk, "socket_accept"); ++} ++ ++static int apparmor_socket_sendmsg(struct socket * sock, ++ struct msghdr * msg, int size) ++{ ++ struct sock *sk = sock->sk; ++ ++ return aa_revalidate_sk(sk, "socket_sendmsg"); ++} ++ ++static int apparmor_socket_recvmsg(struct socket * sock, ++ struct msghdr * msg, int size, int flags) ++{ ++ struct sock *sk = sock->sk; ++ ++ return aa_revalidate_sk(sk, "socket_recvmsg"); ++} ++ ++static int apparmor_socket_getsockname(struct socket * sock) ++{ ++ struct sock *sk = sock->sk; ++ ++ return aa_revalidate_sk(sk, "socket_getsockname"); ++} ++ ++static int apparmor_socket_getpeername(struct socket * sock) ++{ ++ struct sock *sk = sock->sk; ++ ++ return aa_revalidate_sk(sk, "socket_getpeername"); ++} ++ ++static int apparmor_socket_getsockopt(struct socket * sock, int level, ++ int optname) ++{ ++ struct sock *sk = sock->sk; ++ ++ return aa_revalidate_sk(sk, "socket_getsockopt"); ++} ++ ++static int apparmor_socket_setsockopt(struct socket * sock, int level, ++ int optname) ++{ ++ struct sock *sk = sock->sk; ++ ++ return aa_revalidate_sk(sk, "socket_setsockopt"); ++} ++ ++static int apparmor_socket_shutdown(struct socket * sock, int how) ++{ ++ struct sock *sk = sock->sk; ++ ++ return aa_revalidate_sk(sk, "socket_shutdown"); ++} ++ ++static int apparmor_socket_getpeersec_stream(struct socket *sock, ++ char __user *optval, int __user *optlen, unsigned len) ++{ ++ struct sock *sk = sock->sk; ++ ++ return aa_revalidate_sk(sk, "socket_getpeersec_stream"); ++} ++ ++static int apparmor_socket_getpeersec_dgram(struct socket *sock, ++ struct sk_buff *skb, u32 *secid) ++{ ++ struct sock *sk = sock->sk; ++ ++ return aa_revalidate_sk(sk, "socket_getpeersec_dgram"); ++} ++ + static int apparmor_getprocattr(struct task_struct *task, char *name, + char **value) + { +@@ -705,9 +833,6 @@ struct security_operations apparmor_ops + .capable = apparmor_capable, + .syslog = cap_syslog, + +- .netlink_send = cap_netlink_send, +- .netlink_recv = cap_netlink_recv, +- + .bprm_apply_creds = cap_bprm_apply_creds, + .bprm_set_security = apparmor_bprm_set_security, + .bprm_secureexec = apparmor_bprm_secureexec, +@@ -743,6 +868,22 @@ struct security_operations apparmor_ops + + .getprocattr = apparmor_getprocattr, + .setprocattr = apparmor_setprocattr, ++ ++ .socket_create = apparmor_socket_create, ++ .socket_post_create = apparmor_socket_post_create, ++ .socket_bind = apparmor_socket_bind, ++ .socket_connect = apparmor_socket_connect, ++ .socket_listen = apparmor_socket_listen, ++ .socket_accept = apparmor_socket_accept, ++ .socket_sendmsg = apparmor_socket_sendmsg, ++ .socket_recvmsg = apparmor_socket_recvmsg, ++ .socket_getsockname = apparmor_socket_getsockname, ++ .socket_getpeername = apparmor_socket_getpeername, ++ .socket_getsockopt = apparmor_socket_getsockopt, ++ .socket_setsockopt = apparmor_socket_setsockopt, ++ .socket_shutdown = apparmor_socket_shutdown, ++ .socket_getpeersec_stream = apparmor_socket_getpeersec_stream, ++ .socket_getpeersec_dgram = apparmor_socket_getpeersec_dgram, + }; + + static void info_message(const char *str) +--- a/security/apparmor/main.c ++++ b/security/apparmor/main.c +@@ -14,6 +14,9 @@ + #include + #include + #include ++#include ++#include ++#include + + #include "apparmor.h" + +@@ -283,6 +286,24 @@ static void aa_audit_file_mask(struct au + audit_log_format(ab, " %s=\"%s\"", name, mask_str); + } + ++static const char *address_families[] = { ++#include "af_names.h" ++}; ++ ++static const char *sock_types[] = { ++ "unknown(0)", ++ "stream", ++ "dgram", ++ "raw", ++ "rdm", ++ "seqpacket", ++ "dccp", ++ "unknown(7)", ++ "unknown(8)", ++ "unknown(9)", ++ "packet", ++}; ++ + /** + * aa_audit - Log an audit event to the audit subsystem + * @profile: profile to check against +@@ -348,6 +369,24 @@ static int aa_audit_base(struct aa_profi + audit_log_untrustedstring(ab, sa->name2); + } + ++ if (sa->family || sa->type) { ++ if (address_families[sa->family]) ++ audit_log_format(ab, " family=\"%s\"", ++ address_families[sa->family]); ++ else ++ audit_log_format(ab, " family=\"unknown(%d)\"", ++ sa->family); ++ ++ if (sock_types[sa->type]) ++ audit_log_format(ab, " sock_type=\"%s\"", ++ sock_types[sa->type]); ++ else ++ audit_log_format(ab, " sock_type=\"unknown(%d)\"", ++ sa->type); ++ ++ audit_log_format(ab, " protocol=%d", sa->protocol); ++ } ++ + audit_log_format(ab, " pid=%d", current->pid); + + if (profile) { +@@ -660,6 +699,63 @@ int aa_link(struct aa_profile *profile, + return error; + } + ++int aa_net_perm(struct aa_profile *profile, char *operation, ++ int family, int type, int protocol) ++{ ++ struct aa_audit sa; ++ int error = 0; ++ u16 family_mask; ++ ++ if ((family < 0) || (family >= AF_MAX)) ++ return -EINVAL; ++ ++ if ((type < 0) || (type >= SOCK_MAX)) ++ return -EINVAL; ++ ++ /* unix domain and netlink sockets are handled by ipc */ ++ if (family == AF_UNIX || family == AF_NETLINK) ++ return 0; ++ ++ family_mask = profile->network_families[family]; ++ ++ error = (family_mask & (1 << type)) ? 0 : -EACCES; ++ ++ memset(&sa, 0, sizeof(sa)); ++ sa.operation = operation; ++ sa.gfp_mask = GFP_KERNEL; ++ sa.family = family; ++ sa.type = type; ++ sa.protocol = protocol; ++ sa.error_code = error; ++ ++ error = aa_audit(profile, &sa); ++ ++ return error; ++} ++ ++int aa_revalidate_sk(struct sock *sk, char *operation) ++{ ++ struct aa_profile *profile; ++ int error = 0; ++ ++ /* this is some debugging code to flush out the network hooks that ++ that are called in interrupt context */ ++ if (in_interrupt()) { ++ printk("AppArmor Debug: Hook being called from interrupt context\n"); ++ dump_stack(); ++ return 0; ++ } ++ ++ profile = aa_get_profile(current); ++ if (profile) ++ error = aa_net_perm(profile, operation, ++ sk->sk_family, sk->sk_type, ++ sk->sk_protocol); ++ aa_put_profile(profile); ++ ++ return error; ++} ++ + /******************************* + * Global task related functions + *******************************/ +--- a/security/apparmor/module_interface.c ++++ b/security/apparmor/module_interface.c +@@ -282,6 +282,8 @@ static struct aa_profile *aa_unpack_prof + { + struct aa_profile *profile = NULL; + struct aa_audit sa; ++ size_t size = 0; ++ int i; + + int error = -EPROTO; + +@@ -310,6 +312,24 @@ static struct aa_profile *aa_unpack_prof + if (!aa_is_u32(e, &(profile->capabilities), NULL)) + goto fail; + ++ size = aa_is_array(e, "net_allowed_af"); ++ if (size) { ++ if (size > AF_MAX) ++ goto fail; ++ ++ for (i = 0; i < size; i++) { ++ if (!aa_is_u16(e, &profile->network_families[i], NULL)) ++ goto fail; ++ } ++ if (!aa_is_nameX(e, AA_ARRAYEND, NULL)) ++ goto fail; ++ /* allow unix domain and netlink sockets they are handled ++ * by IPC ++ */ ++ } ++ profile->network_families[AF_UNIX] = 0xffff; ++ profile->network_families[AF_NETLINK] = 0xffff; ++ + /* get file rules */ + profile->file_rules = aa_unpack_dfa(e); + if (IS_ERR(profile->file_rules)) { diff --git a/kernel-patches/for-mainline/series b/kernel-patches/for-mainline/series index c13ca13d8..e43e8142c 100644 --- a/kernel-patches/for-mainline/series +++ b/kernel-patches/for-mainline/series @@ -40,6 +40,7 @@ apparmor-lsm.diff apparmor-module_interface.diff apparmor-misc.diff apparmor-intree.diff +apparmor-network.diff do_path_lookup-nameidata.diff sys_fchdir-nameidata.diff file_permission-nameidata.diff