- lock
- null-complain-profile on missing mandatory profile bug
- parameter cleanup
- network mediation patch
This commit is contained in:
John Johansen 2007-07-27 20:20:50 +00:00
parent b2c6ec5b57
commit 17ff3b0f58
7 changed files with 518 additions and 52 deletions

View file

@ -27,7 +27,7 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
* 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 <jjohansen@suse.de>
#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 <jjohansen@suse.de>
__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 <jjohansen@suse.de>
{
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);

View file

@ -7,12 +7,12 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
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 <agruen@suse.de>
+ 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 <agruen@suse.de>
+ 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 <agruen@suse.de>
+
+ 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 <agruen@suse.de>
+
+ 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 <agruen@suse.de>
+ 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 <agruen@suse.de>
+ * 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 <agruen@suse.de>
+ */
+ 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 <agruen@suse.de>
+ 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 <agruen@suse.de>
+ 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 <agruen@suse.de>
+ .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,

View file

@ -7,12 +7,12 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
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 <agruen@suse.de>
+ *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 <agruen@suse.de>
+ *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 <agruen@suse.de>
+ }
+ 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 <agruen@suse.de>
+ 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 */

View file

@ -13,13 +13,13 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
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 <agruen@suse.de>
+ $(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 <agruen@suse.de>
+#include <linux/rcupdate.h>
+
+/*
+ * 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 <agruen@suse.de>
+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));

View file

@ -8,10 +8,10 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
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 <agruen@suse.de>
+#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 <agruen@suse.de>
+ AA_STRUCTEND,
+ AA_LIST,
+ AA_LISTEND,
+ AA_ARRAY,
+ AA_ARRAYEND,
+};
+
+/*
@ -497,6 +499,22 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ 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 <agruen@suse.de>
+ 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;

View file

@ -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 <linux/fs.h>
#include <linux/binfmts.h>
#include <linux/rcupdate.h>
+#include <linux/socket.h>
+#include <net/sock.h>
/*
* 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 <linux/ctype.h>
#include <linux/sysctl.h>
#include <linux/audit.h>
+#include <net/sock.h>
#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 <linux/audit.h>
#include <linux/mount.h>
#include <linux/ptrace.h>
+#include <linux/socket.h>
+#include <linux/net.h>
+#include <net/sock.h>
#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)) {

View file

@ -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