mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-03 15:55:46 +00:00
Fold patches, and remove obsolete ones.
This commit is contained in:
@@ -5,9 +5,10 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
|
|||||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||||
|
|
||||||
---
|
---
|
||||||
security/Kconfig | 1 +
|
security/Kconfig | 1 +
|
||||||
security/Makefile | 1 +
|
security/Makefile | 1 +
|
||||||
2 files changed, 2 insertions(+)
|
security/apparmor/Kconfig | 3 ++-
|
||||||
|
3 files changed, 4 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
--- a/security/Kconfig
|
--- a/security/Kconfig
|
||||||
+++ b/security/Kconfig
|
+++ b/security/Kconfig
|
||||||
@@ -28,3 +29,14 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+obj-$(CONFIG_SECURITY_APPARMOR) += commoncap.o apparmor/
|
+obj-$(CONFIG_SECURITY_APPARMOR) += commoncap.o apparmor/
|
||||||
obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
|
obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
|
||||||
obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o
|
obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o
|
||||||
|
--- a/security/apparmor/Kconfig
|
||||||
|
+++ b/security/apparmor/Kconfig
|
||||||
|
@@ -1,6 +1,7 @@
|
||||||
|
config SECURITY_APPARMOR
|
||||||
|
tristate "AppArmor support"
|
||||||
|
- depends on SECURITY!=n
|
||||||
|
+ depends on SECURITY
|
||||||
|
+ select AUDIT
|
||||||
|
help
|
||||||
|
This enables the AppArmor security module.
|
||||||
|
Required userspace tools (if they are not included in your
|
||||||
|
@@ -1,118 +0,0 @@
|
|||||||
---
|
|
||||||
security/apparmor/lsm.c | 73 +++++-------------------------------------------
|
|
||||||
1 file changed, 9 insertions(+), 64 deletions(-)
|
|
||||||
|
|
||||||
--- a/security/apparmor/lsm.c
|
|
||||||
+++ b/security/apparmor/lsm.c
|
|
||||||
@@ -133,30 +133,6 @@ static int apparmor_ptrace(struct task_s
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int apparmor_capget(struct task_struct *task,
|
|
||||||
- kernel_cap_t *effective,
|
|
||||||
- kernel_cap_t *inheritable,
|
|
||||||
- kernel_cap_t *permitted)
|
|
||||||
-{
|
|
||||||
- return cap_capget(task, effective, inheritable, permitted);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static int apparmor_capset_check(struct task_struct *task,
|
|
||||||
- kernel_cap_t *effective,
|
|
||||||
- kernel_cap_t *inheritable,
|
|
||||||
- kernel_cap_t *permitted)
|
|
||||||
-{
|
|
||||||
- return cap_capset_check(task, effective, inheritable, permitted);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static void apparmor_capset_set(struct task_struct *task,
|
|
||||||
- kernel_cap_t *effective,
|
|
||||||
- kernel_cap_t *inheritable,
|
|
||||||
- kernel_cap_t *permitted)
|
|
||||||
-{
|
|
||||||
- cap_capset_set(task, effective, inheritable, permitted);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static int apparmor_capable(struct task_struct *task, int cap)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
@@ -188,26 +164,6 @@ static int apparmor_sysctl(struct ctl_ta
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int apparmor_syslog(int type)
|
|
||||||
-{
|
|
||||||
- return cap_syslog(type);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static int apparmor_netlink_send(struct sock *sk, struct sk_buff *skb)
|
|
||||||
-{
|
|
||||||
- return cap_netlink_send(sk, skb);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static int apparmor_netlink_recv(struct sk_buff *skb, int cap)
|
|
||||||
-{
|
|
||||||
- return cap_netlink_recv(skb, cap);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static void apparmor_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
|
|
||||||
-{
|
|
||||||
- cap_bprm_apply_creds(bprm, unsafe);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static int apparmor_bprm_set_security(struct linux_binprm *bprm)
|
|
||||||
{
|
|
||||||
/* handle capability bits with setuid, etc */
|
|
||||||
@@ -594,17 +550,6 @@ static void apparmor_task_free_security(
|
|
||||||
aa_release(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int apparmor_task_post_setuid(uid_t id0, uid_t id1, uid_t id2,
|
|
||||||
- int flags)
|
|
||||||
-{
|
|
||||||
- return cap_task_post_setuid(id0, id1, id2, flags);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static void apparmor_task_reparent_to_init(struct task_struct *task)
|
|
||||||
-{
|
|
||||||
- cap_task_reparent_to_init(task);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static int apparmor_getprocattr(struct task_struct *task, char *name,
|
|
||||||
char **value)
|
|
||||||
{
|
|
||||||
@@ -696,17 +641,17 @@ static int apparmor_setprocattr(struct t
|
|
||||||
|
|
||||||
struct security_operations apparmor_ops = {
|
|
||||||
.ptrace = apparmor_ptrace,
|
|
||||||
- .capget = apparmor_capget,
|
|
||||||
- .capset_check = apparmor_capset_check,
|
|
||||||
- .capset_set = apparmor_capset_set,
|
|
||||||
+ .capget = cap_capget,
|
|
||||||
+ .capset_check = cap_capset_check,
|
|
||||||
+ .capset_set = cap_capset_set,
|
|
||||||
.sysctl = apparmor_sysctl,
|
|
||||||
.capable = apparmor_capable,
|
|
||||||
- .syslog = apparmor_syslog,
|
|
||||||
+ .syslog = cap_syslog,
|
|
||||||
|
|
||||||
- .netlink_send = apparmor_netlink_send,
|
|
||||||
- .netlink_recv = apparmor_netlink_recv,
|
|
||||||
+ .netlink_send = cap_netlink_send,
|
|
||||||
+ .netlink_recv = cap_netlink_recv,
|
|
||||||
|
|
||||||
- .bprm_apply_creds = apparmor_bprm_apply_creds,
|
|
||||||
+ .bprm_apply_creds = cap_bprm_apply_creds,
|
|
||||||
.bprm_set_security = apparmor_bprm_set_security,
|
|
||||||
.bprm_secureexec = apparmor_bprm_secureexec,
|
|
||||||
|
|
||||||
@@ -736,8 +681,8 @@ struct security_operations apparmor_ops
|
|
||||||
.task_create = apparmor_task_create,
|
|
||||||
.task_alloc_security = apparmor_task_alloc_security,
|
|
||||||
.task_free_security = apparmor_task_free_security,
|
|
||||||
- .task_post_setuid = apparmor_task_post_setuid,
|
|
||||||
- .task_reparent_to_init = apparmor_task_reparent_to_init,
|
|
||||||
+ .task_post_setuid = cap_task_post_setuid,
|
|
||||||
+ .task_reparent_to_init = cap_task_reparent_to_init,
|
|
||||||
|
|
||||||
.getprocattr = apparmor_getprocattr,
|
|
||||||
.setprocattr = apparmor_setprocattr,
|
|
@@ -7,12 +7,12 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
|
|||||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||||
|
|
||||||
---
|
---
|
||||||
security/apparmor/lsm.c | 828 ++++++++++++++++++++++++++++++++++++++++++++++++
|
security/apparmor/lsm.c | 762 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
1 file changed, 828 insertions(+)
|
1 file changed, 762 insertions(+)
|
||||||
|
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/security/apparmor/lsm.c
|
+++ b/security/apparmor/lsm.c
|
||||||
@@ -0,0 +1,828 @@
|
@@ -0,0 +1,762 @@
|
||||||
+/*
|
+/*
|
||||||
+ * Copyright (C) 1998-2007 Novell/SUSE
|
+ * Copyright (C) 1998-2007 Novell/SUSE
|
||||||
+ *
|
+ *
|
||||||
@@ -129,49 +129,34 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ /**
|
+ /**
|
||||||
+ * parent can ptrace child when
|
+ * parent can ptrace child when
|
||||||
+ * - parent is unconfined
|
+ * - parent is unconfined
|
||||||
+ * - parent is in complain mode
|
+ * - parent & child are in the same namespace &&
|
||||||
+ * - parent and child are confined by the same profile
|
+ * - parent is in complain mode
|
||||||
|
+ * - parent and child are confined by the same profile
|
||||||
|
+ * - parent profile has CAP_SYS_PTRACE
|
||||||
+ */
|
+ */
|
||||||
+
|
+
|
||||||
+ rcu_read_lock();
|
+ rcu_read_lock();
|
||||||
+ cxt = aa_task_context(parent);
|
+ cxt = aa_task_context(parent);
|
||||||
+ child_cxt = aa_task_context(child);
|
+ child_cxt = aa_task_context(child);
|
||||||
+ child_profile = child_cxt ? child_cxt->profile : NULL;
|
+ child_profile = child_cxt ? child_cxt->profile : NULL;
|
||||||
+ error = aa_may_ptrace(cxt, child_profile);
|
+ if (cxt && (parent->nsproxy != child->nsproxy)) {
|
||||||
+ if (cxt && PROFILE_COMPLAIN(cxt->profile)) {
|
+ AA_WARN(GFP_ATOMIC,
|
||||||
+ LOG_HINT(cxt->profile, GFP_ATOMIC, HINT_PTRACE,
|
+ "REJECTING ptrace across namespace of %d by %d",
|
||||||
|
+ parent->pid, child->pid);
|
||||||
|
+ error = -EPERM;
|
||||||
|
+ } else {
|
||||||
|
+ error = aa_may_ptrace(cxt, child_profile);
|
||||||
|
+ if (cxt && PROFILE_COMPLAIN(cxt->profile)) {
|
||||||
|
+ LOG_HINT(cxt->profile, GFP_ATOMIC, HINT_PTRACE,
|
||||||
+ "pid=%d child=%d\n",
|
+ "pid=%d child=%d\n",
|
||||||
+ current->pid, child->pid);
|
+ current->pid, child->pid);
|
||||||
+ }
|
+ }
|
||||||
|
+ }
|
||||||
+ rcu_read_unlock();
|
+ rcu_read_unlock();
|
||||||
+
|
+
|
||||||
+ return error;
|
+ return error;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int apparmor_capget(struct task_struct *task,
|
|
||||||
+ kernel_cap_t *effective,
|
|
||||||
+ kernel_cap_t *inheritable,
|
|
||||||
+ kernel_cap_t *permitted)
|
|
||||||
+{
|
|
||||||
+ return cap_capget(task, effective, inheritable, permitted);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int apparmor_capset_check(struct task_struct *task,
|
|
||||||
+ kernel_cap_t *effective,
|
|
||||||
+ kernel_cap_t *inheritable,
|
|
||||||
+ kernel_cap_t *permitted)
|
|
||||||
+{
|
|
||||||
+ return cap_capset_check(task, effective, inheritable, permitted);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void apparmor_capset_set(struct task_struct *task,
|
|
||||||
+ kernel_cap_t *effective,
|
|
||||||
+ kernel_cap_t *inheritable,
|
|
||||||
+ kernel_cap_t *permitted)
|
|
||||||
+{
|
|
||||||
+ cap_capset_set(task, effective, inheritable, permitted);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int apparmor_capable(struct task_struct *task, int cap)
|
+static int apparmor_capable(struct task_struct *task, int cap)
|
||||||
+{
|
+{
|
||||||
+ int error;
|
+ int error;
|
||||||
@@ -203,26 +188,6 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ return error;
|
+ return error;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int apparmor_syslog(int type)
|
|
||||||
+{
|
|
||||||
+ return cap_syslog(type);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int apparmor_netlink_send(struct sock *sk, struct sk_buff *skb)
|
|
||||||
+{
|
|
||||||
+ return cap_netlink_send(sk, skb);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int apparmor_netlink_recv(struct sk_buff *skb, int cap)
|
|
||||||
+{
|
|
||||||
+ return cap_netlink_recv(skb, cap);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void apparmor_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
|
|
||||||
+{
|
|
||||||
+ cap_bprm_apply_creds(bprm, unsafe);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int apparmor_bprm_set_security(struct linux_binprm *bprm)
|
+static int apparmor_bprm_set_security(struct linux_binprm *bprm)
|
||||||
+{
|
+{
|
||||||
+ /* handle capability bits with setuid, etc */
|
+ /* handle capability bits with setuid, etc */
|
||||||
@@ -443,8 +408,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
|
+static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
|
||||||
+ const char *name, const char *operation,
|
+ const char *operation, int mask,
|
||||||
+ int mask, struct file *file)
|
+ struct file *file)
|
||||||
+{
|
+{
|
||||||
+ int error = 0;
|
+ int error = 0;
|
||||||
+
|
+
|
||||||
@@ -453,8 +418,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ int check = file ? AA_CHECK_FD : 0;
|
+ int check = file ? AA_CHECK_FD : 0;
|
||||||
+
|
+
|
||||||
+ if (profile)
|
+ if (profile)
|
||||||
+ error = aa_perm_xattr(profile, dentry, mnt, name,
|
+ error = aa_perm_xattr(profile, dentry, mnt, operation,
|
||||||
+ operation, mask, check);
|
+ mask, check);
|
||||||
+ aa_put_profile(profile);
|
+ aa_put_profile(profile);
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
@@ -465,30 +430,27 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ char *name, void *value, size_t size,
|
+ char *name, void *value, size_t size,
|
||||||
+ int flags, struct file *file)
|
+ int flags, struct file *file)
|
||||||
+{
|
+{
|
||||||
+ return aa_xattr_permission(dentry, mnt, name, "xattr set", MAY_WRITE,
|
+ return aa_xattr_permission(dentry, mnt, "xattr set", MAY_WRITE, file);
|
||||||
+ file);
|
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
+static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||||
+ char *name, struct file *file)
|
+ char *name, struct file *file)
|
||||||
+{
|
+{
|
||||||
+ return aa_xattr_permission(dentry, mnt, name, "xattr get", MAY_READ,
|
+ return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
|
||||||
+ file);
|
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
|
+static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||||
+ struct file *file)
|
+ struct file *file)
|
||||||
+{
|
+{
|
||||||
+ return aa_xattr_permission(dentry, mnt, NULL, "xattr list", MAY_READ,
|
+ return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
|
||||||
+ file);
|
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int apparmor_inode_removexattr(struct dentry *dentry,
|
+static int apparmor_inode_removexattr(struct dentry *dentry,
|
||||||
+ struct vfsmount *mnt, char *name,
|
+ struct vfsmount *mnt, char *name,
|
||||||
+ struct file *file)
|
+ struct file *file)
|
||||||
+{
|
+{
|
||||||
+ return aa_xattr_permission(dentry, mnt, name, "xattr remove",
|
+ return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
|
||||||
+ MAY_WRITE, file);
|
+ file);
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int apparmor_file_permission(struct file *file, int mask)
|
+static int apparmor_file_permission(struct file *file, int mask)
|
||||||
@@ -526,22 +488,6 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ return error;
|
+ return error;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int apparmor_task_create(unsigned long clone_flags)
|
|
||||||
+{
|
|
||||||
+ struct aa_profile *profile;
|
|
||||||
+ int error = 0;
|
|
||||||
+
|
|
||||||
+ profile = aa_get_profile(current);
|
|
||||||
+ if (profile) {
|
|
||||||
+ /* Don't allow to create new namespaces. */
|
|
||||||
+ if (clone_flags & CLONE_NEWNS)
|
|
||||||
+ error = -EPERM;
|
|
||||||
+ }
|
|
||||||
+ aa_put_profile(profile);
|
|
||||||
+
|
|
||||||
+ return error;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int apparmor_file_alloc_security(struct file *file)
|
+static int apparmor_file_alloc_security(struct file *file)
|
||||||
+{
|
+{
|
||||||
+ struct aa_profile *profile;
|
+ struct aa_profile *profile;
|
||||||
@@ -609,17 +555,6 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ aa_release(task);
|
+ aa_release(task);
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int apparmor_task_post_setuid(uid_t id0, uid_t id1, uid_t id2,
|
|
||||||
+ int flags)
|
|
||||||
+{
|
|
||||||
+ return cap_task_post_setuid(id0, id1, id2, flags);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void apparmor_task_reparent_to_init(struct task_struct *task)
|
|
||||||
+{
|
|
||||||
+ cap_task_reparent_to_init(task);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int apparmor_getprocattr(struct task_struct *task, char *name,
|
+static int apparmor_getprocattr(struct task_struct *task, char *name,
|
||||||
+ char **value)
|
+ char **value)
|
||||||
+{
|
+{
|
||||||
@@ -711,17 +646,17 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+
|
+
|
||||||
+struct security_operations apparmor_ops = {
|
+struct security_operations apparmor_ops = {
|
||||||
+ .ptrace = apparmor_ptrace,
|
+ .ptrace = apparmor_ptrace,
|
||||||
+ .capget = apparmor_capget,
|
+ .capget = cap_capget,
|
||||||
+ .capset_check = apparmor_capset_check,
|
+ .capset_check = cap_capset_check,
|
||||||
+ .capset_set = apparmor_capset_set,
|
+ .capset_set = cap_capset_set,
|
||||||
+ .sysctl = apparmor_sysctl,
|
+ .sysctl = apparmor_sysctl,
|
||||||
+ .capable = apparmor_capable,
|
+ .capable = apparmor_capable,
|
||||||
+ .syslog = apparmor_syslog,
|
+ .syslog = cap_syslog,
|
||||||
+
|
+
|
||||||
+ .netlink_send = apparmor_netlink_send,
|
+ .netlink_send = cap_netlink_send,
|
||||||
+ .netlink_recv = apparmor_netlink_recv,
|
+ .netlink_recv = cap_netlink_recv,
|
||||||
+
|
+
|
||||||
+ .bprm_apply_creds = apparmor_bprm_apply_creds,
|
+ .bprm_apply_creds = cap_bprm_apply_creds,
|
||||||
+ .bprm_set_security = apparmor_bprm_set_security,
|
+ .bprm_set_security = apparmor_bprm_set_security,
|
||||||
+ .bprm_secureexec = apparmor_bprm_secureexec,
|
+ .bprm_secureexec = apparmor_bprm_secureexec,
|
||||||
+
|
+
|
||||||
@@ -748,11 +683,10 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ .file_mmap = apparmor_file_mmap,
|
+ .file_mmap = apparmor_file_mmap,
|
||||||
+ .file_mprotect = apparmor_file_mprotect,
|
+ .file_mprotect = apparmor_file_mprotect,
|
||||||
+
|
+
|
||||||
+ .task_create = apparmor_task_create,
|
|
||||||
+ .task_alloc_security = apparmor_task_alloc_security,
|
+ .task_alloc_security = apparmor_task_alloc_security,
|
||||||
+ .task_free_security = apparmor_task_free_security,
|
+ .task_free_security = apparmor_task_free_security,
|
||||||
+ .task_post_setuid = apparmor_task_post_setuid,
|
+ .task_post_setuid = cap_task_post_setuid,
|
||||||
+ .task_reparent_to_init = apparmor_task_reparent_to_init,
|
+ .task_reparent_to_init = cap_task_reparent_to_init,
|
||||||
+
|
+
|
||||||
+ .getprocattr = apparmor_getprocattr,
|
+ .getprocattr = apparmor_getprocattr,
|
||||||
+ .setprocattr = apparmor_setprocattr,
|
+ .setprocattr = apparmor_setprocattr,
|
||||||
|
@@ -1,54 +0,0 @@
|
|||||||
From: Andreas Gruenbacher <agruen@suse.de>
|
|
||||||
Subject: Get rid of aa_taskattr_access
|
|
||||||
|
|
||||||
---
|
|
||||||
security/apparmor/main.c | 31 +------------------------------
|
|
||||||
1 file changed, 1 insertion(+), 30 deletions(-)
|
|
||||||
|
|
||||||
--- a/security/apparmor/main.c
|
|
||||||
+++ b/security/apparmor/main.c
|
|
||||||
@@ -38,27 +38,6 @@ static const char *capability_names[] =
|
|
||||||
*/
|
|
||||||
struct aa_profile *null_complain_profile;
|
|
||||||
|
|
||||||
-/**
|
|
||||||
- * aa_taskattr_access
|
|
||||||
- * @name: name of the file to check
|
|
||||||
- *
|
|
||||||
- * Check if name matches /proc/self/attr/current, with self resolved
|
|
||||||
- * to the current pid. This file is the usermode interface for
|
|
||||||
- * changing one's hat.
|
|
||||||
- */
|
|
||||||
-static inline int aa_taskattr_access(const char *name)
|
|
||||||
-{
|
|
||||||
- unsigned long pid;
|
|
||||||
- char *end;
|
|
||||||
-
|
|
||||||
- if (strncmp(name, "/proc/", 6) != 0)
|
|
||||||
- return 0;
|
|
||||||
- pid = simple_strtoul(name + 6, &end, 10);
|
|
||||||
- if (pid != current->pid)
|
|
||||||
- return 0;
|
|
||||||
- return strcmp(end, "/attr/current") == 0;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static inline void aa_permerror2result(int perm_result, struct aa_audit *sa)
|
|
||||||
{
|
|
||||||
if (perm_result == 0) { /* success */
|
|
||||||
@@ -82,15 +61,7 @@ static inline void aa_permerror2result(i
|
|
||||||
static int aa_file_denied(struct aa_profile *profile, const char *name,
|
|
||||||
int mask)
|
|
||||||
{
|
|
||||||
- int perms;
|
|
||||||
-
|
|
||||||
- /* Always allow write access to /proc/self/attr/current. */
|
|
||||||
- if (mask == MAY_WRITE && aa_taskattr_access(name))
|
|
||||||
- return 0;
|
|
||||||
-
|
|
||||||
- perms = aa_match(profile->file_rules, name);
|
|
||||||
-
|
|
||||||
- return (mask & ~perms);
|
|
||||||
+ return (mask & ~aa_match(profile->file_rules, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
@@ -7,12 +7,12 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
|
|||||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||||
|
|
||||||
---
|
---
|
||||||
security/apparmor/main.c | 1321 +++++++++++++++++++++++++++++++++++++++++++++++
|
security/apparmor/main.c | 1340 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
1 file changed, 1321 insertions(+)
|
1 file changed, 1340 insertions(+)
|
||||||
|
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/security/apparmor/main.c
|
+++ b/security/apparmor/main.c
|
||||||
@@ -0,0 +1,1321 @@
|
@@ -0,0 +1,1340 @@
|
||||||
+/*
|
+/*
|
||||||
+ * Copyright (C) 2002-2007 Novell/SUSE
|
+ * Copyright (C) 2002-2007 Novell/SUSE
|
||||||
+ *
|
+ *
|
||||||
@@ -53,27 +53,6 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ */
|
+ */
|
||||||
+struct aa_profile *null_complain_profile;
|
+struct aa_profile *null_complain_profile;
|
||||||
+
|
+
|
||||||
+/**
|
|
||||||
+ * aa_taskattr_access
|
|
||||||
+ * @name: name of the file to check
|
|
||||||
+ *
|
|
||||||
+ * Check if name matches /proc/self/attr/current, with self resolved
|
|
||||||
+ * to the current pid. This file is the usermode interface for
|
|
||||||
+ * changing one's hat.
|
|
||||||
+ */
|
|
||||||
+static inline int aa_taskattr_access(const char *name)
|
|
||||||
+{
|
|
||||||
+ unsigned long pid;
|
|
||||||
+ char *end;
|
|
||||||
+
|
|
||||||
+ if (strncmp(name, "/proc/", 6) != 0)
|
|
||||||
+ return 0;
|
|
||||||
+ pid = simple_strtoul(name + 6, &end, 10);
|
|
||||||
+ if (pid != current->pid)
|
|
||||||
+ return 0;
|
|
||||||
+ return strcmp(end, "/attr/current") == 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void aa_permerror2result(int perm_result, struct aa_audit *sa)
|
+static inline void aa_permerror2result(int perm_result, struct aa_audit *sa)
|
||||||
+{
|
+{
|
||||||
+ if (perm_result == 0) { /* success */
|
+ if (perm_result == 0) { /* success */
|
||||||
@@ -97,15 +76,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+static int aa_file_denied(struct aa_profile *profile, const char *name,
|
+static int aa_file_denied(struct aa_profile *profile, const char *name,
|
||||||
+ int mask)
|
+ int mask)
|
||||||
+{
|
+{
|
||||||
+ int perms;
|
+ return (mask & ~aa_match(profile->file_rules, name));
|
||||||
+
|
|
||||||
+ /* Always allow write access to /proc/self/attr/current. */
|
|
||||||
+ if (mask == MAY_WRITE && aa_taskattr_access(name))
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ perms = aa_match(profile->file_rules, name);
|
|
||||||
+
|
|
||||||
+ return (mask & ~perms);
|
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+/**
|
+/**
|
||||||
@@ -147,6 +118,51 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+/**
|
+/**
|
||||||
|
+ * mangle -- escape special characters in str
|
||||||
|
+ * @str: string to escape
|
||||||
|
+ * @buffer: buffer containing str
|
||||||
|
+ *
|
||||||
|
+ * Escape special characters in @str, which must be contained in
|
||||||
|
+ * @buffer. The string grows towards @buffer. Returns a pointer
|
||||||
|
+ * to the quoted string, or ERR_PTR(-ENAMETOOLONG) upon failure.
|
||||||
|
+ */
|
||||||
|
+static char *mangle(char *str, char *buffer)
|
||||||
|
+{
|
||||||
|
+ static const char c_escape[] = {
|
||||||
|
+ ['\a'] = 'a', ['\b'] = 'b',
|
||||||
|
+ ['\f'] = 'f', ['\n'] = 'n',
|
||||||
|
+ ['\r'] = 'r', ['\t'] = 't',
|
||||||
|
+ ['\v'] = 'v',
|
||||||
|
+ [' '] = ' ', ['\\'] = '\\',
|
||||||
|
+ };
|
||||||
|
+ char *s, *t, c;
|
||||||
|
+
|
||||||
|
+#define mangle_escape(c) \
|
||||||
|
+ unlikely((unsigned char)(c) < ARRAY_SIZE(c_escape) && \
|
||||||
|
+ c_escape[(unsigned char)c])
|
||||||
|
+
|
||||||
|
+ for (s = str; (c = *s) != '\0'; s++)
|
||||||
|
+ if (mangle_escape(c))
|
||||||
|
+ goto escape;
|
||||||
|
+ return str;
|
||||||
|
+
|
||||||
|
+escape:
|
||||||
|
+ for (s = str, t = buffer; (c = *s) != '\0'; s++) {
|
||||||
|
+ if (mangle_escape(c)) {
|
||||||
|
+ if (t == s)
|
||||||
|
+ return NULL;
|
||||||
|
+ *t++ = '\\';
|
||||||
|
+ *t++ = c_escape[(unsigned char)c];
|
||||||
|
+ } else
|
||||||
|
+ *t++ = c;
|
||||||
|
+ }
|
||||||
|
+ *t++ = '\0';
|
||||||
|
+
|
||||||
|
+#undef mangle_escape
|
||||||
|
+ return buffer;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
+ * aa_get_name - compute the pathname of a file
|
+ * aa_get_name - compute the pathname of a file
|
||||||
+ * @dentry: dentry of the file
|
+ * @dentry: dentry of the file
|
||||||
+ * @mnt: vfsmount of the file
|
+ * @mnt: vfsmount of the file
|
||||||
@@ -192,12 +208,16 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ buf[size - 1] = '\0';
|
+ buf[size - 1] = '\0';
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
+ name = mangle(name, buf);
|
||||||
|
+ if (!name)
|
||||||
|
+ goto grow_buffer;
|
||||||
+ *buffer = buf;
|
+ *buffer = buf;
|
||||||
+ return name;
|
+ return name;
|
||||||
+ }
|
+ }
|
||||||
+ if (PTR_ERR(name) != -ENAMETOOLONG)
|
+ if (PTR_ERR(name) != -ENAMETOOLONG)
|
||||||
+ return name;
|
+ return name;
|
||||||
+
|
+
|
||||||
|
+grow_buffer:
|
||||||
+ kfree(buf);
|
+ kfree(buf);
|
||||||
+ size <<= 1;
|
+ size <<= 1;
|
||||||
+ if (size > apparmor_path_max)
|
+ if (size > apparmor_path_max)
|
||||||
@@ -398,8 +418,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ opspec_error = -EACCES;
|
+ opspec_error = -EACCES;
|
||||||
+
|
+
|
||||||
+ const gfp_t gfp_mask = sa->gfp_mask;
|
+ const gfp_t gfp_mask = sa->gfp_mask;
|
||||||
+
|
+ char comm_buffer[2 * sizeof(current->comm)], *comm;
|
||||||
+ WARN_ON(sa->type >= AA_AUDITTYPE__END);
|
|
||||||
+
|
+
|
||||||
+ /*
|
+ /*
|
||||||
+ * sa->result: 1 success, 0 failure
|
+ * sa->result: 1 success, 0 failure
|
||||||
@@ -475,7 +494,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+
|
+
|
||||||
+ audit_log_format(ab, "%s ", logcls); /* REJECTING/ALLOWING/etc */
|
+ audit_log_format(ab, "%s ", logcls); /* REJECTING/ALLOWING/etc */
|
||||||
+
|
+
|
||||||
+ if (sa->type == AA_AUDITTYPE_FILE) {
|
+ switch(sa->type) {
|
||||||
|
+ case AA_AUDITTYPE_FILE: {
|
||||||
+ int perm = audit ? sa->mask : sa->error_code;
|
+ int perm = audit ? sa->mask : sa->error_code;
|
||||||
+
|
+
|
||||||
+ audit_log_format(ab, "%s%s%s%s%s access to %s ",
|
+ audit_log_format(ab, "%s%s%s%s%s access to %s ",
|
||||||
@@ -487,12 +507,13 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ sa->name);
|
+ sa->name);
|
||||||
+
|
+
|
||||||
+ opspec_error = -EPERM;
|
+ opspec_error = -EPERM;
|
||||||
+
|
+ break;
|
||||||
+ } else if (sa->type == AA_AUDITTYPE_DIR) {
|
+ }
|
||||||
+ audit_log_format(ab, "%s on %s ", sa->operation, sa->name);
|
+ case AA_AUDITTYPE_DIR:
|
||||||
+
|
+ audit_log_format(ab, "%s on %s ", sa->name2, sa->name);
|
||||||
+ } else if (sa->type == AA_AUDITTYPE_ATTR) {
|
+ break;
|
||||||
+ struct iattr *iattr = (struct iattr*)sa->pval;
|
+ case AA_AUDITTYPE_ATTR: {
|
||||||
|
+ struct iattr *iattr = sa->iattr;
|
||||||
+
|
+
|
||||||
+ audit_log_format(ab,
|
+ audit_log_format(ab,
|
||||||
+ "attribute (%s%s%s%s%s%s%s) change to %s ",
|
+ "attribute (%s%s%s%s%s%s%s) change to %s ",
|
||||||
@@ -506,36 +527,37 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ (iattr->ia_valid & ATTR_MTIME)) ? "mtime," : "",
|
+ (iattr->ia_valid & ATTR_MTIME)) ? "mtime," : "",
|
||||||
+ iattr->ia_valid & ATTR_CTIME ? "ctime," : "",
|
+ iattr->ia_valid & ATTR_CTIME ? "ctime," : "",
|
||||||
+ sa->name);
|
+ sa->name);
|
||||||
+
|
+ break;
|
||||||
+ } else if (sa->type == AA_AUDITTYPE_XATTR) {
|
+ }
|
||||||
+ /* FIXME: how are special characters in sa->name escaped? */
|
+ case AA_AUDITTYPE_XATTR:
|
||||||
+ /* FIXME: check if this can be handled on the stack
|
+ audit_log_format(ab, "%s on %s ", sa->name2, sa->name);
|
||||||
+ with an inline varargs function. */
|
+ break;
|
||||||
+ audit_log_format(ab, "%s on %s ", sa->operation, sa->name);
|
+ case AA_AUDITTYPE_LINK:
|
||||||
+
|
+ audit_log_format(ab, "link access from %s to %s ", sa->name,
|
||||||
+ } else if (sa->type == AA_AUDITTYPE_LINK) {
|
+ sa->name2);
|
||||||
+ audit_log_format(ab,
|
+ break;
|
||||||
+ "link access from %s to %s ",
|
+ case AA_AUDITTYPE_CAP:
|
||||||
+ sa->name,
|
+ audit_log_format(ab, "access to capability '%s' ",
|
||||||
+ (char*)sa->pval);
|
|
||||||
+
|
|
||||||
+ } else if (sa->type == AA_AUDITTYPE_CAP) {
|
|
||||||
+ audit_log_format(ab,
|
|
||||||
+ "access to capability '%s' ",
|
|
||||||
+ capability_names[sa->capability]);
|
+ capability_names[sa->capability]);
|
||||||
+
|
|
||||||
+ opspec_error = -EPERM;
|
+ opspec_error = -EPERM;
|
||||||
+ } else if (sa->type == AA_AUDITTYPE_SYSCALL) {
|
+ break;
|
||||||
|
+ case AA_AUDITTYPE_SYSCALL:
|
||||||
+ audit_log_format(ab, "access to syscall '%s' ", sa->name);
|
+ audit_log_format(ab, "access to syscall '%s' ", sa->name);
|
||||||
+
|
|
||||||
+ opspec_error = -EPERM;
|
+ opspec_error = -EPERM;
|
||||||
+ } else {
|
+ break;
|
||||||
+ /* -EINVAL -- will WARN_ON above */
|
+ default:
|
||||||
+ goto out;
|
+ WARN_ON(1);
|
||||||
|
+ return error;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
+ comm = comm_buffer + sizeof(comm_buffer) - sizeof(current->comm);
|
||||||
|
+ get_task_comm(comm, current);
|
||||||
|
+ comm = mangle(comm, comm_buffer);
|
||||||
|
+ if (!comm)
|
||||||
|
+ comm = "?";
|
||||||
|
+
|
||||||
+ audit_log_format(ab, "(%s(%d) profile %s active %s)",
|
+ audit_log_format(ab, "(%s(%d) profile %s active %s)",
|
||||||
+ current->comm, current->pid,
|
+ comm, current->pid,
|
||||||
+ profile->parent->name, profile->name);
|
+ profile->parent->name, profile->name);
|
||||||
+
|
+
|
||||||
+ audit_log_end(ab);
|
+ audit_log_end(ab);
|
||||||
@@ -544,7 +566,6 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ error = 0;
|
+ error = 0;
|
||||||
+ else
|
+ else
|
||||||
+ error = sa->result ? 0 : opspec_error;
|
+ error = sa->result ? 0 : opspec_error;
|
||||||
+
|
|
||||||
+out:
|
+out:
|
||||||
+ return error;
|
+ return error;
|
||||||
+}
|
+}
|
||||||
@@ -564,7 +585,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ struct aa_audit sa;
|
+ struct aa_audit sa;
|
||||||
+
|
+
|
||||||
+ sa.type = AA_AUDITTYPE_ATTR;
|
+ sa.type = AA_AUDITTYPE_ATTR;
|
||||||
+ sa.pval = iattr;
|
+ sa.iattr = iattr;
|
||||||
+ sa.flags = 0;
|
+ sa.flags = 0;
|
||||||
+ sa.gfp_mask = GFP_KERNEL;
|
+ sa.gfp_mask = GFP_KERNEL;
|
||||||
+
|
+
|
||||||
@@ -585,21 +606,19 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ * @dentry: dentry of the file to check
|
+ * @dentry: dentry of the file to check
|
||||||
+ * @mnt: vfsmount of the file to check
|
+ * @mnt: vfsmount of the file to check
|
||||||
+ * @operation: xattr operation being done
|
+ * @operation: xattr operation being done
|
||||||
+ * @xattr_name: name of xattr to check
|
|
||||||
+ * @mask: access mode requested
|
+ * @mask: access mode requested
|
||||||
+ * @check: kind of check to perform
|
+ * @check: kind of check to perform
|
||||||
+ */
|
+ */
|
||||||
+int aa_perm_xattr(struct aa_profile *profile, struct dentry *dentry,
|
+int aa_perm_xattr(struct aa_profile *profile, struct dentry *dentry,
|
||||||
+ struct vfsmount *mnt, const char *operation,
|
+ struct vfsmount *mnt, const char *operation,
|
||||||
+ const char *xattr_name, int mask, int check)
|
+ int mask, int check)
|
||||||
+{
|
+{
|
||||||
+ struct inode *inode = dentry->d_inode;
|
+ struct inode *inode = dentry->d_inode;
|
||||||
+ int error;
|
+ int error;
|
||||||
+ struct aa_audit sa;
|
+ struct aa_audit sa;
|
||||||
+
|
+
|
||||||
+ sa.type = AA_AUDITTYPE_XATTR;
|
+ sa.type = AA_AUDITTYPE_XATTR;
|
||||||
+ sa.operation = operation;
|
+ sa.name2 = operation;
|
||||||
+ sa.pval = xattr_name;
|
|
||||||
+ sa.flags = 0;
|
+ sa.flags = 0;
|
||||||
+ sa.gfp_mask = GFP_KERNEL;
|
+ sa.gfp_mask = GFP_KERNEL;
|
||||||
+
|
+
|
||||||
@@ -670,7 +689,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ struct aa_audit sa;
|
+ struct aa_audit sa;
|
||||||
+
|
+
|
||||||
+ sa.type = AA_AUDITTYPE_DIR;
|
+ sa.type = AA_AUDITTYPE_DIR;
|
||||||
+ sa.operation = operation;
|
+ sa.name2 = operation;
|
||||||
+ sa.flags = 0;
|
+ sa.flags = 0;
|
||||||
+ sa.gfp_mask = GFP_KERNEL;
|
+ sa.gfp_mask = GFP_KERNEL;
|
||||||
+
|
+
|
||||||
@@ -740,24 +759,24 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ struct dentry *link, struct vfsmount *link_mnt,
|
+ struct dentry *link, struct vfsmount *link_mnt,
|
||||||
+ struct dentry *target, struct vfsmount *target_mnt)
|
+ struct dentry *target, struct vfsmount *target_mnt)
|
||||||
+{
|
+{
|
||||||
+ char *name_buffer = NULL, *pval_buffer = NULL;
|
+ char *name_buffer = NULL, *name2_buffer = NULL;
|
||||||
+ int denied_mask = -EPERM, error;
|
+ int denied_mask = -EPERM, error;
|
||||||
+ struct aa_audit sa;
|
+ struct aa_audit sa;
|
||||||
+
|
+
|
||||||
+ sa.name = aa_get_name(link, link_mnt, &name_buffer, 0);
|
+ sa.name = aa_get_name(link, link_mnt, &name_buffer, 0);
|
||||||
+ sa.pval = aa_get_name(target, target_mnt, &pval_buffer, 0);
|
+ sa.name2 = aa_get_name(target, target_mnt, &name2_buffer, 0);
|
||||||
+
|
+
|
||||||
+ if (IS_ERR(sa.name)) {
|
+ if (IS_ERR(sa.name)) {
|
||||||
+ denied_mask = PTR_ERR(sa.name);
|
+ denied_mask = PTR_ERR(sa.name);
|
||||||
+ sa.name = NULL;
|
+ sa.name = NULL;
|
||||||
+ }
|
+ }
|
||||||
+ if (IS_ERR(sa.pval)) {
|
+ if (IS_ERR(sa.name2)) {
|
||||||
+ denied_mask = PTR_ERR(sa.pval);
|
+ denied_mask = PTR_ERR(sa.name2);
|
||||||
+ sa.pval = NULL;
|
+ sa.name2 = NULL;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ if (sa.name && sa.pval)
|
+ if (sa.name && sa.name2)
|
||||||
+ denied_mask = aa_link_denied(profile, sa.name, sa.pval);
|
+ denied_mask = aa_link_denied(profile, sa.name, sa.name2);
|
||||||
+
|
+
|
||||||
+ aa_permerror2result(denied_mask, &sa);
|
+ aa_permerror2result(denied_mask, &sa);
|
||||||
+
|
+
|
||||||
@@ -768,7 +787,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ error = aa_audit(profile, &sa);
|
+ error = aa_audit(profile, &sa);
|
||||||
+
|
+
|
||||||
+ aa_put_name_buffer(name_buffer);
|
+ aa_put_name_buffer(name_buffer);
|
||||||
+ aa_put_name_buffer(pval_buffer);
|
+ aa_put_name_buffer(name2_buffer);
|
||||||
+
|
+
|
||||||
+ return error;
|
+ return error;
|
||||||
+}
|
+}
|
||||||
|
@@ -13,13 +13,13 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
---
|
---
|
||||||
security/apparmor/Kconfig | 9 +
|
security/apparmor/Kconfig | 9 +
|
||||||
security/apparmor/Makefile | 13 +
|
security/apparmor/Makefile | 13 +
|
||||||
security/apparmor/apparmor.h | 282 +++++++++++++++++++++++++++++++++++++++++
|
security/apparmor/apparmor.h | 279 +++++++++++++++++++++++++++++++++++++++++
|
||||||
security/apparmor/apparmorfs.c | 248 ++++++++++++++++++++++++++++++++++++
|
security/apparmor/apparmorfs.c | 248 ++++++++++++++++++++++++++++++++++++
|
||||||
security/apparmor/inline.h | 219 +++++++++++++++++++++++++++++++
|
security/apparmor/inline.h | 219 ++++++++++++++++++++++++++++++++
|
||||||
security/apparmor/list.c | 94 +++++++++++++
|
security/apparmor/list.c | 94 +++++++++++++
|
||||||
security/apparmor/locking.txt | 59 ++++++++
|
security/apparmor/locking.txt | 59 ++++++++
|
||||||
security/apparmor/procattr.c | 143 ++++++++++++++++++++
|
security/apparmor/procattr.c | 143 +++++++++++++++++++++
|
||||||
8 files changed, 1067 insertions(+)
|
8 files changed, 1064 insertions(+)
|
||||||
|
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/security/apparmor/Kconfig
|
+++ b/security/apparmor/Kconfig
|
||||||
@@ -51,7 +51,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ $(call cmd,make-caps)
|
+ $(call cmd,make-caps)
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/security/apparmor/apparmor.h
|
+++ b/security/apparmor/apparmor.h
|
||||||
@@ -0,0 +1,282 @@
|
@@ -0,0 +1,279 @@
|
||||||
+/*
|
+/*
|
||||||
+ * Copyright (C) 1998-2007 Novell/SUSE
|
+ * Copyright (C) 1998-2007 Novell/SUSE
|
||||||
+ *
|
+ *
|
||||||
@@ -217,15 +217,12 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ unsigned int result;
|
+ unsigned int result;
|
||||||
+ gfp_t gfp_mask;
|
+ gfp_t gfp_mask;
|
||||||
+ int error_code;
|
+ int error_code;
|
||||||
+
|
|
||||||
+ const char *operation;
|
|
||||||
+ const char *name;
|
+ const char *name;
|
||||||
+ union {
|
+ union {
|
||||||
+ int capability;
|
|
||||||
+ int mask;
|
+ int mask;
|
||||||
+ };
|
+ int capability;
|
||||||
+ union {
|
+ const char *name2;
|
||||||
+ const void *pval;
|
+ struct iattr *iattr;
|
||||||
+ va_list vaval;
|
+ va_list vaval;
|
||||||
+ };
|
+ };
|
||||||
+};
|
+};
|
||||||
@@ -277,8 +274,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+extern int aa_attr(struct aa_profile *profile, struct dentry *dentry,
|
+extern int aa_attr(struct aa_profile *profile, struct dentry *dentry,
|
||||||
+ struct vfsmount *mnt, struct iattr *iattr);
|
+ struct vfsmount *mnt, struct iattr *iattr);
|
||||||
+extern int aa_perm_xattr(struct aa_profile *profile, struct dentry *dentry,
|
+extern int aa_perm_xattr(struct aa_profile *profile, struct dentry *dentry,
|
||||||
+ struct vfsmount *mnt, const char *operation,
|
+ struct vfsmount *mnt, const char *operation, int mask,
|
||||||
+ const char *xattr_xattr, int mask, int check);
|
+ int check);
|
||||||
+extern int aa_capability(struct aa_task_context *cxt, int cap);
|
+extern int aa_capability(struct aa_task_context *cxt, int cap);
|
||||||
+extern int aa_perm(struct aa_profile *profile, struct dentry *dentry,
|
+extern int aa_perm(struct aa_profile *profile, struct dentry *dentry,
|
||||||
+ struct vfsmount *mnt, int mask, int check);
|
+ struct vfsmount *mnt, int mask, int check);
|
||||||
|
@@ -1,91 +0,0 @@
|
|||||||
---
|
|
||||||
security/apparmor/match.c | 12 ++++++------
|
|
||||||
security/apparmor/match.h | 2 +-
|
|
||||||
security/apparmor/module_interface.c | 10 ++++++----
|
|
||||||
3 files changed, 13 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
--- a/security/apparmor/match.c
|
|
||||||
+++ b/security/apparmor/match.c
|
|
||||||
@@ -23,9 +23,9 @@ static struct table_header *unpack_table
|
|
||||||
if (bsize < sizeof(struct table_header))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
- th.td_id = ntohs(*(u16 *) (blob));
|
|
||||||
- th.td_flags = ntohs(*(u16 *) (blob + 2));
|
|
||||||
- th.td_lolen = ntohl(*(u32 *) (blob + 8));
|
|
||||||
+ th.td_id = be16_to_cpu(*(u16 *) (blob));
|
|
||||||
+ th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
|
|
||||||
+ th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
|
|
||||||
blob += sizeof(struct table_header);
|
|
||||||
|
|
||||||
if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
|
|
||||||
@@ -41,13 +41,13 @@ static struct table_header *unpack_table
|
|
||||||
*table = th;
|
|
||||||
if (th.td_flags == YYTD_DATA8)
|
|
||||||
UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
|
|
||||||
- u8, ntohb);
|
|
||||||
+ u8, byte_to_byte);
|
|
||||||
else if (th.td_flags == YYTD_DATA16)
|
|
||||||
UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
|
|
||||||
- u16, ntohs);
|
|
||||||
+ u16, be16_to_cpu);
|
|
||||||
else
|
|
||||||
UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
|
|
||||||
- u32, ntohl);
|
|
||||||
+ u32, be32_to_cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
--- a/security/apparmor/match.h
|
|
||||||
+++ b/security/apparmor/match.h
|
|
||||||
@@ -63,7 +63,7 @@ struct aa_dfa {
|
|
||||||
struct table_header *tables[YYTD_ID_NXT];
|
|
||||||
};
|
|
||||||
|
|
||||||
-#define ntohb(X) (X)
|
|
||||||
+#define byte_to_byte(X) (X)
|
|
||||||
|
|
||||||
#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
|
|
||||||
do { \
|
|
||||||
--- a/security/apparmor/module_interface.c
|
|
||||||
+++ b/security/apparmor/module_interface.c
|
|
||||||
@@ -60,7 +60,7 @@ struct aa_ext {
|
|
||||||
|
|
||||||
static inline int aa_inbounds(struct aa_ext *e, size_t size)
|
|
||||||
{
|
|
||||||
- return (e->pos + size <= e->end);
|
|
||||||
+ return (size <= e->end - e->pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -243,7 +243,7 @@ struct aa_dfa *aa_unpack_dfa(struct aa_e
|
|
||||||
* @e: serialized data extent information
|
|
||||||
* @error: error code returned if unpacking fails
|
|
||||||
*/
|
|
||||||
-static struct aa_profile *aa_unpack_profile(struct aa_ext *e)
|
|
||||||
+static struct aa_profile *aa_unpack_profile(struct aa_ext *e, int depth)
|
|
||||||
{
|
|
||||||
struct aa_profile *profile = NULL;
|
|
||||||
|
|
||||||
@@ -284,9 +284,11 @@ static struct aa_profile *aa_unpack_prof
|
|
||||||
|
|
||||||
/* get optional subprofiles */
|
|
||||||
if (aa_is_nameX(e, AA_LIST, "hats")) {
|
|
||||||
+ if (depth > 0)
|
|
||||||
+ goto fail;
|
|
||||||
while (!aa_is_nameX(e, AA_LISTEND, NULL)) {
|
|
||||||
struct aa_profile *subprofile;
|
|
||||||
- subprofile = aa_unpack_profile(e);
|
|
||||||
+ subprofile = aa_unpack_profile(e, depth + 1);
|
|
||||||
if (IS_ERR(subprofile)) {
|
|
||||||
error = PTR_ERR(subprofile);
|
|
||||||
goto fail;
|
|
||||||
@@ -320,7 +322,7 @@ fail:
|
|
||||||
*/
|
|
||||||
static struct aa_profile *aa_unpack_profile_wrapper(struct aa_ext *e)
|
|
||||||
{
|
|
||||||
- struct aa_profile *profile = aa_unpack_profile(e);
|
|
||||||
+ struct aa_profile *profile = aa_unpack_profile(e, 0);
|
|
||||||
if (!IS_ERR(profile) &&
|
|
||||||
(!list_empty(&profile->sub) || profile->flags.complain)) {
|
|
||||||
int error;
|
|
@@ -10,8 +10,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
---
|
---
|
||||||
security/apparmor/match.c | 232 ++++++++++++
|
security/apparmor/match.c | 232 ++++++++++++
|
||||||
security/apparmor/match.h | 83 ++++
|
security/apparmor/match.h | 83 ++++
|
||||||
security/apparmor/module_interface.c | 641 +++++++++++++++++++++++++++++++++++
|
security/apparmor/module_interface.c | 643 +++++++++++++++++++++++++++++++++++
|
||||||
3 files changed, 956 insertions(+)
|
3 files changed, 958 insertions(+)
|
||||||
|
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/security/apparmor/match.c
|
+++ b/security/apparmor/match.c
|
||||||
@@ -41,9 +41,9 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ if (bsize < sizeof(struct table_header))
|
+ if (bsize < sizeof(struct table_header))
|
||||||
+ goto out;
|
+ goto out;
|
||||||
+
|
+
|
||||||
+ th.td_id = ntohs(*(u16 *) (blob));
|
+ th.td_id = be16_to_cpu(*(u16 *) (blob));
|
||||||
+ th.td_flags = ntohs(*(u16 *) (blob + 2));
|
+ th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
|
||||||
+ th.td_lolen = ntohl(*(u32 *) (blob + 8));
|
+ th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
|
||||||
+ blob += sizeof(struct table_header);
|
+ blob += sizeof(struct table_header);
|
||||||
+
|
+
|
||||||
+ if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
|
+ if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
|
||||||
@@ -59,13 +59,13 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ *table = th;
|
+ *table = th;
|
||||||
+ if (th.td_flags == YYTD_DATA8)
|
+ if (th.td_flags == YYTD_DATA8)
|
||||||
+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
|
+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
|
||||||
+ u8, ntohb);
|
+ u8, byte_to_byte);
|
||||||
+ else if (th.td_flags == YYTD_DATA16)
|
+ else if (th.td_flags == YYTD_DATA16)
|
||||||
+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
|
+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
|
||||||
+ u16, ntohs);
|
+ u16, be16_to_cpu);
|
||||||
+ else
|
+ else
|
||||||
+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
|
+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
|
||||||
+ u32, ntohl);
|
+ u32, be32_to_cpu);
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+out:
|
+out:
|
||||||
@@ -316,7 +316,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ struct table_header *tables[YYTD_ID_NXT];
|
+ struct table_header *tables[YYTD_ID_NXT];
|
||||||
+};
|
+};
|
||||||
+
|
+
|
||||||
+#define ntohb(X) (X)
|
+#define byte_to_byte(X) (X)
|
||||||
+
|
+
|
||||||
+#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
|
+#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
|
||||||
+ do { \
|
+ do { \
|
||||||
@@ -336,7 +336,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+#endif /* __MATCH_H */
|
+#endif /* __MATCH_H */
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/security/apparmor/module_interface.c
|
+++ b/security/apparmor/module_interface.c
|
||||||
@@ -0,0 +1,641 @@
|
@@ -0,0 +1,643 @@
|
||||||
+/*
|
+/*
|
||||||
+ * Copyright (C) 1998-2007 Novell/SUSE
|
+ * Copyright (C) 1998-2007 Novell/SUSE
|
||||||
+ *
|
+ *
|
||||||
@@ -399,7 +399,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+
|
+
|
||||||
+static inline int aa_inbounds(struct aa_ext *e, size_t size)
|
+static inline int aa_inbounds(struct aa_ext *e, size_t size)
|
||||||
+{
|
+{
|
||||||
+ return (e->pos + size <= e->end);
|
+ return (size <= e->end - e->pos);
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+/**
|
+/**
|
||||||
@@ -582,7 +582,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ * @e: serialized data extent information
|
+ * @e: serialized data extent information
|
||||||
+ * @error: error code returned if unpacking fails
|
+ * @error: error code returned if unpacking fails
|
||||||
+ */
|
+ */
|
||||||
+static struct aa_profile *aa_unpack_profile(struct aa_ext *e)
|
+static struct aa_profile *aa_unpack_profile(struct aa_ext *e, int depth)
|
||||||
+{
|
+{
|
||||||
+ struct aa_profile *profile = NULL;
|
+ struct aa_profile *profile = NULL;
|
||||||
+
|
+
|
||||||
@@ -623,9 +623,11 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+
|
+
|
||||||
+ /* get optional subprofiles */
|
+ /* get optional subprofiles */
|
||||||
+ if (aa_is_nameX(e, AA_LIST, "hats")) {
|
+ if (aa_is_nameX(e, AA_LIST, "hats")) {
|
||||||
|
+ if (depth > 0)
|
||||||
|
+ goto fail;
|
||||||
+ while (!aa_is_nameX(e, AA_LISTEND, NULL)) {
|
+ while (!aa_is_nameX(e, AA_LISTEND, NULL)) {
|
||||||
+ struct aa_profile *subprofile;
|
+ struct aa_profile *subprofile;
|
||||||
+ subprofile = aa_unpack_profile(e);
|
+ subprofile = aa_unpack_profile(e, depth + 1);
|
||||||
+ if (IS_ERR(subprofile)) {
|
+ if (IS_ERR(subprofile)) {
|
||||||
+ error = PTR_ERR(subprofile);
|
+ error = PTR_ERR(subprofile);
|
||||||
+ goto fail;
|
+ goto fail;
|
||||||
@@ -659,7 +661,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
+ */
|
+ */
|
||||||
+static struct aa_profile *aa_unpack_profile_wrapper(struct aa_ext *e)
|
+static struct aa_profile *aa_unpack_profile_wrapper(struct aa_ext *e)
|
||||||
+{
|
+{
|
||||||
+ struct aa_profile *profile = aa_unpack_profile(e);
|
+ struct aa_profile *profile = aa_unpack_profile(e, 0);
|
||||||
+ if (!IS_ERR(profile) &&
|
+ if (!IS_ERR(profile) &&
|
||||||
+ (!list_empty(&profile->sub) || profile->flags.complain)) {
|
+ (!list_empty(&profile->sub) || profile->flags.complain)) {
|
||||||
+ int error;
|
+ int error;
|
||||||
|
@@ -1,41 +0,0 @@
|
|||||||
---
|
|
||||||
security/apparmor/lsm.c | 19 ++++++++++++++-----
|
|
||||||
1 file changed, 14 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
--- a/security/apparmor/lsm.c
|
|
||||||
+++ b/security/apparmor/lsm.c
|
|
||||||
@@ -114,20 +114,29 @@ static int apparmor_ptrace(struct task_s
|
|
||||||
/**
|
|
||||||
* parent can ptrace child when
|
|
||||||
* - parent is unconfined
|
|
||||||
- * - parent is in complain mode
|
|
||||||
- * - parent and child are confined by the same profile
|
|
||||||
+ * - parent & child are in the same namespace &&
|
|
||||||
+ * - parent is in complain mode
|
|
||||||
+ * - parent and child are confined by the same profile
|
|
||||||
+ * - parent profile has CAP_SYS_PTRACE
|
|
||||||
*/
|
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
cxt = aa_task_context(parent);
|
|
||||||
child_cxt = aa_task_context(child);
|
|
||||||
child_profile = child_cxt ? child_cxt->profile : NULL;
|
|
||||||
- error = aa_may_ptrace(cxt, child_profile);
|
|
||||||
- if (cxt && PROFILE_COMPLAIN(cxt->profile)) {
|
|
||||||
- LOG_HINT(cxt->profile, GFP_ATOMIC, HINT_PTRACE,
|
|
||||||
+ if (cxt && (parent->nsproxy != child->nsproxy)) {
|
|
||||||
+ AA_WARN(GFP_ATOMIC,
|
|
||||||
+ "REJECTING ptrace across namespace of %d by %d",
|
|
||||||
+ parent->pid, child->pid);
|
|
||||||
+ error = -EPERM;
|
|
||||||
+ } else {
|
|
||||||
+ error = aa_may_ptrace(cxt, child_profile);
|
|
||||||
+ if (cxt && PROFILE_COMPLAIN(cxt->profile)) {
|
|
||||||
+ LOG_HINT(cxt->profile, GFP_ATOMIC, HINT_PTRACE,
|
|
||||||
"pid=%d child=%d\n",
|
|
||||||
current->pid, child->pid);
|
|
||||||
}
|
|
||||||
+ }
|
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
return error;
|
|
@@ -1,291 +0,0 @@
|
|||||||
The whole way how audit messages are generated is crap, but it's a bad
|
|
||||||
time to fix it right now. Anyway, here are some minor changes that make
|
|
||||||
it slightly less ugly:
|
|
||||||
|
|
||||||
- the xattr name is not use din aa_audit, so don't pass it through.
|
|
||||||
- convert the huge if in aa_audit into a case statement.
|
|
||||||
- get rid of the pval, and put the particular fields into the union
|
|
||||||
instead.
|
|
||||||
- use name2 for the operation.
|
|
||||||
- put some more fields never used together in the union as well.
|
|
||||||
|
|
||||||
---
|
|
||||||
security/apparmor/apparmor.h | 13 ++----
|
|
||||||
security/apparmor/lsm.c | 21 ++++------
|
|
||||||
security/apparmor/main.c | 84 +++++++++++++++++++------------------------
|
|
||||||
3 files changed, 52 insertions(+), 66 deletions(-)
|
|
||||||
|
|
||||||
--- a/security/apparmor/apparmor.h
|
|
||||||
+++ b/security/apparmor/apparmor.h
|
|
||||||
@@ -163,15 +163,12 @@ struct aa_audit {
|
|
||||||
unsigned int result;
|
|
||||||
gfp_t gfp_mask;
|
|
||||||
int error_code;
|
|
||||||
-
|
|
||||||
- const char *operation;
|
|
||||||
const char *name;
|
|
||||||
union {
|
|
||||||
- int capability;
|
|
||||||
int mask;
|
|
||||||
- };
|
|
||||||
- union {
|
|
||||||
- const void *pval;
|
|
||||||
+ int capability;
|
|
||||||
+ const char *name2;
|
|
||||||
+ struct iattr *iattr;
|
|
||||||
va_list vaval;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -223,8 +220,8 @@ extern int aa_audit(struct aa_profile *p
|
|
||||||
extern int aa_attr(struct aa_profile *profile, struct dentry *dentry,
|
|
||||||
struct vfsmount *mnt, struct iattr *iattr);
|
|
||||||
extern int aa_perm_xattr(struct aa_profile *profile, struct dentry *dentry,
|
|
||||||
- struct vfsmount *mnt, const char *operation,
|
|
||||||
- const char *xattr_xattr, int mask, int check);
|
|
||||||
+ struct vfsmount *mnt, const char *operation, int mask,
|
|
||||||
+ int check);
|
|
||||||
extern int aa_capability(struct aa_task_context *cxt, int cap);
|
|
||||||
extern int aa_perm(struct aa_profile *profile, struct dentry *dentry,
|
|
||||||
struct vfsmount *mnt, int mask, int check);
|
|
||||||
--- a/security/apparmor/lsm.c
|
|
||||||
+++ b/security/apparmor/lsm.c
|
|
||||||
@@ -393,8 +393,8 @@ out:
|
|
||||||
}
|
|
||||||
|
|
||||||
static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
|
|
||||||
- const char *name, const char *operation,
|
|
||||||
- int mask, struct file *file)
|
|
||||||
+ const char *operation, int mask,
|
|
||||||
+ struct file *file)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
@@ -403,8 +403,8 @@ static int aa_xattr_permission(struct de
|
|
||||||
int check = file ? AA_CHECK_FD : 0;
|
|
||||||
|
|
||||||
if (profile)
|
|
||||||
- error = aa_perm_xattr(profile, dentry, mnt, name,
|
|
||||||
- operation, mask, check);
|
|
||||||
+ error = aa_perm_xattr(profile, dentry, mnt, operation,
|
|
||||||
+ mask, check);
|
|
||||||
aa_put_profile(profile);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -415,30 +415,27 @@ static int apparmor_inode_setxattr(struc
|
|
||||||
char *name, void *value, size_t size,
|
|
||||||
int flags, struct file *file)
|
|
||||||
{
|
|
||||||
- return aa_xattr_permission(dentry, mnt, name, "xattr set", MAY_WRITE,
|
|
||||||
- file);
|
|
||||||
+ return aa_xattr_permission(dentry, mnt, "xattr set", MAY_WRITE, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
|
||||||
char *name, struct file *file)
|
|
||||||
{
|
|
||||||
- return aa_xattr_permission(dentry, mnt, name, "xattr get", MAY_READ,
|
|
||||||
- file);
|
|
||||||
+ return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
|
|
||||||
struct file *file)
|
|
||||||
{
|
|
||||||
- return aa_xattr_permission(dentry, mnt, NULL, "xattr list", MAY_READ,
|
|
||||||
- file);
|
|
||||||
+ return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int apparmor_inode_removexattr(struct dentry *dentry,
|
|
||||||
struct vfsmount *mnt, char *name,
|
|
||||||
struct file *file)
|
|
||||||
{
|
|
||||||
- return aa_xattr_permission(dentry, mnt, name, "xattr remove",
|
|
||||||
- MAY_WRITE, file);
|
|
||||||
+ return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
|
|
||||||
+ file);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int apparmor_file_permission(struct file *file, int mask)
|
|
||||||
--- a/security/apparmor/main.c
|
|
||||||
+++ b/security/apparmor/main.c
|
|
||||||
@@ -404,8 +404,6 @@ int aa_audit(struct aa_profile *profile,
|
|
||||||
|
|
||||||
const gfp_t gfp_mask = sa->gfp_mask;
|
|
||||||
|
|
||||||
- WARN_ON(sa->type >= AA_AUDITTYPE__END);
|
|
||||||
-
|
|
||||||
/*
|
|
||||||
* sa->result: 1 success, 0 failure
|
|
||||||
* sa->error_code: success: 0
|
|
||||||
@@ -480,7 +478,8 @@ int aa_audit(struct aa_profile *profile,
|
|
||||||
|
|
||||||
audit_log_format(ab, "%s ", logcls); /* REJECTING/ALLOWING/etc */
|
|
||||||
|
|
||||||
- if (sa->type == AA_AUDITTYPE_FILE) {
|
|
||||||
+ switch(sa->type) {
|
|
||||||
+ case AA_AUDITTYPE_FILE: {
|
|
||||||
int perm = audit ? sa->mask : sa->error_code;
|
|
||||||
|
|
||||||
audit_log_format(ab, "%s%s%s%s%s access to %s ",
|
|
||||||
@@ -492,12 +491,13 @@ int aa_audit(struct aa_profile *profile,
|
|
||||||
sa->name);
|
|
||||||
|
|
||||||
opspec_error = -EPERM;
|
|
||||||
-
|
|
||||||
- } else if (sa->type == AA_AUDITTYPE_DIR) {
|
|
||||||
- audit_log_format(ab, "%s on %s ", sa->operation, sa->name);
|
|
||||||
-
|
|
||||||
- } else if (sa->type == AA_AUDITTYPE_ATTR) {
|
|
||||||
- struct iattr *iattr = (struct iattr*)sa->pval;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ case AA_AUDITTYPE_DIR:
|
|
||||||
+ audit_log_format(ab, "%s on %s ", sa->name2, sa->name);
|
|
||||||
+ break;
|
|
||||||
+ case AA_AUDITTYPE_ATTR: {
|
|
||||||
+ struct iattr *iattr = sa->iattr;
|
|
||||||
|
|
||||||
audit_log_format(ab,
|
|
||||||
"attribute (%s%s%s%s%s%s%s) change to %s ",
|
|
||||||
@@ -511,32 +511,27 @@ int aa_audit(struct aa_profile *profile,
|
|
||||||
(iattr->ia_valid & ATTR_MTIME)) ? "mtime," : "",
|
|
||||||
iattr->ia_valid & ATTR_CTIME ? "ctime," : "",
|
|
||||||
sa->name);
|
|
||||||
-
|
|
||||||
- } else if (sa->type == AA_AUDITTYPE_XATTR) {
|
|
||||||
- /* FIXME: how are special characters in sa->name escaped? */
|
|
||||||
- /* FIXME: check if this can be handled on the stack
|
|
||||||
- with an inline varargs function. */
|
|
||||||
- audit_log_format(ab, "%s on %s ", sa->operation, sa->name);
|
|
||||||
-
|
|
||||||
- } else if (sa->type == AA_AUDITTYPE_LINK) {
|
|
||||||
- audit_log_format(ab,
|
|
||||||
- "link access from %s to %s ",
|
|
||||||
- sa->name,
|
|
||||||
- (char*)sa->pval);
|
|
||||||
-
|
|
||||||
- } else if (sa->type == AA_AUDITTYPE_CAP) {
|
|
||||||
- audit_log_format(ab,
|
|
||||||
- "access to capability '%s' ",
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ case AA_AUDITTYPE_XATTR:
|
|
||||||
+ audit_log_format(ab, "%s on %s ", sa->name2, sa->name);
|
|
||||||
+ break;
|
|
||||||
+ case AA_AUDITTYPE_LINK:
|
|
||||||
+ audit_log_format(ab, "link access from %s to %s ", sa->name,
|
|
||||||
+ sa->name2);
|
|
||||||
+ break;
|
|
||||||
+ case AA_AUDITTYPE_CAP:
|
|
||||||
+ audit_log_format(ab, "access to capability '%s' ",
|
|
||||||
capability_names[sa->capability]);
|
|
||||||
-
|
|
||||||
opspec_error = -EPERM;
|
|
||||||
- } else if (sa->type == AA_AUDITTYPE_SYSCALL) {
|
|
||||||
+ break;
|
|
||||||
+ case AA_AUDITTYPE_SYSCALL:
|
|
||||||
audit_log_format(ab, "access to syscall '%s' ", sa->name);
|
|
||||||
-
|
|
||||||
opspec_error = -EPERM;
|
|
||||||
- } else {
|
|
||||||
- /* -EINVAL -- will WARN_ON above */
|
|
||||||
- goto out;
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ WARN_ON(1);
|
|
||||||
+ return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
audit_log_format(ab, "(%s(%d) profile %s active %s)",
|
|
||||||
@@ -549,7 +544,6 @@ int aa_audit(struct aa_profile *profile,
|
|
||||||
error = 0;
|
|
||||||
else
|
|
||||||
error = sa->result ? 0 : opspec_error;
|
|
||||||
-
|
|
||||||
out:
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
@@ -569,7 +563,7 @@ int aa_attr(struct aa_profile *profile,
|
|
||||||
struct aa_audit sa;
|
|
||||||
|
|
||||||
sa.type = AA_AUDITTYPE_ATTR;
|
|
||||||
- sa.pval = iattr;
|
|
||||||
+ sa.iattr = iattr;
|
|
||||||
sa.flags = 0;
|
|
||||||
sa.gfp_mask = GFP_KERNEL;
|
|
||||||
|
|
||||||
@@ -590,21 +584,19 @@ int aa_attr(struct aa_profile *profile,
|
|
||||||
* @dentry: dentry of the file to check
|
|
||||||
* @mnt: vfsmount of the file to check
|
|
||||||
* @operation: xattr operation being done
|
|
||||||
- * @xattr_name: name of xattr to check
|
|
||||||
* @mask: access mode requested
|
|
||||||
* @check: kind of check to perform
|
|
||||||
*/
|
|
||||||
int aa_perm_xattr(struct aa_profile *profile, struct dentry *dentry,
|
|
||||||
struct vfsmount *mnt, const char *operation,
|
|
||||||
- const char *xattr_name, int mask, int check)
|
|
||||||
+ int mask, int check)
|
|
||||||
{
|
|
||||||
struct inode *inode = dentry->d_inode;
|
|
||||||
int error;
|
|
||||||
struct aa_audit sa;
|
|
||||||
|
|
||||||
sa.type = AA_AUDITTYPE_XATTR;
|
|
||||||
- sa.operation = operation;
|
|
||||||
- sa.pval = xattr_name;
|
|
||||||
+ sa.name2 = operation;
|
|
||||||
sa.flags = 0;
|
|
||||||
sa.gfp_mask = GFP_KERNEL;
|
|
||||||
|
|
||||||
@@ -675,7 +667,7 @@ int aa_perm_dir(struct aa_profile *profi
|
|
||||||
struct aa_audit sa;
|
|
||||||
|
|
||||||
sa.type = AA_AUDITTYPE_DIR;
|
|
||||||
- sa.operation = operation;
|
|
||||||
+ sa.name2 = operation;
|
|
||||||
sa.flags = 0;
|
|
||||||
sa.gfp_mask = GFP_KERNEL;
|
|
||||||
|
|
||||||
@@ -745,24 +737,24 @@ int aa_link(struct aa_profile *profile,
|
|
||||||
struct dentry *link, struct vfsmount *link_mnt,
|
|
||||||
struct dentry *target, struct vfsmount *target_mnt)
|
|
||||||
{
|
|
||||||
- char *name_buffer = NULL, *pval_buffer = NULL;
|
|
||||||
+ char *name_buffer = NULL, *name2_buffer = NULL;
|
|
||||||
int denied_mask = -EPERM, error;
|
|
||||||
struct aa_audit sa;
|
|
||||||
|
|
||||||
sa.name = aa_get_name(link, link_mnt, &name_buffer, 0);
|
|
||||||
- sa.pval = aa_get_name(target, target_mnt, &pval_buffer, 0);
|
|
||||||
+ sa.name2 = aa_get_name(target, target_mnt, &name2_buffer, 0);
|
|
||||||
|
|
||||||
if (IS_ERR(sa.name)) {
|
|
||||||
denied_mask = PTR_ERR(sa.name);
|
|
||||||
sa.name = NULL;
|
|
||||||
}
|
|
||||||
- if (IS_ERR(sa.pval)) {
|
|
||||||
- denied_mask = PTR_ERR(sa.pval);
|
|
||||||
- sa.pval = NULL;
|
|
||||||
+ if (IS_ERR(sa.name2)) {
|
|
||||||
+ denied_mask = PTR_ERR(sa.name2);
|
|
||||||
+ sa.name2 = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (sa.name && sa.pval)
|
|
||||||
- denied_mask = aa_link_denied(profile, sa.name, sa.pval);
|
|
||||||
+ if (sa.name && sa.name2)
|
|
||||||
+ denied_mask = aa_link_denied(profile, sa.name, sa.name2);
|
|
||||||
|
|
||||||
aa_permerror2result(denied_mask, &sa);
|
|
||||||
|
|
||||||
@@ -773,7 +765,7 @@ int aa_link(struct aa_profile *profile,
|
|
||||||
error = aa_audit(profile, &sa);
|
|
||||||
|
|
||||||
aa_put_name_buffer(name_buffer);
|
|
||||||
- aa_put_name_buffer(pval_buffer);
|
|
||||||
+ aa_put_name_buffer(name2_buffer);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
@@ -1,49 +0,0 @@
|
|||||||
Two bugs:
|
|
||||||
|
|
||||||
- task->comm should be accessed via get_task_comm().
|
|
||||||
- comm is user modifiable via prtcl(PR_SET_NAME), so users may inject
|
|
||||||
special characters. We need to quote.
|
|
||||||
|
|
||||||
What for does user-space use the task names in the log? I hope for
|
|
||||||
nothing...
|
|
||||||
|
|
||||||
---
|
|
||||||
security/apparmor/main.c | 9 ++++++++-
|
|
||||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/security/apparmor/main.c
|
|
||||||
+++ b/security/apparmor/main.c
|
|
||||||
@@ -403,6 +403,7 @@ int aa_audit(struct aa_profile *profile,
|
|
||||||
opspec_error = -EACCES;
|
|
||||||
|
|
||||||
const gfp_t gfp_mask = sa->gfp_mask;
|
|
||||||
+ char comm_buffer[2 * sizeof(current->comm)], *comm;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sa->result: 1 success, 0 failure
|
|
||||||
@@ -534,8 +535,14 @@ int aa_audit(struct aa_profile *profile,
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ comm = comm_buffer + sizeof(comm_buffer) - sizeof(current->comm);
|
|
||||||
+ get_task_comm(comm, current);
|
|
||||||
+ comm = mangle(comm, comm_buffer);
|
|
||||||
+ if (!comm)
|
|
||||||
+ comm = "?";
|
|
||||||
+
|
|
||||||
audit_log_format(ab, "(%s(%d) profile %s active %s)",
|
|
||||||
- current->comm, current->pid,
|
|
||||||
+ comm, current->pid,
|
|
||||||
profile->parent->name, profile->name);
|
|
||||||
|
|
||||||
audit_log_end(ab);
|
|
||||||
--- a/fs/exec.c
|
|
||||||
+++ b/fs/exec.c
|
|
||||||
@@ -806,6 +806,7 @@ void get_task_comm(char *buf, struct tas
|
|
||||||
strncpy(buf, tsk->comm, sizeof(tsk->comm));
|
|
||||||
task_unlock(tsk);
|
|
||||||
}
|
|
||||||
+EXPORT_SYMBOL(get_task_comm);
|
|
||||||
|
|
||||||
void set_task_comm(struct task_struct *tsk, char *buf)
|
|
||||||
{
|
|
@@ -1,459 +0,0 @@
|
|||||||
Index: b/security/apparmor/apparmor.h
|
|
||||||
===================================================================
|
|
||||||
--- a/security/apparmor/apparmor.h
|
|
||||||
+++ b/security/apparmor/apparmor.h
|
|
||||||
@@ -37,7 +37,7 @@
|
|
||||||
|
|
||||||
/* Control parameters (0 or 1), settable thru module/boot flags or
|
|
||||||
* via /sys/kernel/security/apparmor/control */
|
|
||||||
-extern int apparmor_complain;
|
|
||||||
+extern int apparmor_learning;
|
|
||||||
extern int apparmor_debug;
|
|
||||||
extern int apparmor_audit;
|
|
||||||
extern int apparmor_logsyscall;
|
|
||||||
@@ -48,12 +48,12 @@ static inline int mediated_filesystem(st
|
|
||||||
return !(inode->i_sb->s_flags & MS_NOUSER);
|
|
||||||
}
|
|
||||||
|
|
||||||
-#define PROFILE_COMPLAIN(_profile) \
|
|
||||||
- (apparmor_complain == 1 || ((_profile) && (_profile)->flags.complain))
|
|
||||||
+#define PROFILE_LEARNING(_profile) \
|
|
||||||
+ (apparmor_learning == 1 || ((_profile) && (_profile)->flags.learning))
|
|
||||||
|
|
||||||
-#define APPARMOR_COMPLAIN(_cxt) \
|
|
||||||
- (apparmor_complain == 1 || \
|
|
||||||
- ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.complain))
|
|
||||||
+#define APPARMOR_LEARNING(_cxt) \
|
|
||||||
+ (apparmor_learning == 1 || \
|
|
||||||
+ ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.learning))
|
|
||||||
|
|
||||||
#define PROFILE_AUDIT(_profile) \
|
|
||||||
(apparmor_audit == 1 || ((_profile) && (_profile)->flags.audit))
|
|
||||||
@@ -116,7 +116,7 @@ struct aa_profile {
|
|
||||||
struct list_head list;
|
|
||||||
struct list_head sub;
|
|
||||||
struct {
|
|
||||||
- int complain;
|
|
||||||
+ int learning;
|
|
||||||
int audit;
|
|
||||||
} flags;
|
|
||||||
struct aa_profile *null_profile;
|
|
||||||
@@ -158,7 +158,7 @@ static inline struct aa_task_context *aa
|
|
||||||
return rcu_dereference((struct aa_task_context *)task->security);
|
|
||||||
}
|
|
||||||
|
|
||||||
-extern struct aa_profile *null_complain_profile;
|
|
||||||
+extern struct aa_profile *null_learning_profile;
|
|
||||||
|
|
||||||
/* aa_audit - AppArmor auditing structure
|
|
||||||
* Structure is populated by access control code and passed to aa_audit which
|
|
||||||
@@ -217,8 +217,8 @@ struct aa_audit {
|
|
||||||
|
|
||||||
/* main.c */
|
|
||||||
extern void free_aa_task_context_rcu_callback(struct rcu_head *head);
|
|
||||||
-extern int alloc_null_complain_profile(void);
|
|
||||||
-extern void free_null_complain_profile(void);
|
|
||||||
+extern int alloc_null_learning_profile(void);
|
|
||||||
+extern void free_null_learning_profile(void);
|
|
||||||
extern int attach_nullprofile(struct aa_profile *profile);
|
|
||||||
extern int aa_audit_message(struct aa_profile *profile, gfp_t gfp, int,
|
|
||||||
const char *, ...);
|
|
||||||
Index: b/security/apparmor/apparmorfs.c
|
|
||||||
===================================================================
|
|
||||||
--- a/security/apparmor/apparmorfs.c
|
|
||||||
+++ b/security/apparmor/apparmorfs.c
|
|
||||||
@@ -106,8 +106,8 @@ static struct root_entry {
|
|
||||||
|
|
||||||
/* interface for setting binary config values */
|
|
||||||
{"control", S_IFDIR, 0550},
|
|
||||||
- {"complain", S_IFREG, 0640, &apparmorfs_control_fops,
|
|
||||||
- &apparmor_complain},
|
|
||||||
+ {"learning", S_IFREG, 0640, &apparmorfs_control_fops,
|
|
||||||
+ &apparmor_learning},
|
|
||||||
{"audit", S_IFREG, 0640, &apparmorfs_control_fops,
|
|
||||||
&apparmor_audit},
|
|
||||||
{"debug", S_IFREG, 0640, &apparmorfs_control_fops,
|
|
||||||
Index: b/security/apparmor/list.c
|
|
||||||
===================================================================
|
|
||||||
--- a/security/apparmor/list.c
|
|
||||||
+++ b/security/apparmor/list.c
|
|
||||||
@@ -84,7 +84,7 @@ static int seq_show_profile(struct seq_f
|
|
||||||
{
|
|
||||||
struct aa_profile *profile = (struct aa_profile *)v;
|
|
||||||
seq_printf(f, "%s (%s)\n", profile->name,
|
|
||||||
- PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
|
|
||||||
+ PROFILE_LEARNING(profile) ? "learning" : "enforce");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Index: b/security/apparmor/lsm.c
|
|
||||||
===================================================================
|
|
||||||
--- a/security/apparmor/lsm.c
|
|
||||||
+++ b/security/apparmor/lsm.c
|
|
||||||
@@ -26,15 +26,15 @@
|
|
||||||
* /sys/modules/parameters, as we want to do additional mediation and
|
|
||||||
* don't want to add special path code. */
|
|
||||||
|
|
||||||
-/* Complain mode -- in complain mode access failures result in auditing only
|
|
||||||
+/* Learning mode -- in learning mode access failures result in auditing only
|
|
||||||
* and task is allowed access. audit events are processed by userspace to
|
|
||||||
* generate policy. Default is 'enforce' (0).
|
|
||||||
* Value is also togglable per profile and referenced when global value is
|
|
||||||
* enforce.
|
|
||||||
*/
|
|
||||||
-int apparmor_complain = 0;
|
|
||||||
-module_param_named(complain, apparmor_complain, int, S_IRUSR);
|
|
||||||
-MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
|
|
||||||
+int apparmor_learning = 0;
|
|
||||||
+module_param_named(learning, apparmor_learning, int, S_IRUSR);
|
|
||||||
+MODULE_PARM_DESC(apparmor_learning, "Toggle AppArmor learning mode");
|
|
||||||
|
|
||||||
/* Debug mode */
|
|
||||||
int apparmor_debug = 0;
|
|
||||||
@@ -767,15 +767,15 @@ struct security_operations apparmor_ops
|
|
||||||
static int __init apparmor_init(void)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
- const char *complainmsg = ": complainmode enabled";
|
|
||||||
+ const char *learningmsg = ": learningmode enabled";
|
|
||||||
|
|
||||||
if ((error = create_apparmorfs())) {
|
|
||||||
AA_ERROR("Unable to activate AppArmor filesystem\n");
|
|
||||||
goto createfs_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if ((error = alloc_null_complain_profile())){
|
|
||||||
- AA_ERROR("Unable to allocate null complain profile\n");
|
|
||||||
+ if ((error = alloc_null_learning_profile())){
|
|
||||||
+ AA_ERROR("Unable to allocate null learning profile\n");
|
|
||||||
goto alloc_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -785,15 +785,15 @@ static int __init apparmor_init(void)
|
|
||||||
}
|
|
||||||
|
|
||||||
AA_INFO(GFP_KERNEL, "AppArmor initialized%s\n",
|
|
||||||
- apparmor_complain ? complainmsg : "");
|
|
||||||
+ apparmor_learning ? learningmsg : "");
|
|
||||||
aa_audit_message(NULL, GFP_KERNEL, 0,
|
|
||||||
"AppArmor initialized%s\n",
|
|
||||||
- apparmor_complain ? complainmsg : "");
|
|
||||||
+ apparmor_learning ? learningmsg : "");
|
|
||||||
|
|
||||||
return error;
|
|
||||||
|
|
||||||
register_security_out:
|
|
||||||
- free_null_complain_profile();
|
|
||||||
+ free_null_learning_profile();
|
|
||||||
|
|
||||||
alloc_out:
|
|
||||||
(void)destroy_apparmorfs();
|
|
||||||
@@ -825,7 +825,7 @@ static void __exit apparmor_exit(void)
|
|
||||||
|
|
||||||
/* FIXME: cleanup profiles references on files */
|
|
||||||
|
|
||||||
- free_null_complain_profile();
|
|
||||||
+ free_null_learning_profile();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delay for an rcu cycle to make sure that all active task
|
|
||||||
Index: b/security/apparmor/main.c
|
|
||||||
===================================================================
|
|
||||||
--- a/security/apparmor/main.c
|
|
||||||
+++ b/security/apparmor/main.c
|
|
||||||
@@ -25,17 +25,17 @@ static const char *capability_names[] =
|
|
||||||
#include "capability_names.h"
|
|
||||||
};
|
|
||||||
|
|
||||||
-/* NULL complain profile
|
|
||||||
+/* NULL learning profile
|
|
||||||
*
|
|
||||||
- * Used when in complain mode, to emit Permitting messages for non-existant
|
|
||||||
+ * Used when in learning mode, to emit Permitting messages for non-existant
|
|
||||||
* profiles and hats. This is necessary because of selective mode, in which
|
|
||||||
- * case we need a complain null_profile and enforce null_profile
|
|
||||||
+ * case we need a learning null_profile and enforce null_profile
|
|
||||||
*
|
|
||||||
- * The null_complain_profile cannot be statically allocated, because it
|
|
||||||
+ * The null_learning_profile cannot be statically allocated, because it
|
|
||||||
* can be associated to files which keep their reference even if apparmor is
|
|
||||||
* unloaded
|
|
||||||
*/
|
|
||||||
-struct aa_profile *null_complain_profile;
|
|
||||||
+struct aa_profile *null_learning_profile;
|
|
||||||
|
|
||||||
/***************************
|
|
||||||
* Private utility functions
|
|
||||||
@@ -237,14 +237,14 @@ int attach_nullprofile(struct aa_profile
|
|
||||||
hat = alloc_aa_profile();
|
|
||||||
if (!hat)
|
|
||||||
goto fail;
|
|
||||||
- if (profile->flags.complain)
|
|
||||||
- hatname = kstrdup("null-complain-profile", GFP_KERNEL);
|
|
||||||
+ if (profile->flags.learning)
|
|
||||||
+ hatname = kstrdup("null-learning-profile", GFP_KERNEL);
|
|
||||||
else
|
|
||||||
hatname = kstrdup("null-profile", GFP_KERNEL);
|
|
||||||
if (!hatname)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
- hat->flags.complain = profile->flags.complain;
|
|
||||||
+ hat->flags.learning = profile->flags.learning;
|
|
||||||
hat->name = hatname;
|
|
||||||
hat->parent = profile;
|
|
||||||
|
|
||||||
@@ -261,43 +261,43 @@ fail:
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
- * alloc_null_complain_profile - Allocate the global null_complain_profile.
|
|
||||||
+ * alloc_null_learning_profile - Allocate the global null_learning_profile.
|
|
||||||
*
|
|
||||||
* Return %0 (success) or error (-%ENOMEM)
|
|
||||||
*/
|
|
||||||
-int alloc_null_complain_profile(void)
|
|
||||||
+int alloc_null_learning_profile(void)
|
|
||||||
{
|
|
||||||
- null_complain_profile = alloc_aa_profile();
|
|
||||||
- if (!null_complain_profile)
|
|
||||||
+ null_learning_profile = alloc_aa_profile();
|
|
||||||
+ if (!null_learning_profile)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
- null_complain_profile->name =
|
|
||||||
- kstrdup("null-complain-profile", GFP_KERNEL);
|
|
||||||
+ null_learning_profile->name =
|
|
||||||
+ kstrdup("null-learning-profile", GFP_KERNEL);
|
|
||||||
|
|
||||||
- if (!null_complain_profile->name)
|
|
||||||
+ if (!null_learning_profile->name)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
- null_complain_profile->flags.complain = 1;
|
|
||||||
- if (attach_nullprofile(null_complain_profile))
|
|
||||||
+ null_learning_profile->flags.learning = 1;
|
|
||||||
+ if (attach_nullprofile(null_learning_profile))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
/* free_aa_profile is safe for freeing partially constructed objects */
|
|
||||||
- free_aa_profile(null_complain_profile);
|
|
||||||
- null_complain_profile = NULL;
|
|
||||||
+ free_aa_profile(null_learning_profile);
|
|
||||||
+ null_learning_profile = NULL;
|
|
||||||
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
- * free_null_complain_profile - Free null profiles
|
|
||||||
+ * free_null_learning_profile - Free null profiles
|
|
||||||
*/
|
|
||||||
-void free_null_complain_profile(void)
|
|
||||||
+void free_null_learning_profile(void)
|
|
||||||
{
|
|
||||||
- aa_put_profile(null_complain_profile);
|
|
||||||
- null_complain_profile = NULL;
|
|
||||||
+ aa_put_profile(null_learning_profile);
|
|
||||||
+ null_learning_profile = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -362,7 +362,7 @@ int aa_audit(struct aa_profile *profile,
|
|
||||||
const char *logcls;
|
|
||||||
unsigned int flags;
|
|
||||||
int audit = 0,
|
|
||||||
- complain = 0,
|
|
||||||
+ learning = 0,
|
|
||||||
error = -EINVAL,
|
|
||||||
opspec_error = -EACCES;
|
|
||||||
|
|
||||||
@@ -400,8 +400,8 @@ int aa_audit(struct aa_profile *profile,
|
|
||||||
*/
|
|
||||||
logcls = "REJECTING";
|
|
||||||
} else {
|
|
||||||
- complain = PROFILE_COMPLAIN(profile);
|
|
||||||
- logcls = complain ? "PERMITTING" : "REJECTING";
|
|
||||||
+ learning = PROFILE_LEARNING(profile);
|
|
||||||
+ logcls = learning ? "PERMITTING" : "REJECTING";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In future extend w/ per-profile flags
|
|
||||||
@@ -427,7 +427,7 @@ int aa_audit(struct aa_profile *profile,
|
|
||||||
if (!ab) {
|
|
||||||
AA_ERROR("Unable to log event (%d) to audit subsys\n",
|
|
||||||
sa->type);
|
|
||||||
- if (complain)
|
|
||||||
+ if (learning)
|
|
||||||
error = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
@@ -509,7 +509,7 @@ int aa_audit(struct aa_profile *profile,
|
|
||||||
|
|
||||||
audit_log_end(ab);
|
|
||||||
|
|
||||||
- if (complain)
|
|
||||||
+ if (learning)
|
|
||||||
error = 0;
|
|
||||||
else
|
|
||||||
error = sa->result ? 0 : opspec_error;
|
|
||||||
@@ -664,7 +664,7 @@ int aa_capability(struct aa_task_context
|
|
||||||
|
|
||||||
/* test if cap has alread been logged */
|
|
||||||
if (cap_raised(cxt->caps_logged, cap)) {
|
|
||||||
- if (PROFILE_COMPLAIN(cxt->profile))
|
|
||||||
+ if (PROFILE_LEARNING(cxt->profile))
|
|
||||||
error = 0;
|
|
||||||
return error;
|
|
||||||
} else
|
|
||||||
@@ -773,8 +773,8 @@ repeat:
|
|
||||||
cxt->hat_magic);
|
|
||||||
unlock_profile(profile);
|
|
||||||
|
|
||||||
- if (APPARMOR_COMPLAIN(child_cxt) &&
|
|
||||||
- profile == null_complain_profile) {
|
|
||||||
+ if (APPARMOR_LEARNING(child_cxt) &&
|
|
||||||
+ profile == null_learning_profile) {
|
|
||||||
LOG_HINT(profile, GFP_KERNEL, HINT_FORK,
|
|
||||||
"pid=%d child=%d\n",
|
|
||||||
current->pid, child->pid);
|
|
||||||
@@ -788,7 +788,7 @@ repeat:
|
|
||||||
|
|
||||||
static struct aa_profile *
|
|
||||||
aa_register_find(struct aa_profile *profile, const char *name, int mandatory,
|
|
||||||
- int complain)
|
|
||||||
+ int learning)
|
|
||||||
{
|
|
||||||
struct aa_profile *new_profile;
|
|
||||||
|
|
||||||
@@ -798,14 +798,14 @@ aa_register_find(struct aa_profile *prof
|
|
||||||
AA_DEBUG("%s: setting profile %s\n",
|
|
||||||
__FUNCTION__, new_profile->name);
|
|
||||||
} else if (mandatory && profile) {
|
|
||||||
- if (complain) {
|
|
||||||
+ if (learning) {
|
|
||||||
LOG_HINT(profile, GFP_KERNEL, HINT_MANDPROF,
|
|
||||||
"image=%s pid=%d profile=%s active=%s\n",
|
|
||||||
name,
|
|
||||||
current->pid,
|
|
||||||
profile->parent->name, profile->name);
|
|
||||||
|
|
||||||
- profile = aa_dup_profile(null_complain_profile);
|
|
||||||
+ profile = aa_dup_profile(null_learning_profile);
|
|
||||||
} else {
|
|
||||||
AA_WARN(GFP_KERNEL, "REJECTING exec(2) of image '%s'. "
|
|
||||||
"Profile mandatory and not found "
|
|
||||||
@@ -838,7 +838,7 @@ int aa_register(struct linux_binprm *bpr
|
|
||||||
char *filename, *buffer = NULL;
|
|
||||||
struct file *filp = bprm->file;
|
|
||||||
struct aa_profile *profile, *old_profile, *new_profile = NULL;
|
|
||||||
- int exec_mode = AA_EXEC_UNSAFE, complain = 0;
|
|
||||||
+ int exec_mode = AA_EXEC_UNSAFE, learning = 0;
|
|
||||||
|
|
||||||
AA_DEBUG("%s\n", __FUNCTION__);
|
|
||||||
|
|
||||||
@@ -852,7 +852,7 @@ int aa_register(struct linux_binprm *bpr
|
|
||||||
repeat:
|
|
||||||
profile = aa_get_profile(current);
|
|
||||||
if (profile) {
|
|
||||||
- complain = PROFILE_COMPLAIN(profile);
|
|
||||||
+ learning = PROFILE_LEARNING(profile);
|
|
||||||
|
|
||||||
/* Confined task, determine what mode inherit, unconfined or
|
|
||||||
* mandatory to load new profile
|
|
||||||
@@ -883,7 +883,7 @@ repeat:
|
|
||||||
filename);
|
|
||||||
new_profile = aa_register_find(profile,
|
|
||||||
filename, 1,
|
|
||||||
- complain);
|
|
||||||
+ learning);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
@@ -900,12 +900,12 @@ repeat:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
- } else if (complain) {
|
|
||||||
+ } else if (learning) {
|
|
||||||
/* There was no entry in calling profile
|
|
||||||
* describing mode to execute image in.
|
|
||||||
* Drop into null-profile (disabling secure exec).
|
|
||||||
*/
|
|
||||||
- new_profile = aa_dup_profile(null_complain_profile);
|
|
||||||
+ new_profile = aa_dup_profile(null_learning_profile);
|
|
||||||
exec_mode |= AA_EXEC_UNSAFE;
|
|
||||||
} else {
|
|
||||||
AA_WARN(GFP_KERNEL,
|
|
||||||
@@ -957,7 +957,7 @@ repeat:
|
|
||||||
((unsigned long)bprm->security | bprm_flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (complain && new_profile == null_complain_profile) {
|
|
||||||
+ if (learning && new_profile == null_learning_profile) {
|
|
||||||
LOG_HINT(new_profile, GFP_ATOMIC, HINT_CHGPROF,
|
|
||||||
"pid=%d\n",
|
|
||||||
current->pid);
|
|
||||||
@@ -1044,7 +1044,7 @@ static inline int do_change_hat(const ch
|
|
||||||
} else {
|
|
||||||
struct aa_profile *profile = cxt->profile;
|
|
||||||
|
|
||||||
- if (APPARMOR_COMPLAIN(cxt)) {
|
|
||||||
+ if (APPARMOR_LEARNING(cxt)) {
|
|
||||||
LOG_HINT(profile, GFP_ATOMIC, HINT_UNKNOWN_HAT,
|
|
||||||
"%s pid=%d "
|
|
||||||
"profile=%s active=%s\n",
|
|
||||||
@@ -1116,7 +1116,7 @@ int aa_change_hat(const char *hat_name,
|
|
||||||
profile = cxt->profile;
|
|
||||||
|
|
||||||
/* check to see if the confined process has any hats. */
|
|
||||||
- if (list_empty(&profile->parent->sub) && !PROFILE_COMPLAIN(profile)) {
|
|
||||||
+ if (list_empty(&profile->parent->sub) && !PROFILE_LEARNING(profile)) {
|
|
||||||
error = -ECHILD;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
Index: b/security/apparmor/module_interface.c
|
|
||||||
===================================================================
|
|
||||||
--- a/security/apparmor/module_interface.c
|
|
||||||
+++ b/security/apparmor/module_interface.c
|
|
||||||
@@ -245,12 +245,12 @@ static struct aa_profile *aa_unpack_prof
|
|
||||||
if (!aa_is_dynstring(e, &profile->name, NULL))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
- /* per profile debug flags (complain, audit) */
|
|
||||||
+ /* per profile debug flags (learning, audit) */
|
|
||||||
if (!aa_is_nameX(e, AA_STRUCT, "flags"))
|
|
||||||
goto fail;
|
|
||||||
if (!aa_is_u32(e, NULL, NULL))
|
|
||||||
goto fail;
|
|
||||||
- if (!aa_is_u32(e, &(profile->flags.complain), NULL))
|
|
||||||
+ if (!aa_is_u32(e, &(profile->flags.learning), NULL))
|
|
||||||
goto fail;
|
|
||||||
if (!aa_is_u32(e, &(profile->flags.audit), NULL))
|
|
||||||
goto fail;
|
|
||||||
@@ -308,7 +308,7 @@ static struct aa_profile *aa_unpack_prof
|
|
||||||
{
|
|
||||||
struct aa_profile *profile = aa_unpack_profile(e);
|
|
||||||
if (!IS_ERR(profile) &&
|
|
||||||
- (!list_empty(&profile->sub) || profile->flags.complain)) {
|
|
||||||
+ (!list_empty(&profile->sub) || profile->flags.learning)) {
|
|
||||||
int error;
|
|
||||||
if ((error = attach_nullprofile(profile))) {
|
|
||||||
aa_put_profile(profile);
|
|
||||||
Index: b/security/apparmor/procattr.c
|
|
||||||
===================================================================
|
|
||||||
--- a/security/apparmor/procattr.c
|
|
||||||
+++ b/security/apparmor/procattr.c
|
|
||||||
@@ -19,8 +19,8 @@ int aa_getprocattr(struct aa_profile *pr
|
|
||||||
char *str;
|
|
||||||
|
|
||||||
if (profile) {
|
|
||||||
- const char *mode_str = PROFILE_COMPLAIN(profile) ?
|
|
||||||
- " (complain)" : " (enforce)";
|
|
||||||
+ const char *mode_str = PROFILE_LEARNING(profile) ?
|
|
||||||
+ " (learning)" : " (enforce)";
|
|
||||||
|
|
||||||
*len = ((profile != profile->parent) ?
|
|
||||||
strlen(profile->parent->name) + 1 : 0) +
|
|
@@ -1,49 +0,0 @@
|
|||||||
Per the discussion in the email thread beginning with
|
|
||||||
|
|
||||||
Subject: [pdx] Block the CLONE_NEWNS flag in clone(2)
|
|
||||||
Message-Id: <200702241013.09434.agruen@suse.de>
|
|
||||||
|
|
||||||
we decided to drop the outright rejection on CLONE_NEWNS since the kernel
|
|
||||||
currently requires CAP_SYS_ADMIN.
|
|
||||||
|
|
||||||
As an alternative to this patch, we could convert the error = -EPERM
|
|
||||||
line to a capable(CAP_SYS_ADMIN) check, to guarantee that CLONE_NEWNS
|
|
||||||
always requires CAP_SYS_ADMIN under apparmor, even if the kernel changes
|
|
||||||
to not require it.
|
|
||||||
---
|
|
||||||
security/apparmor/lsm.c | 17 -----------------
|
|
||||||
1 file changed, 17 deletions(-)
|
|
||||||
|
|
||||||
--- a/security/apparmor/lsm.c
|
|
||||||
+++ b/security/apparmor/lsm.c
|
|
||||||
@@ -467,22 +467,6 @@ out:
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int apparmor_task_create(unsigned long clone_flags)
|
|
||||||
-{
|
|
||||||
- struct aa_profile *profile;
|
|
||||||
- int error = 0;
|
|
||||||
-
|
|
||||||
- profile = aa_get_profile(current);
|
|
||||||
- if (profile) {
|
|
||||||
- /* Don't allow to create new namespaces. */
|
|
||||||
- if (clone_flags & CLONE_NEWNS)
|
|
||||||
- error = -EPERM;
|
|
||||||
- }
|
|
||||||
- aa_put_profile(profile);
|
|
||||||
-
|
|
||||||
- return error;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static int apparmor_file_alloc_security(struct file *file)
|
|
||||||
{
|
|
||||||
struct aa_profile *profile;
|
|
||||||
@@ -678,7 +662,6 @@ struct security_operations apparmor_ops
|
|
||||||
.file_mmap = apparmor_file_mmap,
|
|
||||||
.file_mprotect = apparmor_file_mprotect,
|
|
||||||
|
|
||||||
- .task_create = apparmor_task_create,
|
|
||||||
.task_alloc_security = apparmor_task_alloc_security,
|
|
||||||
.task_free_security = apparmor_task_free_security,
|
|
||||||
.task_post_setuid = cap_task_post_setuid,
|
|
10
kernel-patches/for-mainline/export-get_task_comm.diff
Normal file
10
kernel-patches/for-mainline/export-get_task_comm.diff
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
--- a/fs/exec.c
|
||||||
|
+++ b/fs/exec.c
|
||||||
|
@@ -806,6 +806,7 @@ void get_task_comm(char *buf, struct tas
|
||||||
|
strncpy(buf, tsk->comm, sizeof(tsk->comm));
|
||||||
|
task_unlock(tsk);
|
||||||
|
}
|
||||||
|
+EXPORT_SYMBOL(get_task_comm);
|
||||||
|
|
||||||
|
void set_task_comm(struct task_struct *tsk, char *buf)
|
||||||
|
{
|
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
security/apparmor/Kconfig | 3 ++-
|
|
||||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/security/apparmor/Kconfig
|
|
||||||
+++ b/security/apparmor/Kconfig
|
|
||||||
@@ -1,6 +1,7 @@
|
|
||||||
config SECURITY_APPARMOR
|
|
||||||
tristate "AppArmor support"
|
|
||||||
- depends on SECURITY!=n
|
|
||||||
+ depends on SECURITY
|
|
||||||
+ select AUDIT
|
|
||||||
help
|
|
||||||
This enables the AppArmor security module.
|
|
||||||
Required userspace tools (if they are not included in your
|
|
@@ -1,75 +0,0 @@
|
|||||||
---
|
|
||||||
security/apparmor/main.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
1 file changed, 49 insertions(+)
|
|
||||||
|
|
||||||
--- a/security/apparmor/main.c
|
|
||||||
+++ b/security/apparmor/main.c
|
|
||||||
@@ -103,6 +103,51 @@ static int aa_link_denied(struct aa_prof
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
+ * mangle -- escape special characters in str
|
|
||||||
+ * @str: string to escape
|
|
||||||
+ * @buffer: buffer containing str
|
|
||||||
+ *
|
|
||||||
+ * Escape special characters in @str, which must be contained in
|
|
||||||
+ * @buffer. The string grows towards @buffer. Returns a pointer
|
|
||||||
+ * to the quoted string, or ERR_PTR(-ENAMETOOLONG) upon failure.
|
|
||||||
+ */
|
|
||||||
+static char *mangle(char *str, char *buffer)
|
|
||||||
+{
|
|
||||||
+ static const char c_escape[] = {
|
|
||||||
+ ['\a'] = 'a', ['\b'] = 'b',
|
|
||||||
+ ['\f'] = 'f', ['\n'] = 'n',
|
|
||||||
+ ['\r'] = 'r', ['\t'] = 't',
|
|
||||||
+ ['\v'] = 'v',
|
|
||||||
+ [' '] = ' ', ['\\'] = '\\',
|
|
||||||
+ };
|
|
||||||
+ char *s, *t, c;
|
|
||||||
+
|
|
||||||
+#define mangle_escape(c) \
|
|
||||||
+ unlikely((unsigned char)(c) < ARRAY_SIZE(c_escape) && \
|
|
||||||
+ c_escape[(unsigned char)c])
|
|
||||||
+
|
|
||||||
+ for (s = str; (c = *s) != '\0'; s++)
|
|
||||||
+ if (mangle_escape(c))
|
|
||||||
+ goto escape;
|
|
||||||
+ return str;
|
|
||||||
+
|
|
||||||
+escape:
|
|
||||||
+ for (s = str, t = buffer; (c = *s) != '\0'; s++) {
|
|
||||||
+ if (mangle_escape(c)) {
|
|
||||||
+ if (t == s)
|
|
||||||
+ return NULL;
|
|
||||||
+ *t++ = '\\';
|
|
||||||
+ *t++ = c_escape[(unsigned char)c];
|
|
||||||
+ } else
|
|
||||||
+ *t++ = c;
|
|
||||||
+ }
|
|
||||||
+ *t++ = '\0';
|
|
||||||
+
|
|
||||||
+#undef mangle_escape
|
|
||||||
+ return buffer;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
* aa_get_name - compute the pathname of a file
|
|
||||||
* @dentry: dentry of the file
|
|
||||||
* @mnt: vfsmount of the file
|
|
||||||
@@ -148,12 +193,16 @@ static char *aa_get_name(struct dentry *
|
|
||||||
buf[size - 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
+ name = mangle(name, buf);
|
|
||||||
+ if (!name)
|
|
||||||
+ goto grow_buffer;
|
|
||||||
*buffer = buf;
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
if (PTR_ERR(name) != -ENAMETOOLONG)
|
|
||||||
return name;
|
|
||||||
|
|
||||||
+grow_buffer:
|
|
||||||
kfree(buf);
|
|
||||||
size <<= 1;
|
|
||||||
if (size > apparmor_path_max)
|
|
@@ -1,61 +0,0 @@
|
|||||||
From: Andreas Gruenbacher <agruen@suse.de>
|
|
||||||
Subject: Make d_path() consistent across mount operations
|
|
||||||
|
|
||||||
Right now, the path that __d_path() computes can become slightly
|
|
||||||
inconsistent when it races with mount operations: it grabs the
|
|
||||||
vfsmount_lock when traversing mount points, but immediately drops it
|
|
||||||
again, only to re-grab it when it reaches the next mount point.
|
|
||||||
The result is that the filename computed is not always consisent, and
|
|
||||||
the file may never have had that name. (This is unlikely, but still
|
|
||||||
possible.)
|
|
||||||
|
|
||||||
We can easily fix this by grabbing the vfsmount_lock when the first
|
|
||||||
mount point is reached, and holding onto it until the d_cache lookup is
|
|
||||||
completed.
|
|
||||||
|
|
||||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|
||||||
|
|
||||||
---
|
|
||||||
fs/dcache.c | 14 ++++++++------
|
|
||||||
1 file changed, 8 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
--- a/fs/dcache.c
|
|
||||||
+++ b/fs/dcache.c
|
|
||||||
@@ -1754,7 +1754,7 @@ static char *__d_path(struct dentry *den
|
|
||||||
struct dentry *root, struct vfsmount *rootmnt,
|
|
||||||
char *buffer, int buflen, int fail_deleted)
|
|
||||||
{
|
|
||||||
- int namelen, is_slash;
|
|
||||||
+ int namelen, is_slash, vfsmount_locked = 0;
|
|
||||||
|
|
||||||
if (buflen < 2)
|
|
||||||
return ERR_PTR(-ENAMETOOLONG);
|
|
||||||
@@ -1777,14 +1777,14 @@ static char *__d_path(struct dentry *den
|
|
||||||
struct dentry * parent;
|
|
||||||
|
|
||||||
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
|
|
||||||
- spin_lock(&vfsmount_lock);
|
|
||||||
- if (vfsmnt->mnt_parent == vfsmnt) {
|
|
||||||
- spin_unlock(&vfsmount_lock);
|
|
||||||
- goto global_root;
|
|
||||||
+ if (!vfsmount_locked) {
|
|
||||||
+ spin_lock(&vfsmount_lock);
|
|
||||||
+ vfsmount_locked = 1;
|
|
||||||
}
|
|
||||||
+ if (vfsmnt->mnt_parent == vfsmnt)
|
|
||||||
+ goto global_root;
|
|
||||||
dentry = vfsmnt->mnt_mountpoint;
|
|
||||||
vfsmnt = vfsmnt->mnt_parent;
|
|
||||||
- spin_unlock(&vfsmount_lock);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
parent = dentry->d_parent;
|
|
||||||
@@ -1803,6 +1803,8 @@ static char *__d_path(struct dentry *den
|
|
||||||
*--buffer = '/';
|
|
||||||
|
|
||||||
out:
|
|
||||||
+ if (vfsmount_locked)
|
|
||||||
+ spin_unlock(&vfsmount_lock);
|
|
||||||
spin_unlock(&dcache_lock);
|
|
||||||
return buffer;
|
|
||||||
|
|
@@ -39,30 +39,23 @@ proc-mounts-cleanup.diff
|
|||||||
# fix-d_path.diff
|
# fix-d_path.diff
|
||||||
file-handle-ops.diff
|
file-handle-ops.diff
|
||||||
security-xattr-file.diff
|
security-xattr-file.diff
|
||||||
|
sysctl-pathname.diff
|
||||||
|
export-get_task_comm.diff
|
||||||
apparmor-audit.diff
|
apparmor-audit.diff
|
||||||
apparmor-main.diff
|
apparmor-main.diff
|
||||||
apparmor-main-2.diff
|
|
||||||
mangle.diff
|
|
||||||
apparmor-lsm.diff
|
apparmor-lsm.diff
|
||||||
apparmor-lsm-2.diff
|
|
||||||
drop_CLONE_NEWNS_restriction.diff
|
|
||||||
apparmor-ns-ptrace.diff
|
|
||||||
apparmor-module_interface.diff
|
apparmor-module_interface.diff
|
||||||
apparmor-module_interface-2.diff
|
|
||||||
apparmor-misc.diff
|
apparmor-misc.diff
|
||||||
audit-cleanup.diff
|
|
||||||
comm.diff
|
|
||||||
ecryptfs-d_revalidate.diff
|
|
||||||
nfs-nameidata-check.diff
|
|
||||||
apparmor-intree.diff
|
apparmor-intree.diff
|
||||||
sysctl-pathname.diff
|
ecryptfs-d_revalidate.diff
|
||||||
apparmor-sysctl-pathname.diff
|
apparmor-sysctl-pathname.diff
|
||||||
vfs_create-nameidata.diff
|
vfs_create-nameidata.diff
|
||||||
do_path_lookup-nameidata.diff
|
do_path_lookup-nameidata.diff
|
||||||
sys_fchdir-nameidata.diff
|
sys_fchdir-nameidata.diff
|
||||||
nfsd_permission-nameidata.diff
|
nfsd_permission-nameidata.diff
|
||||||
file_permission-nameidata.diff
|
file_permission-nameidata.diff
|
||||||
kconfig-dependencies.diff
|
# NOT YET
|
||||||
|
nfs-nameidata-check.diff
|
||||||
split-up-nameidata.diff
|
split-up-nameidata.diff
|
||||||
# xattr_permission.diff
|
# xattr_permission.diff
|
||||||
# vfs_create-args.diff
|
# vfs_create-args.diff
|
||||||
|
@@ -2347,7 +2347,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|||||||
|
|
||||||
+/**
|
+/**
|
||||||
+ * Fields shared between nameidata and nameidata2 -- nameidata2 could
|
+ * Fields shared between nameidata and nameidata2 -- nameidata2 could
|
||||||
+ * be embedded in nameidata, but then the vfs code would become
|
+ * simply be embedded in nameidata, but then the vfs code would become
|
||||||
+ * cluttered with dereferences.
|
+ * cluttered with dereferences.
|
||||||
+ */
|
+ */
|
||||||
+#define __NAMEIDATA2 \
|
+#define __NAMEIDATA2 \
|
||||||
|
Reference in New Issue
Block a user