diff --git a/debian/changelog b/debian/changelog index f978aa3d8..95fcff5af 100644 --- a/debian/changelog +++ b/debian/changelog @@ -26,6 +26,7 @@ linux-2.6 (3.2.19-1) UNRELEASED; urgency=low * [x86] udeb: Add hyperv-modules containing Hyper-V paravirtualised drivers * [x86] ata_piix: defer disks to the Hyper-V drivers by default * [x86] drm/i915:: Disable FBC on SandyBridge (Closes: #675022) + * AppArmor: compatibility patch for v5 interface (Closes: #661151) -- Ben Hutchings Sun, 27 May 2012 01:12:44 +0100 diff --git a/debian/config/config b/debian/config/config index 90459d49a..e62fda784 100644 --- a/debian/config/config +++ b/debian/config/config @@ -4680,6 +4680,7 @@ CONFIG_DEFAULT_SECURITY_DAC=y ## CONFIG_SECURITY_APPARMOR=y CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_APPARMOR_COMPAT_24=y ## ## file: security/integrity/ima/Kconfig diff --git a/debian/patches/features/all/AppArmor-compatibility-patch-for-v5-interface.patch b/debian/patches/features/all/AppArmor-compatibility-patch-for-v5-interface.patch new file mode 100644 index 000000000..b8d1f1aac --- /dev/null +++ b/debian/patches/features/all/AppArmor-compatibility-patch-for-v5-interface.patch @@ -0,0 +1,381 @@ +From: John Johansen +Date: Wed, 10 Aug 2011 22:02:40 -0700 +Subject: AppArmor: compatibility patch for v5 interface + +commit 004192fb5223c7b81a949e36a080a5da56132826 in +git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor + +Signed-off-by: John Johansen +[bwh: Fix up context to apply without the v5 network control interface; + fix unmatched aafs_create() when CONFIG_SECURITY_APPARMOR_COMPAT_24 not set] +--- + security/apparmor/Kconfig | 9 + + security/apparmor/Makefile | 1 + + security/apparmor/apparmorfs-24.c | 287 ++++++++++++++++++++++++++++++++ + security/apparmor/apparmorfs.c | 18 +- + security/apparmor/include/apparmorfs.h | 6 + + 5 files changed, 319 insertions(+), 2 deletions(-) + create mode 100644 security/apparmor/apparmorfs-24.c + +--- a/security/apparmor/Kconfig ++++ b/security/apparmor/Kconfig +@@ -29,3 +29,12 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE + boot. + + If you are unsure how to answer this question, answer 1. ++ ++config SECURITY_APPARMOR_COMPAT_24 ++ bool "Enable AppArmor 2.4 compatability" ++ depends on SECURITY_APPARMOR ++ default y ++ help ++ This option enables compatability with AppArmor 2.4. It is ++ recommended if compatability with older versions of AppArmor ++ is desired. +--- a/security/apparmor/Makefile ++++ b/security/apparmor/Makefile +@@ -5,6 +5,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o + apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ + path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ + resource.o sid.o file.o ++apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o + + clean-files := capability_names.h rlim_names.h + +--- /dev/null ++++ b/security/apparmor/apparmorfs-24.c +@@ -0,0 +1,287 @@ ++/* ++ * AppArmor security module ++ * ++ * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions ++ * ++ * Copyright (C) 1998-2008 Novell/SUSE ++ * Copyright 2009-2010 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation, version 2 of the ++ * License. ++ * ++ * ++ * This file contain functions providing an interface for <= AppArmor 2.4 ++ * compatibility. It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24 ++ * being set (see Makefile). ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "include/apparmor.h" ++#include "include/audit.h" ++#include "include/context.h" ++#include "include/policy.h" ++ ++ ++/* apparmor/matching */ ++static ssize_t aa_matching_read(struct file *file, char __user *buf, ++ size_t size, loff_t *ppos) ++{ ++ const char matching[] = "pattern=aadfa audit perms=crwxamlk/ " ++ "user::other"; ++ ++ return simple_read_from_buffer(buf, size, ppos, matching, ++ sizeof(matching) - 1); ++} ++ ++const struct file_operations aa_fs_matching_fops = { ++ .read = aa_matching_read, ++}; ++ ++/* apparmor/features */ ++static ssize_t aa_features_read(struct file *file, char __user *buf, ++ size_t size, loff_t *ppos) ++{ ++ const char features[] = "file=3.1 capability=2.0 network=1.0 " ++ "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1"; ++ ++ return simple_read_from_buffer(buf, size, ppos, features, ++ sizeof(features) - 1); ++} ++ ++const struct file_operations aa_fs_features_fops = { ++ .read = aa_features_read, ++}; ++ ++/** ++ * __next_namespace - find the next namespace to list ++ * @root: root namespace to stop search at (NOT NULL) ++ * @ns: current ns position (NOT NULL) ++ * ++ * Find the next namespace from @ns under @root and handle all locking needed ++ * while switching current namespace. ++ * ++ * Returns: next namespace or NULL if at last namespace under @root ++ * NOTE: will not unlock root->lock ++ */ ++static struct aa_namespace *__next_namespace(struct aa_namespace *root, ++ struct aa_namespace *ns) ++{ ++ struct aa_namespace *parent; ++ ++ /* is next namespace a child */ ++ if (!list_empty(&ns->sub_ns)) { ++ struct aa_namespace *next; ++ next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list); ++ read_lock(&next->lock); ++ return next; ++ } ++ ++ /* check if the next ns is a sibling, parent, gp, .. */ ++ parent = ns->parent; ++ while (parent) { ++ read_unlock(&ns->lock); ++ list_for_each_entry_continue(ns, &parent->sub_ns, base.list) { ++ read_lock(&ns->lock); ++ return ns; ++ } ++ if (parent == root) ++ return NULL; ++ ns = parent; ++ parent = parent->parent; ++ } ++ ++ return NULL; ++} ++ ++/** ++ * __first_profile - find the first profile in a namespace ++ * @root: namespace that is root of profiles being displayed (NOT NULL) ++ * @ns: namespace to start in (NOT NULL) ++ * ++ * Returns: unrefcounted profile or NULL if no profile ++ */ ++static struct aa_profile *__first_profile(struct aa_namespace *root, ++ struct aa_namespace *ns) ++{ ++ for ( ; ns; ns = __next_namespace(root, ns)) { ++ if (!list_empty(&ns->base.profiles)) ++ return list_first_entry(&ns->base.profiles, ++ struct aa_profile, base.list); ++ } ++ return NULL; ++} ++ ++/** ++ * __next_profile - step to the next profile in a profile tree ++ * @profile: current profile in tree (NOT NULL) ++ * ++ * Perform a depth first taversal on the profile tree in a namespace ++ * ++ * Returns: next profile or NULL if done ++ * Requires: profile->ns.lock to be held ++ */ ++static struct aa_profile *__next_profile(struct aa_profile *p) ++{ ++ struct aa_profile *parent; ++ struct aa_namespace *ns = p->ns; ++ ++ /* is next profile a child */ ++ if (!list_empty(&p->base.profiles)) ++ return list_first_entry(&p->base.profiles, typeof(*p), ++ base.list); ++ ++ /* is next profile a sibling, parent sibling, gp, subling, .. */ ++ parent = p->parent; ++ while (parent) { ++ list_for_each_entry_continue(p, &parent->base.profiles, ++ base.list) ++ return p; ++ p = parent; ++ parent = parent->parent; ++ } ++ ++ /* is next another profile in the namespace */ ++ list_for_each_entry_continue(p, &ns->base.profiles, base.list) ++ return p; ++ ++ return NULL; ++} ++ ++/** ++ * next_profile - step to the next profile in where ever it may be ++ * @root: root namespace (NOT NULL) ++ * @profile: current profile (NOT NULL) ++ * ++ * Returns: next profile or NULL if there isn't one ++ */ ++static struct aa_profile *next_profile(struct aa_namespace *root, ++ struct aa_profile *profile) ++{ ++ struct aa_profile *next = __next_profile(profile); ++ if (next) ++ return next; ++ ++ /* finished all profiles in namespace move to next namespace */ ++ return __first_profile(root, __next_namespace(root, profile->ns)); ++} ++ ++/** ++ * p_start - start a depth first traversal of profile tree ++ * @f: seq_file to fill ++ * @pos: current position ++ * ++ * Returns: first profile under current namespace or NULL if none found ++ * ++ * acquires first ns->lock ++ */ ++static void *p_start(struct seq_file *f, loff_t *pos) ++ __acquires(root->lock) ++{ ++ struct aa_profile *profile = NULL; ++ struct aa_namespace *root = aa_current_profile()->ns; ++ loff_t l = *pos; ++ f->private = aa_get_namespace(root); ++ ++ ++ /* find the first profile */ ++ read_lock(&root->lock); ++ profile = __first_profile(root, root); ++ ++ /* skip to position */ ++ for (; profile && l > 0; l--) ++ profile = next_profile(root, profile); ++ ++ return profile; ++} ++ ++/** ++ * p_next - read the next profile entry ++ * @f: seq_file to fill ++ * @p: profile previously returned ++ * @pos: current position ++ * ++ * Returns: next profile after @p or NULL if none ++ * ++ * may acquire/release locks in namespace tree as necessary ++ */ ++static void *p_next(struct seq_file *f, void *p, loff_t *pos) ++{ ++ struct aa_profile *profile = p; ++ struct aa_namespace *root = f->private; ++ (*pos)++; ++ ++ return next_profile(root, profile); ++} ++ ++/** ++ * p_stop - stop depth first traversal ++ * @f: seq_file we are filling ++ * @p: the last profile writen ++ * ++ * Release all locking done by p_start/p_next on namespace tree ++ */ ++static void p_stop(struct seq_file *f, void *p) ++ __releases(root->lock) ++{ ++ struct aa_profile *profile = p; ++ struct aa_namespace *root = f->private, *ns; ++ ++ if (profile) { ++ for (ns = profile->ns; ns && ns != root; ns = ns->parent) ++ read_unlock(&ns->lock); ++ } ++ read_unlock(&root->lock); ++ aa_put_namespace(root); ++} ++ ++/** ++ * seq_show_profile - show a profile entry ++ * @f: seq_file to file ++ * @p: current position (profile) (NOT NULL) ++ * ++ * Returns: error on failure ++ */ ++static int seq_show_profile(struct seq_file *f, void *p) ++{ ++ struct aa_profile *profile = (struct aa_profile *)p; ++ struct aa_namespace *root = f->private; ++ ++ if (profile->ns != root) ++ seq_printf(f, ":%s://", aa_ns_name(root, profile->ns)); ++ seq_printf(f, "%s (%s)\n", profile->base.hname, ++ COMPLAIN_MODE(profile) ? "complain" : "enforce"); ++ ++ return 0; ++} ++ ++static const struct seq_operations aa_fs_profiles_op = { ++ .start = p_start, ++ .next = p_next, ++ .stop = p_stop, ++ .show = seq_show_profile, ++}; ++ ++static int profiles_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &aa_fs_profiles_op); ++} ++ ++static int profiles_release(struct inode *inode, struct file *file) ++{ ++ return seq_release(inode, file); ++} ++ ++const struct file_operations aa_fs_profiles_fops = { ++ .open = profiles_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = profiles_release, ++}; +--- a/security/apparmor/apparmorfs.c ++++ b/security/apparmor/apparmorfs.c +@@ -187,7 +187,11 @@ void __init aa_destroy_aafs(void) + aafs_remove(".remove"); + aafs_remove(".replace"); + aafs_remove(".load"); +- ++#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24 ++ aafs_remove("profiles"); ++ aafs_remove("matching"); ++ aafs_remove("features"); ++#endif + securityfs_remove(aa_fs_dentry); + aa_fs_dentry = NULL; + } +@@ -218,7 +222,17 @@ static int __init aa_create_aafs(void) + aa_fs_dentry = NULL; + goto error; + } +- ++#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24 ++ error = aafs_create("matching", 0444, &aa_fs_matching_fops); ++ if (error) ++ goto error; ++ error = aafs_create("features", 0444, &aa_fs_features_fops); ++ if (error) ++ goto error; ++ error = aafs_create("profiles", 0440, &aa_fs_profiles_fops); ++ if (error) ++ goto error; ++#endif + error = aafs_create(".load", 0640, &aa_fs_profile_load); + if (error) + goto error; +--- a/security/apparmor/include/apparmorfs.h ++++ b/security/apparmor/include/apparmorfs.h +@@ -17,4 +17,10 @@ + + extern void __init aa_destroy_aafs(void); + ++#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24 ++extern const struct file_operations aa_fs_matching_fops; ++extern const struct file_operations aa_fs_features_fops; ++extern const struct file_operations aa_fs_profiles_fops; ++#endif ++ + #endif /* __AA_APPARMORFS_H */ diff --git a/debian/patches/series/base b/debian/patches/series/base index 6ec769faf..ff71984dd 100644 --- a/debian/patches/series/base +++ b/debian/patches/series/base @@ -299,3 +299,6 @@ + features/all/codel/0007-fq_codel-should-use-qdisc-backlog-as-threshold.patch + bugfix/all/drm-i915-Disable-FBC-on-SandyBridge.patch + +# AppArmor userland compatibility. This had better be gone in wheezy+1! ++ features/all/AppArmor-compatibility-patch-for-v5-interface.patch