mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
- append
- lock - null-complain-profile on missing mandatory profile bug - parameter cleanup - network mediation patch
This commit is contained in:
parent
b2c6ec5b57
commit
17ff3b0f58
7 changed files with 518 additions and 52 deletions
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
399
kernel-patches/for-mainline/apparmor-network.diff
Normal file
399
kernel-patches/for-mainline/apparmor-network.diff
Normal 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)) {
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue