2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 06:16:03 +00:00

Fold patches, and remove obsolete ones.

This commit is contained in:
Andreas Gruenbacher
2007-04-27 11:20:11 +00:00
parent 77db9ae104
commit 7ee57d5e7a
19 changed files with 191 additions and 1527 deletions

View File

@@ -5,9 +5,10 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/Kconfig | 1 +
security/Makefile | 1 +
2 files changed, 2 insertions(+)
security/Kconfig | 1 +
security/Makefile | 1 +
security/apparmor/Kconfig | 3 ++-
3 files changed, 4 insertions(+), 1 deletion(-)
--- a/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_CAPABILITIES) += commoncap.o capability.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

View File

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

View File

@@ -7,12 +7,12 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/apparmor/lsm.c | 828 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 828 insertions(+)
security/apparmor/lsm.c | 762 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 762 insertions(+)
--- /dev/null
+++ b/security/apparmor/lsm.c
@@ -0,0 +1,828 @@
@@ -0,0 +1,762 @@
+/*
+ * Copyright (C) 1998-2007 Novell/SUSE
+ *
@@ -129,49 +129,34 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ /**
+ * 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;
+}
+
+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;
@@ -203,26 +188,6 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ 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 */
@@ -443,8 +408,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+}
+
+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;
+
@@ -453,8 +418,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.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);
+ }
+
@@ -465,30 +430,27 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ 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)
@@ -526,22 +488,6 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ 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;
@@ -609,17 +555,6 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ 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)
+{
@@ -711,17 +646,17 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+
+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,
+
@@ -748,11 +683,10 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ .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 = 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,

View File

@@ -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));
}
/**

View File

@@ -7,12 +7,12 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/apparmor/main.c | 1321 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1321 insertions(+)
security/apparmor/main.c | 1340 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1340 insertions(+)
--- /dev/null
+++ b/security/apparmor/main.c
@@ -0,0 +1,1321 @@
@@ -0,0 +1,1340 @@
+/*
+ * Copyright (C) 2002-2007 Novell/SUSE
+ *
@@ -53,27 +53,6 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ */
+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 */
@@ -97,15 +76,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+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));
+}
+
+/**
@@ -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
+ * @dentry: dentry of the file
+ * @mnt: vfsmount of the file
@@ -192,12 +208,16 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ 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)
@@ -398,8 +418,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ opspec_error = -EACCES;
+
+ const gfp_t gfp_mask = sa->gfp_mask;
+
+ WARN_ON(sa->type >= AA_AUDITTYPE__END);
+ char comm_buffer[2 * sizeof(current->comm)], *comm;
+
+ /*
+ * 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 */
+
+ 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 ",
@@ -487,12 +507,13 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ 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 ",
@@ -506,36 +527,37 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ (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;
+ }
+
+ 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);
@@ -544,7 +566,6 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ error = 0;
+ else
+ error = sa->result ? 0 : opspec_error;
+
+out:
+ return error;
+}
@@ -564,7 +585,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ struct aa_audit sa;
+
+ sa.type = AA_AUDITTYPE_ATTR;
+ sa.pval = iattr;
+ sa.iattr = iattr;
+ sa.flags = 0;
+ sa.gfp_mask = GFP_KERNEL;
+
@@ -585,21 +606,19 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ * @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;
+
@@ -670,7 +689,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ struct aa_audit sa;
+
+ sa.type = AA_AUDITTYPE_DIR;
+ sa.operation = operation;
+ sa.name2 = operation;
+ sa.flags = 0;
+ 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 *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);
+
@@ -768,7 +787,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ 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;
+}

View File

@@ -13,13 +13,13 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/apparmor/Kconfig | 9 +
security/apparmor/Makefile | 13 +
security/apparmor/apparmor.h | 282 +++++++++++++++++++++++++++++++++++++++++
security/apparmor/apparmor.h | 279 +++++++++++++++++++++++++++++++++++++++++
security/apparmor/apparmorfs.c | 248 ++++++++++++++++++++++++++++++++++++
security/apparmor/inline.h | 219 +++++++++++++++++++++++++++++++
security/apparmor/inline.h | 219 ++++++++++++++++++++++++++++++++
security/apparmor/list.c | 94 +++++++++++++
security/apparmor/locking.txt | 59 ++++++++
security/apparmor/procattr.c | 143 ++++++++++++++++++++
8 files changed, 1067 insertions(+)
security/apparmor/procattr.c | 143 +++++++++++++++++++++
8 files changed, 1064 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,282 @@
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 1998-2007 Novell/SUSE
+ *
@@ -217,15 +217,12 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ 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;
+ };
+};
@@ -277,8 +274,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+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);

View File

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

View File

@@ -10,8 +10,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/apparmor/match.c | 232 ++++++++++++
security/apparmor/match.h | 83 ++++
security/apparmor/module_interface.c | 641 +++++++++++++++++++++++++++++++++++
3 files changed, 956 insertions(+)
security/apparmor/module_interface.c | 643 +++++++++++++++++++++++++++++++++++
3 files changed, 958 insertions(+)
--- /dev/null
+++ b/security/apparmor/match.c
@@ -41,9 +41,9 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ 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 ||
@@ -59,13 +59,13 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ *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:
@@ -316,7 +316,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ 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 { \
@@ -336,7 +336,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+#endif /* __MATCH_H */
--- /dev/null
+++ b/security/apparmor/module_interface.c
@@ -0,0 +1,641 @@
@@ -0,0 +1,643 @@
+/*
+ * 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)
+{
+ 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
+ * @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;
+
@@ -623,9 +623,11 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+
+ /* 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;
@@ -659,7 +661,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ */
+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;

View File

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

View File

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

View File

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

View File

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

View File

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

View 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)
{

View File

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

View File

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

View File

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

View File

@@ -39,30 +39,23 @@ proc-mounts-cleanup.diff
# fix-d_path.diff
file-handle-ops.diff
security-xattr-file.diff
sysctl-pathname.diff
export-get_task_comm.diff
apparmor-audit.diff
apparmor-main.diff
apparmor-main-2.diff
mangle.diff
apparmor-lsm.diff
apparmor-lsm-2.diff
drop_CLONE_NEWNS_restriction.diff
apparmor-ns-ptrace.diff
apparmor-module_interface.diff
apparmor-module_interface-2.diff
apparmor-misc.diff
audit-cleanup.diff
comm.diff
ecryptfs-d_revalidate.diff
nfs-nameidata-check.diff
apparmor-intree.diff
sysctl-pathname.diff
ecryptfs-d_revalidate.diff
apparmor-sysctl-pathname.diff
vfs_create-nameidata.diff
do_path_lookup-nameidata.diff
sys_fchdir-nameidata.diff
nfsd_permission-nameidata.diff
file_permission-nameidata.diff
kconfig-dependencies.diff
# NOT YET
nfs-nameidata-check.diff
split-up-nameidata.diff
# xattr_permission.diff
# vfs_create-args.diff

View File

@@ -2347,7 +2347,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+/**
+ * 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.
+ */
+#define __NAMEIDATA2 \