diff --git a/kernel-patches/for-mainline/apparmor-intree.diff b/kernel-patches/for-mainline/apparmor-intree.diff index 5de19db52..32ffe28be 100644 --- a/kernel-patches/for-mainline/apparmor-intree.diff +++ b/kernel-patches/for-mainline/apparmor-intree.diff @@ -5,9 +5,10 @@ Signed-off-by: John Johansen Signed-off-by: Andreas Gruenbacher --- - 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 +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 diff --git a/kernel-patches/for-mainline/apparmor-lsm-2.diff b/kernel-patches/for-mainline/apparmor-lsm-2.diff deleted file mode 100644 index 5c93d38de..000000000 --- a/kernel-patches/for-mainline/apparmor-lsm-2.diff +++ /dev/null @@ -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, diff --git a/kernel-patches/for-mainline/apparmor-lsm.diff b/kernel-patches/for-mainline/apparmor-lsm.diff index 0551eb86a..d3ee8e04b 100644 --- a/kernel-patches/for-mainline/apparmor-lsm.diff +++ b/kernel-patches/for-mainline/apparmor-lsm.diff @@ -7,12 +7,12 @@ Signed-off-by: John Johansen Signed-off-by: Andreas Gruenbacher --- - security/apparmor/lsm.c | 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 + /** + * 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 + 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 +} + +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 + 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 + 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 + 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 + 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 + +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 + .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, diff --git a/kernel-patches/for-mainline/apparmor-main-2.diff b/kernel-patches/for-mainline/apparmor-main-2.diff deleted file mode 100644 index b26bd3dbf..000000000 --- a/kernel-patches/for-mainline/apparmor-main-2.diff +++ /dev/null @@ -1,54 +0,0 @@ -From: Andreas Gruenbacher -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)); - } - - /** diff --git a/kernel-patches/for-mainline/apparmor-main.diff b/kernel-patches/for-mainline/apparmor-main.diff index 4fad03cd1..fc9f9a69a 100644 --- a/kernel-patches/for-mainline/apparmor-main.diff +++ b/kernel-patches/for-mainline/apparmor-main.diff @@ -7,12 +7,12 @@ Signed-off-by: John Johansen Signed-off-by: Andreas Gruenbacher --- - security/apparmor/main.c | 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 + */ +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 +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 +} + +/** ++ * 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 + 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 + 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 + + 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 + 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 + (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 + error = 0; + else + error = sa->result ? 0 : opspec_error; -+ +out: + return error; +} @@ -564,7 +585,7 @@ Signed-off-by: Andreas Gruenbacher + 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 + * @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 + 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 + 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 + 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; +} diff --git a/kernel-patches/for-mainline/apparmor-misc.diff b/kernel-patches/for-mainline/apparmor-misc.diff index 23377d6ac..bf978a268 100644 --- a/kernel-patches/for-mainline/apparmor-misc.diff +++ b/kernel-patches/for-mainline/apparmor-misc.diff @@ -13,13 +13,13 @@ Signed-off-by: Andreas Gruenbacher --- security/apparmor/Kconfig | 9 + security/apparmor/Makefile | 13 + - security/apparmor/apparmor.h | 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 + $(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 + 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 +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); diff --git a/kernel-patches/for-mainline/apparmor-module_interface-2.diff b/kernel-patches/for-mainline/apparmor-module_interface-2.diff deleted file mode 100644 index 00b5829e0..000000000 --- a/kernel-patches/for-mainline/apparmor-module_interface-2.diff +++ /dev/null @@ -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; diff --git a/kernel-patches/for-mainline/apparmor-module_interface.diff b/kernel-patches/for-mainline/apparmor-module_interface.diff index eb4c0bff3..3579d2bad 100644 --- a/kernel-patches/for-mainline/apparmor-module_interface.diff +++ b/kernel-patches/for-mainline/apparmor-module_interface.diff @@ -10,8 +10,8 @@ Signed-off-by: Andreas Gruenbacher --- 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 + 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 + *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 + 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 +#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 + +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 + * @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 + + /* 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 + */ +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; diff --git a/kernel-patches/for-mainline/apparmor-ns-ptrace.diff b/kernel-patches/for-mainline/apparmor-ns-ptrace.diff deleted file mode 100644 index ec95968e6..000000000 --- a/kernel-patches/for-mainline/apparmor-ns-ptrace.diff +++ /dev/null @@ -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; diff --git a/kernel-patches/for-mainline/audit-cleanup.diff b/kernel-patches/for-mainline/audit-cleanup.diff deleted file mode 100644 index 49bbd3cbb..000000000 --- a/kernel-patches/for-mainline/audit-cleanup.diff +++ /dev/null @@ -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; - } diff --git a/kernel-patches/for-mainline/comm.diff b/kernel-patches/for-mainline/comm.diff deleted file mode 100644 index 47e58d79d..000000000 --- a/kernel-patches/for-mainline/comm.diff +++ /dev/null @@ -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) - { diff --git a/kernel-patches/for-mainline/complain-to-learn.diff b/kernel-patches/for-mainline/complain-to-learn.diff deleted file mode 100644 index c33870d14..000000000 --- a/kernel-patches/for-mainline/complain-to-learn.diff +++ /dev/null @@ -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) + diff --git a/kernel-patches/for-mainline/drop_CLONE_NEWNS_restriction.diff b/kernel-patches/for-mainline/drop_CLONE_NEWNS_restriction.diff deleted file mode 100644 index e810fecc2..000000000 --- a/kernel-patches/for-mainline/drop_CLONE_NEWNS_restriction.diff +++ /dev/null @@ -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, diff --git a/kernel-patches/for-mainline/export-get_task_comm.diff b/kernel-patches/for-mainline/export-get_task_comm.diff new file mode 100644 index 000000000..064f526c5 --- /dev/null +++ b/kernel-patches/for-mainline/export-get_task_comm.diff @@ -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) + { diff --git a/kernel-patches/for-mainline/kconfig-dependencies.diff b/kernel-patches/for-mainline/kconfig-dependencies.diff deleted file mode 100644 index b462c0443..000000000 --- a/kernel-patches/for-mainline/kconfig-dependencies.diff +++ /dev/null @@ -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 diff --git a/kernel-patches/for-mainline/mangle.diff b/kernel-patches/for-mainline/mangle.diff deleted file mode 100644 index e72fca2ab..000000000 --- a/kernel-patches/for-mainline/mangle.diff +++ /dev/null @@ -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) diff --git a/kernel-patches/for-mainline/mount-consistent-d_path.diff b/kernel-patches/for-mainline/mount-consistent-d_path.diff deleted file mode 100644 index 9312385c6..000000000 --- a/kernel-patches/for-mainline/mount-consistent-d_path.diff +++ /dev/null @@ -1,61 +0,0 @@ -From: Andreas Gruenbacher -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 - ---- - 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; - diff --git a/kernel-patches/for-mainline/series b/kernel-patches/for-mainline/series index bf2af582b..7c8f7daec 100644 --- a/kernel-patches/for-mainline/series +++ b/kernel-patches/for-mainline/series @@ -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 diff --git a/kernel-patches/for-mainline/split-up-nameidata.diff b/kernel-patches/for-mainline/split-up-nameidata.diff index 90cba40bc..4e65954f9 100644 --- a/kernel-patches/for-mainline/split-up-nameidata.diff +++ b/kernel-patches/for-mainline/split-up-nameidata.diff @@ -2347,7 +2347,7 @@ Signed-off-by: Andreas Gruenbacher +/** + * 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 \