Author: arekm Date: Tue Mar 16 21:15:44 2010 GMT Module: packages Tag: HEAD ---- Log message: - up apparmor to 2.5
---- Files affected: packages/kernel: kernel-apparmor.patch (1.6 -> 1.7) , kernel.spec (1.776 -> 1.777) ---- Diffs: ================================================================ Index: packages/kernel/kernel-apparmor.patch diff -u packages/kernel/kernel-apparmor.patch:1.6 packages/kernel/kernel-apparmor.patch:1.7 --- packages/kernel/kernel-apparmor.patch:1.6 Tue Nov 3 20:57:25 2009 +++ packages/kernel/kernel-apparmor.patch Tue Mar 16 22:15:38 2010 @@ -1,17 +1,7 @@ -diff -urN linux-2.6.31.org/Documentation/kernel-parameters.txt linux-2.6.31/Documentation/kernel-parameters.txt ---- linux-2.6.31.org/Documentation/kernel-parameters.txt 2009-09-10 00:13:59.000000000 +0200 -+++ linux-2.6.31/Documentation/kernel-parameters.txt 2009-09-10 22:17:58.000000000 +0200 -@@ -90,6 +90,7 @@ - A lot of drivers has their options described inside of - Documentation/scsi/. - SECURITY Different security models are enabled. -+ SECURITY_DEFAULT set a default security module - SELINUX SELinux support is enabled. - SERIAL Serial support is enabled. - SH SuperH architecture is enabled. -diff -urN linux-2.6.31.org/include/linux/audit.h linux-2.6.31/include/linux/audit.h ---- linux-2.6.31.org/include/linux/audit.h 2009-09-10 00:13:59.000000000 +0200 -+++ linux-2.6.31/include/linux/audit.h 2009-09-10 22:18:05.000000000 +0200 +diff --git a/include/linux/audit.h b/include/linux/audit.h +index 3c7a358..a1db25b 100644 +--- a/include/linux/audit.h ++++ b/include/linux/audit.h @@ -33,7 +33,7 @@ * 1200 - 1299 messages internal to the audit daemon * 1300 - 1399 audit event messages @@ -36,10 +26,11 @@ #define AUDIT_FIRST_KERN_ANOM_MSG 1700 #define AUDIT_LAST_KERN_ANOM_MSG 1799 #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ -diff -urN linux-2.6.31.org/security/Kconfig linux-2.6.31/security/Kconfig ---- linux-2.6.31.org/security/Kconfig 2009-09-10 00:13:59.000000000 +0200 -+++ linux-2.6.31/security/Kconfig 2009-09-11 08:37:07.888942907 +0200 -@@ -132,6 +132,7 @@ +diff --git a/security/Kconfig b/security/Kconfig +index 226b955..bd72ae6 100644 +--- a/security/Kconfig ++++ b/security/Kconfig +@@ -140,6 +140,7 @@ config LSM_MMAP_MIN_ADDR source security/selinux/Kconfig source security/smack/Kconfig source security/tomoyo/Kconfig @@ -47,22 +38,162 @@ source security/integrity/ima/Kconfig -diff -urN kernel.org/security/apparmor/apparmorfs.c kernel/security/apparmor/apparmorfs.c ---- kernel.org/security/apparmor/apparmorfs.c 1970-01-01 01:00:00.000000000 +0100 -+++ kernel/security/apparmor/apparmorfs.c 2009-09-10 22:18:06.000000000 +0200 -@@ -0,0 +1,391 @@ +@@ -148,6 +149,7 @@ choice + default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX + default DEFAULT_SECURITY_SMACK if SECURITY_SMACK + default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO ++ default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR + default DEFAULT_SECURITY_DAC + + help +@@ -163,6 +165,9 @@ choice + config DEFAULT_SECURITY_TOMOYO + bool "TOMOYO" if SECURITY_TOMOYO=y + ++ config DEFAULT_SECURITY_APPARMOR ++ bool "AppArmor" if SECURITY_APPARMOR=y ++ + config DEFAULT_SECURITY_DAC + bool "Unix Discretionary Access Controls" + +@@ -173,6 +178,7 @@ config DEFAULT_SECURITY + default "selinux" if DEFAULT_SECURITY_SELINUX + default "smack" if DEFAULT_SECURITY_SMACK + default "tomoyo" if DEFAULT_SECURITY_TOMOYO ++ default "apparmor" if DEFAULT_SECURITY_APPARMOR + default "" if DEFAULT_SECURITY_DAC + + endmenu +diff --git a/security/Makefile b/security/Makefile +index da20a19..8bb0fe9 100644 +--- a/security/Makefile ++++ b/security/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_KEYS) += keys/ + subdir-$(CONFIG_SECURITY_SELINUX) += selinux + subdir-$(CONFIG_SECURITY_SMACK) += smack + subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo ++subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor + + # always enable default capabilities + obj-y += commoncap.o +@@ -19,6 +20,7 @@ obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o + obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o + obj-$(CONFIG_AUDIT) += lsm_audit.o + obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o ++obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o + obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o + + # Object integrity file lists +diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore +new file mode 100644 +index 0000000..0a0a99f +--- /dev/null ++++ b/security/apparmor/.gitignore +@@ -0,0 +1,5 @@ ++# ++# Generated include files ++# ++af_names.h ++capability_names.h +diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig +new file mode 100644 +index 0000000..5c57df7 +--- /dev/null ++++ b/security/apparmor/Kconfig +@@ -0,0 +1,40 @@ ++config SECURITY_APPARMOR ++ bool "AppArmor support" ++ depends on SECURITY ++ select AUDIT ++ select SECURITY_PATH ++ select SECURITYFS ++ select SECURITY_NETWORK ++ default n ++ help ++ This enables the AppArmor security module. ++ Required userspace tools (if they are not included in your ++ distribution) and further information may be found at ++ <http://forge.novell.com/modules/xfmod/project/?apparmor> ++ ++ If you are unsure how to answer this question, answer N. ++ ++config SECURITY_APPARMOR_BOOTPARAM_VALUE ++ int "AppArmor boot parameter default value" ++ depends on SECURITY_APPARMOR ++ range 0 1 ++ default 1 ++ help ++ This option sets the default value for the kernel parameter ++ 'apparmor', which allows AppArmor to be enabled or disabled ++ at boot. If this option is set to 0 (zero), the AppArmor ++ kernel parameter will default to 0, disabling AppArmor at ++ bootup. If this option is set to 1 (one), the AppArmor ++ kernel parameter will default to 1, enabling AppArmor at ++ bootup. ++ ++ 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. +diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile +new file mode 100644 +index 0000000..554cba7 +--- /dev/null ++++ b/security/apparmor/Makefile +@@ -0,0 +1,24 @@ ++# Makefile for AppArmor Linux Security Module ++# ++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 net.o ++ ++apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o ++ ++clean-files: capability_names.h af_names.h ++ ++quiet_cmd_make-caps = GEN $@ ++cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ++ ++quiet_cmd_make-af = GEN $@ ++cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ; sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ++ ++$(obj)/capability.o : $(obj)/capability_names.h ++$(obj)/net.o : $(obj)/af_names.h ++$(obj)/capability_names.h : $(srctree)/include/linux/capability.h ++ $(call cmd,make-caps) ++$(obj)/af_names.h : $(srctree)/include/linux/socket.h ++ $(call cmd,make-af) +diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c +new file mode 100644 +index 0000000..f64aae8 +--- /dev/null ++++ b/security/apparmor/apparmorfs-24.c +@@ -0,0 +1,61 @@ +/* + * AppArmor security module + * -+ * This file contains AppArmor /proc/<pid>/attr interface functions ++ * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions + * + * Copyright (C) 1998-2008 Novell/SUSE -+ * Copyright 2009 Canonical Ltd. ++ * 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 <linux/security.h> @@ -76,14 +207,124 @@ +#include "include/audit.h" +#include "include/context.h" +#include "include/policy.h" -+#include "include/policy_interface.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, ++}; +diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c +new file mode 100644 +index 0000000..89a26a0 +--- /dev/null ++++ b/security/apparmor/apparmorfs.c +@@ -0,0 +1,561 @@ ++/* ++ * AppArmor security module ++ * ++ * This file contains AppArmor /sys/kernel/security/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. ++ */ ++ ++#include <linux/security.h> ++#include <linux/vmalloc.h> ++#include <linux/module.h> ++#include <linux/seq_file.h> ++#include <linux/uaccess.h> ++#include <linux/namei.h> ++ ++#include "include/apparmor.h" ++#include "include/apparmorfs.h" ++#include "include/audit.h" ++#include "include/context.h" ++#include "include/policy.h" ++ ++/** ++ * kvmalloc - do allocation prefering kmalloc but falling back to vmalloc ++ * @size: size of allocation ++ * ++ * Return: allocated buffer or NULL if failed ++ * ++ * It is possible that policy being loaded from the user is larger than ++ * what can be allocated by kmalloc, in those cases fall back to vmalloc. ++ */ ++static void *kvmalloc(size_t size) ++{ ++ void *buffer; ++ ++ if (size == 0) ++ return NULL; ++ ++ buffer = kmalloc(size, GFP_KERNEL); ++ if (!buffer) ++ buffer = vmalloc(size); ++ return buffer; ++} ++ ++/** ++ * kvfree - free an allocation do by kvmalloc ++ * @buffer: buffer to free ++ * ++ * Free a buffer allocated by kvmalloc ++ */ ++static void kvfree(void *buffer) ++{ ++ if (!buffer) ++ return; ++ ++ if (is_vmalloc_addr(buffer)) ++ vfree(buffer); ++ else ++ kfree(buffer); ++} ++ ++/** ++ * aa_simple_write_to_buffer - common routine for getting policy from user ++ * @userbuf: user buffer to copy data from (NOT NULL) ++ * @alloc_size: size of user buffer ++ * @copy_size: size of data to copy from user buffer ++ * @pos: position write is at in the file ++ * @operation: name of operation doing the user buffer copy (NOT NULL) ++ * ++ * Returns: kernel buffer containing copy of user buffer data or an ++ * ERR_PTR on failure. ++ */ +static char *aa_simple_write_to_buffer(const char __user *userbuf, + size_t alloc_size, size_t copy_size, + loff_t *pos, const char *operation) +{ -+ const struct cred *cred; -+ struct aa_profile *profile; + char *data; + + if (*pos != 0) { @@ -93,30 +334,30 @@ + } + + /* -+ * Don't allow confined processes to load/replace/remove profiles. -+ * No sane person would add rules allowing this to a profile -+ * but we enforce the restriction anyways. ++ * Don't allow profile load/replace/remove from profiles that don't ++ * have CAP_MAC_ADMIN + */ -+ cred = aa_current_policy(&profile); -+ if (profile) { -+ struct aa_audit sa; -+ memset(&sa, 0, sizeof(sa)); -+ sa.operation = operation; -+ sa.gfp_mask = GFP_KERNEL; -+ sa.error = -EACCES; ++ if (!capable(CAP_MAC_ADMIN)) { ++ struct aa_profile *profile = NULL; ++ struct aa_audit sa = { ++ .operation = operation, ++ .gfp_mask = GFP_KERNEL, ++ .error = -EACCES, ++ }; ++ profile = aa_current_profile(); + data = ERR_PTR(aa_audit(AUDIT_APPARMOR_DENIED, profile, &sa, + NULL)); + goto out; + } -+ -+ data = vmalloc(alloc_size); ++ /* freed by caller to aa_simple_write_to_buffer */ ++ data = kvmalloc(alloc_size); + if (data == NULL) { + data = ERR_PTR(-ENOMEM); + goto out; + } + + if (copy_from_user(data, userbuf, copy_size)) { -+ vfree(data); ++ kvfree(data); + data = ERR_PTR(-EFAULT); + goto out; + } @@ -125,334 +366,458 @@ + return data; +} + -+static struct aa_profile *next_profile(struct aa_profile *profile) ++ ++/* .load file hook fn to load policy */ ++static ssize_t aa_profile_load(struct file *f, const char __user *buf, ++ size_t size, loff_t *pos) +{ -+ struct aa_profile *parent; -+ struct aa_namespace *ns = profile->ns; ++ char *data; ++ ssize_t error; + -+ if (!list_empty(&profile->base.profiles)) -+ return list_first_entry(&profile->base.profiles, -+ struct aa_profile, base.list); ++ data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load"); + -+ parent = profile->parent; -+ while (parent) { -+ list_for_each_entry_continue(profile, &parent->base.profiles, -+ base.list) -+ return profile; -+ profile = parent; -+ parent = parent->parent; ++ error = PTR_ERR(data); ++ if (!IS_ERR(data)) { ++ error = aa_interface_replace_profiles(data, size, 1); ++ kvfree(data); + } + -+ list_for_each_entry_continue(profile, &ns->base.profiles, base.list) -+ return profile; -+ -+ read_unlock(&ns->base.lock); -+ list_for_each_entry_continue(ns, &ns_list, base.list) { -+ read_lock(&ns->base.lock); -+ return list_first_entry(&ns->base.profiles, struct aa_profile, -+ base.list); -+ read_unlock(&ns->base.lock); -+ } -+ return NULL; ++ return error; +} + -+static void *p_start(struct seq_file *f, loff_t *pos) -+ __acquires(ns_list_lock) ++static const struct file_operations aa_fs_profile_load = { ++ .write = aa_profile_load ++}; ++ ++/* .replace file hook fn to load and/or replace policy */ ++static ssize_t aa_profile_replace(struct file *f, const char __user *buf, ++ size_t size, loff_t *pos) +{ -+ struct aa_namespace *ns; -+ loff_t l = *pos; ++ char *data; ++ ssize_t error; + -+ read_lock(&ns_list_lock); -+ if (!list_empty(&ns_list)) { -+ struct aa_profile *profile = NULL; -+ ns = list_first_entry(&ns_list, typeof(*ns), base.list); -+ read_lock(&ns->base.lock); -+ if (!list_empty(&ns->base.profiles)) { -+ profile = list_first_entry(&ns->base.profiles, -+ typeof(*profile), base.list); -+ for ( ; profile && l > 0; l--) -+ profile = next_profile(profile); -+ return profile; -+ } else -+ read_unlock(&ns->base.lock); ++ data = aa_simple_write_to_buffer(buf, size, size, pos, ++ "profile_replace"); ++ error = PTR_ERR(data); ++ if (!IS_ERR(data)) { ++ error = aa_interface_replace_profiles(data, size, 0); ++ kvfree(data); + } -+ return NULL; ++ ++ return error; +} + -+static void *p_next(struct seq_file *f, void *p, loff_t *pos) ++static const struct file_operations aa_fs_profile_replace = { ++ .write = aa_profile_replace ++}; ++ ++/* .remove file hook fn to remove loaded policy */ ++static ssize_t aa_profile_remove(struct file *f, const char __user *buf, ++ size_t size, loff_t *pos) +{ -+ struct aa_profile *profile = (struct aa_profile *) p; ++ char *data; ++ ssize_t error; + -+ (*pos)++; -+ profile = next_profile(profile); ++ /* ++ * aa_remove_profile needs a null terminated string so 1 extra ++ * byte is allocated and the copied data is null terminated. ++ */ ++ data = aa_simple_write_to_buffer(buf, size + 1, size, pos, ++ "profile_remove"); + -+ return profile; ++ error = PTR_ERR(data); ++ if (!IS_ERR(data)) { ++ data[size] = 0; ++ error = aa_interface_remove_profiles(data, size); ++ kvfree(data); ++ } ++ ++ return error; +} + -+static void p_stop(struct seq_file *f, void *p) -+ __releases(ns_list_lock) ++static const struct file_operations aa_fs_profile_remove = { ++ .write = aa_profile_remove ++}; ++ ++ ++/** ++ * __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_profile *profile = (struct aa_profile *) p; ++ struct aa_namespace *parent; + -+ if (profile) -+ read_unlock(&profile->ns->base.lock); -+ read_unlock(&ns_list_lock); ++ /* 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; +} + -+static void print_name(struct seq_file *f, struct aa_profile *profile) -+{ -+ if (profile->parent) { -+ print_name(f, profile->parent); -+ seq_printf(f, "//"); ++/** ++ * __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); + } -+ seq_printf(f, "%s", profile->base.name); ++ return NULL; +} + -+static int seq_show_profile(struct seq_file *f, void *p) ++/** ++ * __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 *profile = (struct aa_profile *)p; ++ struct aa_profile *parent; ++ struct aa_namespace *ns = p->ns; + -+ if (profile->ns != default_namespace) <<Diff was trimmed, longer than 597 lines>> ---- CVS-web: http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/packages/kernel/kernel-apparmor.patch?r1=1.6&r2=1.7&f=u http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/packages/kernel/kernel.spec?r1=1.776&r2=1.777&f=u _______________________________________________ pld-cvs-commit mailing list [email protected] http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit
