diff options
Diffstat (limited to 'ANDROID_3.4.5/security/apparmor')
33 files changed, 0 insertions, 7863 deletions
diff --git a/ANDROID_3.4.5/security/apparmor/Kconfig b/ANDROID_3.4.5/security/apparmor/Kconfig deleted file mode 100644 index 9b9013b2..00000000 --- a/ANDROID_3.4.5/security/apparmor/Kconfig +++ /dev/null @@ -1,31 +0,0 @@ -config SECURITY_APPARMOR - bool "AppArmor support" - depends on SECURITY && NET - 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://apparmor.wiki.kernel.org - - 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 - boot. If this option is set to 1 (one), the AppArmor - kernel parameter will default to 1, enabling AppArmor at - boot. - - If you are unsure how to answer this question, answer 1. diff --git a/ANDROID_3.4.5/security/apparmor/Makefile b/ANDROID_3.4.5/security/apparmor/Makefile deleted file mode 100644 index 806bd19a..00000000 --- a/ANDROID_3.4.5/security/apparmor/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -# 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 - -clean-files := capability_names.h rlim_names.h - - -# Build a lower case string table of capability names -# Transforms lines from -# #define CAP_DAC_OVERRIDE 1 -# to -# [1] = "dac_override", -quiet_cmd_make-caps = GEN $@ -cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\ - sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \ - -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\ - echo "};" >> $@ - - -# Build a lower case string table of rlimit names. -# Transforms lines from -# #define RLIMIT_STACK 3 /* max stack size */ -# to -# [RLIMIT_STACK] = "stack", -# -# and build a second integer table (with the second sed cmd), that maps -# RLIMIT defines to the order defined in asm-generic/resource.h This is -# required by policy load to map policy ordering of RLIMITs to internal -# ordering for architectures that redefine an RLIMIT. -# Transforms lines from -# #define RLIMIT_STACK 3 /* max stack size */ -# to -# RLIMIT_STACK, -# -# and build the securityfs entries for the mapping. -# Transforms lines from -# #define RLIMIT_FSIZE 1 /* Maximum filesize */ -# #define RLIMIT_STACK 3 /* max stack size */ -# to -# #define AA_FS_RLIMIT_MASK "fsize stack" -quiet_cmd_make-rlim = GEN $@ -cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \ - > $@ ;\ - sed $< >> $@ -r -n \ - -e 's/^\# ?define[ \t]+(RLIMIT_([A-Z0-9_]+)).*/[\1] = "\L\2",/p';\ - echo "};" >> $@ ;\ - echo "static const int rlim_map[RLIM_NLIMITS] = {" >> $@ ;\ - sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\ - echo "};" >> $@ ; \ - echo -n '\#define AA_FS_RLIMIT_MASK "' >> $@ ;\ - sed -r -n 's/^\# ?define[ \t]+RLIMIT_([A-Z0-9_]+).*/\L\1/p' $< | \ - tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ - -$(obj)/capability.o : $(obj)/capability_names.h -$(obj)/resource.o : $(obj)/rlim_names.h -$(obj)/capability_names.h : $(srctree)/include/linux/capability.h \ - $(src)/Makefile - $(call cmd,make-caps) -$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h \ - $(src)/Makefile - $(call cmd,make-rlim) diff --git a/ANDROID_3.4.5/security/apparmor/apparmorfs.c b/ANDROID_3.4.5/security/apparmor/apparmorfs.c deleted file mode 100644 index 16c15ec6..00000000 --- a/ANDROID_3.4.5/security/apparmor/apparmorfs.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * 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 <linux/capability.h> - -#include "include/apparmor.h" -#include "include/apparmorfs.h" -#include "include/audit.h" -#include "include/context.h" -#include "include/policy.h" -#include "include/resource.h" - -/** - * aa_simple_write_to_buffer - common routine for getting policy from user - * @op: operation doing the user buffer copy - * @userbuf: user buffer to copy data from (NOT NULL) - * @alloc_size: size of user buffer (REQUIRES: @alloc_size >= @copy_size) - * @copy_size: size of data to copy from user buffer - * @pos: position write is at in the file (NOT NULL) - * - * Returns: kernel buffer containing copy of user buffer data or an - * ERR_PTR on failure. - */ -static char *aa_simple_write_to_buffer(int op, const char __user *userbuf, - size_t alloc_size, size_t copy_size, - loff_t *pos) -{ - char *data; - - BUG_ON(copy_size > alloc_size); - - if (*pos != 0) - /* only writes from pos 0, that is complete writes */ - return ERR_PTR(-ESPIPE); - - /* - * Don't allow profile load/replace/remove from profiles that don't - * have CAP_MAC_ADMIN - */ - if (!aa_may_manage_policy(op)) - return ERR_PTR(-EACCES); - - /* freed by caller to simple_write_to_buffer */ - data = kvmalloc(alloc_size); - if (data == NULL) - return ERR_PTR(-ENOMEM); - - if (copy_from_user(data, userbuf, copy_size)) { - kvfree(data); - return ERR_PTR(-EFAULT); - } - - return data; -} - - -/* .load file hook fn to load policy */ -static ssize_t profile_load(struct file *f, const char __user *buf, size_t size, - loff_t *pos) -{ - char *data; - ssize_t error; - - data = aa_simple_write_to_buffer(OP_PROF_LOAD, buf, size, size, pos); - - error = PTR_ERR(data); - if (!IS_ERR(data)) { - error = aa_replace_profiles(data, size, PROF_ADD); - kvfree(data); - } - - return error; -} - -static const struct file_operations aa_fs_profile_load = { - .write = profile_load, - .llseek = default_llseek, -}; - -/* .replace file hook fn to load and/or replace policy */ -static ssize_t profile_replace(struct file *f, const char __user *buf, - size_t size, loff_t *pos) -{ - char *data; - ssize_t error; - - data = aa_simple_write_to_buffer(OP_PROF_REPL, buf, size, size, pos); - error = PTR_ERR(data); - if (!IS_ERR(data)) { - error = aa_replace_profiles(data, size, PROF_REPLACE); - kvfree(data); - } - - return error; -} - -static const struct file_operations aa_fs_profile_replace = { - .write = profile_replace, - .llseek = default_llseek, -}; - -/* .remove file hook fn to remove loaded policy */ -static ssize_t profile_remove(struct file *f, const char __user *buf, - size_t size, loff_t *pos) -{ - char *data; - ssize_t error; - - /* - * 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(OP_PROF_RM, buf, size + 1, size, pos); - - error = PTR_ERR(data); - if (!IS_ERR(data)) { - data[size] = 0; - error = aa_remove_profiles(data, size); - kvfree(data); - } - - return error; -} - -static const struct file_operations aa_fs_profile_remove = { - .write = profile_remove, - .llseek = default_llseek, -}; - -static int aa_fs_seq_show(struct seq_file *seq, void *v) -{ - struct aa_fs_entry *fs_file = seq->private; - - if (!fs_file) - return 0; - - switch (fs_file->v_type) { - case AA_FS_TYPE_BOOLEAN: - seq_printf(seq, "%s\n", fs_file->v.boolean ? "yes" : "no"); - break; - case AA_FS_TYPE_STRING: - seq_printf(seq, "%s\n", fs_file->v.string); - break; - case AA_FS_TYPE_U64: - seq_printf(seq, "%#08lx\n", fs_file->v.u64); - break; - default: - /* Ignore unpritable entry types. */ - break; - } - - return 0; -} - -static int aa_fs_seq_open(struct inode *inode, struct file *file) -{ - return single_open(file, aa_fs_seq_show, inode->i_private); -} - -const struct file_operations aa_fs_seq_file_ops = { - .owner = THIS_MODULE, - .open = aa_fs_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/** Base file system setup **/ - -static struct aa_fs_entry aa_fs_entry_file[] = { - AA_FS_FILE_STRING("mask", "create read write exec append mmap_exec " \ - "link lock"), - { } -}; - -static struct aa_fs_entry aa_fs_entry_domain[] = { - AA_FS_FILE_BOOLEAN("change_hat", 1), - AA_FS_FILE_BOOLEAN("change_hatv", 1), - AA_FS_FILE_BOOLEAN("change_onexec", 1), - AA_FS_FILE_BOOLEAN("change_profile", 1), - { } -}; - -static struct aa_fs_entry aa_fs_entry_features[] = { - AA_FS_DIR("domain", aa_fs_entry_domain), - AA_FS_DIR("file", aa_fs_entry_file), - AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), - AA_FS_DIR("rlimit", aa_fs_entry_rlimit), - { } -}; - -static struct aa_fs_entry aa_fs_entry_apparmor[] = { - AA_FS_FILE_FOPS(".load", 0640, &aa_fs_profile_load), - AA_FS_FILE_FOPS(".replace", 0640, &aa_fs_profile_replace), - AA_FS_FILE_FOPS(".remove", 0640, &aa_fs_profile_remove), - AA_FS_DIR("features", aa_fs_entry_features), - { } -}; - -static struct aa_fs_entry aa_fs_entry = - AA_FS_DIR("apparmor", aa_fs_entry_apparmor); - -/** - * aafs_create_file - create a file entry in the apparmor securityfs - * @fs_file: aa_fs_entry to build an entry for (NOT NULL) - * @parent: the parent dentry in the securityfs - * - * Use aafs_remove_file to remove entries created with this fn. - */ -static int __init aafs_create_file(struct aa_fs_entry *fs_file, - struct dentry *parent) -{ - int error = 0; - - fs_file->dentry = securityfs_create_file(fs_file->name, - S_IFREG | fs_file->mode, - parent, fs_file, - fs_file->file_ops); - if (IS_ERR(fs_file->dentry)) { - error = PTR_ERR(fs_file->dentry); - fs_file->dentry = NULL; - } - return error; -} - -/** - * aafs_create_dir - recursively create a directory entry in the securityfs - * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL) - * @parent: the parent dentry in the securityfs - * - * Use aafs_remove_dir to remove entries created with this fn. - */ -static int __init aafs_create_dir(struct aa_fs_entry *fs_dir, - struct dentry *parent) -{ - int error; - struct aa_fs_entry *fs_file; - - fs_dir->dentry = securityfs_create_dir(fs_dir->name, parent); - if (IS_ERR(fs_dir->dentry)) { - error = PTR_ERR(fs_dir->dentry); - fs_dir->dentry = NULL; - goto failed; - } - - for (fs_file = fs_dir->v.files; fs_file->name; ++fs_file) { - if (fs_file->v_type == AA_FS_TYPE_DIR) - error = aafs_create_dir(fs_file, fs_dir->dentry); - else - error = aafs_create_file(fs_file, fs_dir->dentry); - if (error) - goto failed; - } - - return 0; - -failed: - return error; -} - -/** - * aafs_remove_file - drop a single file entry in the apparmor securityfs - * @fs_file: aa_fs_entry to detach from the securityfs (NOT NULL) - */ -static void __init aafs_remove_file(struct aa_fs_entry *fs_file) -{ - if (!fs_file->dentry) - return; - - securityfs_remove(fs_file->dentry); - fs_file->dentry = NULL; -} - -/** - * aafs_remove_dir - recursively drop a directory entry from the securityfs - * @fs_dir: aa_fs_entry (and all child entries) to detach (NOT NULL) - */ -static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir) -{ - struct aa_fs_entry *fs_file; - - for (fs_file = fs_dir->v.files; fs_file->name; ++fs_file) { - if (fs_file->v_type == AA_FS_TYPE_DIR) - aafs_remove_dir(fs_file); - else - aafs_remove_file(fs_file); - } - - aafs_remove_file(fs_dir); -} - -/** - * aa_destroy_aafs - cleanup and free aafs - * - * releases dentries allocated by aa_create_aafs - */ -void __init aa_destroy_aafs(void) -{ - aafs_remove_dir(&aa_fs_entry); -} - -/** - * aa_create_aafs - create the apparmor security filesystem - * - * dentries created here are released by aa_destroy_aafs - * - * Returns: error on failure - */ -static int __init aa_create_aafs(void) -{ - int error; - - if (!apparmor_initialized) - return 0; - - if (aa_fs_entry.dentry) { - AA_ERROR("%s: AppArmor securityfs already exists\n", __func__); - return -EEXIST; - } - - /* Populate fs tree. */ - error = aafs_create_dir(&aa_fs_entry, NULL); - if (error) - goto error; - - /* TODO: add support for apparmorfs_null and apparmorfs_mnt */ - - /* Report that AppArmor fs is enabled */ - aa_info_message("AppArmor Filesystem Enabled"); - return 0; - -error: - aa_destroy_aafs(); - AA_ERROR("Error creating AppArmor securityfs\n"); - return error; -} - -fs_initcall(aa_create_aafs); diff --git a/ANDROID_3.4.5/security/apparmor/audit.c b/ANDROID_3.4.5/security/apparmor/audit.c deleted file mode 100644 index cc3520d3..00000000 --- a/ANDROID_3.4.5/security/apparmor/audit.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor auditing 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/audit.h> -#include <linux/socket.h> - -#include "include/apparmor.h" -#include "include/audit.h" -#include "include/policy.h" - -const char *const op_table[] = { - "null", - - "sysctl", - "capable", - - "unlink", - "mkdir", - "rmdir", - "mknod", - "truncate", - "link", - "symlink", - "rename_src", - "rename_dest", - "chmod", - "chown", - "getattr", - "open", - - "file_perm", - "file_lock", - "file_mmap", - "file_mprotect", - - "create", - "post_create", - "bind", - "connect", - "listen", - "accept", - "sendmsg", - "recvmsg", - "getsockname", - "getpeername", - "getsockopt", - "setsockopt", - "socket_shutdown", - - "ptrace", - - "exec", - "change_hat", - "change_profile", - "change_onexec", - - "setprocattr", - "setrlimit", - - "profile_replace", - "profile_load", - "profile_remove" -}; - -const char *const audit_mode_names[] = { - "normal", - "quiet_denied", - "quiet", - "noquiet", - "all" -}; - -static const char *const aa_audit_type[] = { - "AUDIT", - "ALLOWED", - "DENIED", - "HINT", - "STATUS", - "ERROR", - "KILLED" - "AUTO" -}; - -/* - * Currently AppArmor auditing is fed straight into the audit framework. - * - * TODO: - * netlink interface for complain mode - * user auditing, - send user auditing to netlink interface - * system control of whether user audit messages go to system log - */ - -/** - * audit_base - core AppArmor function. - * @ab: audit buffer to fill (NOT NULL) - * @ca: audit structure containing data to audit (NOT NULL) - * - * Record common AppArmor audit data from @sa - */ -static void audit_pre(struct audit_buffer *ab, void *ca) -{ - struct common_audit_data *sa = ca; - struct task_struct *tsk = sa->tsk ? sa->tsk : current; - - if (aa_g_audit_header) { - audit_log_format(ab, "apparmor="); - audit_log_string(ab, aa_audit_type[sa->aad->type]); - } - - if (sa->aad->op) { - audit_log_format(ab, " operation="); - audit_log_string(ab, op_table[sa->aad->op]); - } - - if (sa->aad->info) { - audit_log_format(ab, " info="); - audit_log_string(ab, sa->aad->info); - if (sa->aad->error) - audit_log_format(ab, " error=%d", sa->aad->error); - } - - if (sa->aad->profile) { - struct aa_profile *profile = sa->aad->profile; - pid_t pid; - rcu_read_lock(); - pid = rcu_dereference(tsk->real_parent)->pid; - rcu_read_unlock(); - audit_log_format(ab, " parent=%d", pid); - if (profile->ns != root_ns) { - audit_log_format(ab, " namespace="); - audit_log_untrustedstring(ab, profile->ns->base.hname); - } - audit_log_format(ab, " profile="); - audit_log_untrustedstring(ab, profile->base.hname); - } - - if (sa->aad->name) { - audit_log_format(ab, " name="); - audit_log_untrustedstring(ab, sa->aad->name); - } -} - -/** - * aa_audit_msg - Log a message to the audit subsystem - * @sa: audit event structure (NOT NULL) - * @cb: optional callback fn for type specific fields (MAYBE NULL) - */ -void aa_audit_msg(int type, struct common_audit_data *sa, - void (*cb) (struct audit_buffer *, void *)) -{ - sa->aad->type = type; - common_lsm_audit(sa, audit_pre, cb); -} - -/** - * aa_audit - Log a profile based audit event to the audit subsystem - * @type: audit type for the message - * @profile: profile to check against (NOT NULL) - * @gfp: allocation flags to use - * @sa: audit event (NOT NULL) - * @cb: optional callback fn for type specific fields (MAYBE NULL) - * - * Handle default message switching based off of audit mode flags - * - * Returns: error on failure - */ -int aa_audit(int type, struct aa_profile *profile, gfp_t gfp, - struct common_audit_data *sa, - void (*cb) (struct audit_buffer *, void *)) -{ - BUG_ON(!profile); - - if (type == AUDIT_APPARMOR_AUTO) { - if (likely(!sa->aad->error)) { - if (AUDIT_MODE(profile) != AUDIT_ALL) - return 0; - type = AUDIT_APPARMOR_AUDIT; - } else if (COMPLAIN_MODE(profile)) - type = AUDIT_APPARMOR_ALLOWED; - else - type = AUDIT_APPARMOR_DENIED; - } - if (AUDIT_MODE(profile) == AUDIT_QUIET || - (type == AUDIT_APPARMOR_DENIED && - AUDIT_MODE(profile) == AUDIT_QUIET)) - return sa->aad->error; - - if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) - type = AUDIT_APPARMOR_KILL; - - if (!unconfined(profile)) - sa->aad->profile = profile; - - aa_audit_msg(type, sa, cb); - - if (sa->aad->type == AUDIT_APPARMOR_KILL) - (void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current); - - if (sa->aad->type == AUDIT_APPARMOR_ALLOWED) - return complain_error(sa->aad->error); - - return sa->aad->error; -} diff --git a/ANDROID_3.4.5/security/apparmor/capability.c b/ANDROID_3.4.5/security/apparmor/capability.c deleted file mode 100644 index 088dba3b..00000000 --- a/ANDROID_3.4.5/security/apparmor/capability.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor capability mediation 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/capability.h> -#include <linux/errno.h> -#include <linux/gfp.h> - -#include "include/apparmor.h" -#include "include/capability.h" -#include "include/context.h" -#include "include/policy.h" -#include "include/audit.h" - -/* - * Table of capability names: we generate it from capabilities.h. - */ -#include "capability_names.h" - -struct audit_cache { - struct aa_profile *profile; - kernel_cap_t caps; -}; - -static DEFINE_PER_CPU(struct audit_cache, audit_cache); - -/** - * audit_cb - call back for capability components of audit struct - * @ab - audit buffer (NOT NULL) - * @va - audit struct to audit data from (NOT NULL) - */ -static void audit_cb(struct audit_buffer *ab, void *va) -{ - struct common_audit_data *sa = va; - audit_log_format(ab, " capname="); - audit_log_untrustedstring(ab, capability_names[sa->u.cap]); -} - -/** - * audit_caps - audit a capability - * @profile: profile confining task (NOT NULL) - * @task: task capability test was performed against (NOT NULL) - * @cap: capability tested - * @error: error code returned by test - * - * Do auditing of capability and handle, audit/complain/kill modes switching - * and duplicate message elimination. - * - * Returns: 0 or sa->error on success, error code on failure - */ -static int audit_caps(struct aa_profile *profile, struct task_struct *task, - int cap, int error) -{ - struct audit_cache *ent; - int type = AUDIT_APPARMOR_AUTO; - struct common_audit_data sa; - struct apparmor_audit_data aad = {0,}; - COMMON_AUDIT_DATA_INIT(&sa, CAP); - sa.aad = &aad; - sa.tsk = task; - sa.u.cap = cap; - sa.aad->op = OP_CAPABLE; - sa.aad->error = error; - - if (likely(!error)) { - /* test if auditing is being forced */ - if (likely((AUDIT_MODE(profile) != AUDIT_ALL) && - !cap_raised(profile->caps.audit, cap))) - return 0; - type = AUDIT_APPARMOR_AUDIT; - } else if (KILL_MODE(profile) || - cap_raised(profile->caps.kill, cap)) { - type = AUDIT_APPARMOR_KILL; - } else if (cap_raised(profile->caps.quiet, cap) && - AUDIT_MODE(profile) != AUDIT_NOQUIET && - AUDIT_MODE(profile) != AUDIT_ALL) { - /* quiet auditing */ - return error; - } - - /* Do simple duplicate message elimination */ - ent = &get_cpu_var(audit_cache); - if (profile == ent->profile && cap_raised(ent->caps, cap)) { - put_cpu_var(audit_cache); - if (COMPLAIN_MODE(profile)) - return complain_error(error); - return error; - } else { - aa_put_profile(ent->profile); - ent->profile = aa_get_profile(profile); - cap_raise(ent->caps, cap); - } - put_cpu_var(audit_cache); - - return aa_audit(type, profile, GFP_ATOMIC, &sa, audit_cb); -} - -/** - * profile_capable - test if profile allows use of capability @cap - * @profile: profile being enforced (NOT NULL, NOT unconfined) - * @cap: capability to test if allowed - * - * Returns: 0 if allowed else -EPERM - */ -static int profile_capable(struct aa_profile *profile, int cap) -{ - return cap_raised(profile->caps.allow, cap) ? 0 : -EPERM; -} - -/** - * aa_capable - test permission to use capability - * @task: task doing capability test against (NOT NULL) - * @profile: profile confining @task (NOT NULL) - * @cap: capability to be tested - * @audit: whether an audit record should be generated - * - * Look up capability in profile capability set. - * - * Returns: 0 on success, or else an error code. - */ -int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap, - int audit) -{ - int error = profile_capable(profile, cap); - - if (!audit) { - if (COMPLAIN_MODE(profile)) - return complain_error(error); - return error; - } - - return audit_caps(profile, task, cap, error); -} diff --git a/ANDROID_3.4.5/security/apparmor/context.c b/ANDROID_3.4.5/security/apparmor/context.c deleted file mode 100644 index 8a9b5027..00000000 --- a/ANDROID_3.4.5/security/apparmor/context.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor functions used to manipulate object security - * contexts. - * - * 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. - * - * - * AppArmor sets confinement on every task, via the the aa_task_cxt and - * the aa_task_cxt.profile, both of which are required and are not allowed - * to be NULL. The aa_task_cxt is not reference counted and is unique - * to each cred (which is reference count). The profile pointed to by - * the task_cxt is reference counted. - * - * TODO - * If a task uses change_hat it currently does not return to the old - * cred or task context but instead creates a new one. Ideally the task - * should return to the previous cred if it has not been modified. - * - */ - -#include "include/context.h" -#include "include/policy.h" - -/** - * aa_alloc_task_context - allocate a new task_cxt - * @flags: gfp flags for allocation - * - * Returns: allocated buffer or NULL on failure - */ -struct aa_task_cxt *aa_alloc_task_context(gfp_t flags) -{ - return kzalloc(sizeof(struct aa_task_cxt), flags); -} - -/** - * aa_free_task_context - free a task_cxt - * @cxt: task_cxt to free (MAYBE NULL) - */ -void aa_free_task_context(struct aa_task_cxt *cxt) -{ - if (cxt) { - aa_put_profile(cxt->profile); - aa_put_profile(cxt->previous); - aa_put_profile(cxt->onexec); - - kzfree(cxt); - } -} - -/** - * aa_dup_task_context - duplicate a task context, incrementing reference counts - * @new: a blank task context (NOT NULL) - * @old: the task context to copy (NOT NULL) - */ -void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old) -{ - *new = *old; - aa_get_profile(new->profile); - aa_get_profile(new->previous); - aa_get_profile(new->onexec); -} - -/** - * aa_replace_current_profile - replace the current tasks profiles - * @profile: new profile (NOT NULL) - * - * Returns: 0 or error on failure - */ -int aa_replace_current_profile(struct aa_profile *profile) -{ - struct aa_task_cxt *cxt = current_cred()->security; - struct cred *new; - BUG_ON(!profile); - - if (cxt->profile == profile) - return 0; - - new = prepare_creds(); - if (!new) - return -ENOMEM; - - cxt = new->security; - if (unconfined(profile) || (cxt->profile->ns != profile->ns)) { - /* if switching to unconfined or a different profile namespace - * clear out context state - */ - aa_put_profile(cxt->previous); - aa_put_profile(cxt->onexec); - cxt->previous = NULL; - cxt->onexec = NULL; - cxt->token = 0; - } - /* be careful switching cxt->profile, when racing replacement it - * is possible that cxt->profile->replacedby is the reference keeping - * @profile valid, so make sure to get its reference before dropping - * the reference on cxt->profile */ - aa_get_profile(profile); - aa_put_profile(cxt->profile); - cxt->profile = profile; - - commit_creds(new); - return 0; -} - -/** - * aa_set_current_onexec - set the tasks change_profile to happen onexec - * @profile: system profile to set at exec (MAYBE NULL to clear value) - * - * Returns: 0 or error on failure - */ -int aa_set_current_onexec(struct aa_profile *profile) -{ - struct aa_task_cxt *cxt; - struct cred *new = prepare_creds(); - if (!new) - return -ENOMEM; - - cxt = new->security; - aa_get_profile(profile); - aa_put_profile(cxt->onexec); - cxt->onexec = profile; - - commit_creds(new); - return 0; -} - -/** - * aa_set_current_hat - set the current tasks hat - * @profile: profile to set as the current hat (NOT NULL) - * @token: token value that must be specified to change from the hat - * - * Do switch of tasks hat. If the task is currently in a hat - * validate the token to match. - * - * Returns: 0 or error on failure - */ -int aa_set_current_hat(struct aa_profile *profile, u64 token) -{ - struct aa_task_cxt *cxt; - struct cred *new = prepare_creds(); - if (!new) - return -ENOMEM; - BUG_ON(!profile); - - cxt = new->security; - if (!cxt->previous) { - /* transfer refcount */ - cxt->previous = cxt->profile; - cxt->token = token; - } else if (cxt->token == token) { - aa_put_profile(cxt->profile); - } else { - /* previous_profile && cxt->token != token */ - abort_creds(new); - return -EACCES; - } - cxt->profile = aa_get_profile(aa_newest_version(profile)); - /* clear exec on switching context */ - aa_put_profile(cxt->onexec); - cxt->onexec = NULL; - - commit_creds(new); - return 0; -} - -/** - * aa_restore_previous_profile - exit from hat context restoring the profile - * @token: the token that must be matched to exit hat context - * - * Attempt to return out of a hat to the previous profile. The token - * must match the stored token value. - * - * Returns: 0 or error of failure - */ -int aa_restore_previous_profile(u64 token) -{ - struct aa_task_cxt *cxt; - struct cred *new = prepare_creds(); - if (!new) - return -ENOMEM; - - cxt = new->security; - if (cxt->token != token) { - abort_creds(new); - return -EACCES; - } - /* ignore restores when there is no saved profile */ - if (!cxt->previous) { - abort_creds(new); - return 0; - } - - aa_put_profile(cxt->profile); - cxt->profile = aa_newest_version(cxt->previous); - BUG_ON(!cxt->profile); - if (unlikely(cxt->profile != cxt->previous)) { - aa_get_profile(cxt->profile); - aa_put_profile(cxt->previous); - } - /* clear exec && prev information when restoring to previous context */ - cxt->previous = NULL; - cxt->token = 0; - aa_put_profile(cxt->onexec); - cxt->onexec = NULL; - - commit_creds(new); - return 0; -} diff --git a/ANDROID_3.4.5/security/apparmor/domain.c b/ANDROID_3.4.5/security/apparmor/domain.c deleted file mode 100644 index 6327685c..00000000 --- a/ANDROID_3.4.5/security/apparmor/domain.c +++ /dev/null @@ -1,823 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor policy attachment and domain transitions - * - * Copyright (C) 2002-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/errno.h> -#include <linux/fdtable.h> -#include <linux/file.h> -#include <linux/mount.h> -#include <linux/syscalls.h> -#include <linux/tracehook.h> -#include <linux/personality.h> - -#include "include/audit.h" -#include "include/apparmorfs.h" -#include "include/context.h" -#include "include/domain.h" -#include "include/file.h" -#include "include/ipc.h" -#include "include/match.h" -#include "include/path.h" -#include "include/policy.h" - -/** - * aa_free_domain_entries - free entries in a domain table - * @domain: the domain table to free (MAYBE NULL) - */ -void aa_free_domain_entries(struct aa_domain *domain) -{ - int i; - if (domain) { - if (!domain->table) - return; - - for (i = 0; i < domain->size; i++) - kzfree(domain->table[i]); - kzfree(domain->table); - domain->table = NULL; - } -} - -/** - * may_change_ptraced_domain - check if can change profile on ptraced task - * @task: task we want to change profile of (NOT NULL) - * @to_profile: profile to change to (NOT NULL) - * - * Check if the task is ptraced and if so if the tracing task is allowed - * to trace the new domain - * - * Returns: %0 or error if change not allowed - */ -static int may_change_ptraced_domain(struct task_struct *task, - struct aa_profile *to_profile) -{ - struct task_struct *tracer; - const struct cred *cred = NULL; - struct aa_profile *tracerp = NULL; - int error = 0; - - rcu_read_lock(); - tracer = ptrace_parent(task); - if (tracer) { - /* released below */ - cred = get_task_cred(tracer); - tracerp = aa_cred_profile(cred); - } - - /* not ptraced */ - if (!tracer || unconfined(tracerp)) - goto out; - - error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH); - -out: - rcu_read_unlock(); - if (cred) - put_cred(cred); - - return error; -} - -/** - * change_profile_perms - find permissions for change_profile - * @profile: the current profile (NOT NULL) - * @ns: the namespace being switched to (NOT NULL) - * @name: the name of the profile to change to (NOT NULL) - * @request: requested perms - * @start: state to start matching in - * - * Returns: permission set - */ -static struct file_perms change_profile_perms(struct aa_profile *profile, - struct aa_namespace *ns, - const char *name, u32 request, - unsigned int start) -{ - struct file_perms perms; - struct path_cond cond = { }; - unsigned int state; - - if (unconfined(profile)) { - perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC; - perms.audit = perms.quiet = perms.kill = 0; - return perms; - } else if (!profile->file.dfa) { - return nullperms; - } else if ((ns == profile->ns)) { - /* try matching against rules with out namespace prepended */ - aa_str_perms(profile->file.dfa, start, name, &cond, &perms); - if (COMBINED_PERM_MASK(perms) & request) - return perms; - } - - /* try matching with namespace name and then profile */ - state = aa_dfa_match(profile->file.dfa, start, ns->base.name); - state = aa_dfa_match_len(profile->file.dfa, state, ":", 1); - aa_str_perms(profile->file.dfa, state, name, &cond, &perms); - - return perms; -} - -/** - * __attach_match_ - find an attachment match - * @name - to match against (NOT NULL) - * @head - profile list to walk (NOT NULL) - * - * Do a linear search on the profiles in the list. There is a matching - * preference where an exact match is preferred over a name which uses - * expressions to match, and matching expressions with the greatest - * xmatch_len are preferred. - * - * Requires: @head not be shared or have appropriate locks held - * - * Returns: profile or NULL if no match found - */ -static struct aa_profile *__attach_match(const char *name, - struct list_head *head) -{ - int len = 0; - struct aa_profile *profile, *candidate = NULL; - - list_for_each_entry(profile, head, base.list) { - if (profile->flags & PFLAG_NULL) - continue; - if (profile->xmatch && profile->xmatch_len > len) { - unsigned int state = aa_dfa_match(profile->xmatch, - DFA_START, name); - u32 perm = dfa_user_allow(profile->xmatch, state); - /* any accepting state means a valid match. */ - if (perm & MAY_EXEC) { - candidate = profile; - len = profile->xmatch_len; - } - } else if (!strcmp(profile->base.name, name)) - /* exact non-re match, no more searching required */ - return profile; - } - - return candidate; -} - -/** - * find_attach - do attachment search for unconfined processes - * @ns: the current namespace (NOT NULL) - * @list: list to search (NOT NULL) - * @name: the executable name to match against (NOT NULL) - * - * Returns: profile or NULL if no match found - */ -static struct aa_profile *find_attach(struct aa_namespace *ns, - struct list_head *list, const char *name) -{ - struct aa_profile *profile; - - read_lock(&ns->lock); - profile = aa_get_profile(__attach_match(name, list)); - read_unlock(&ns->lock); - - return profile; -} - -/** - * separate_fqname - separate the namespace and profile names - * @fqname: the fqname name to split (NOT NULL) - * @ns_name: the namespace name if it exists (NOT NULL) - * - * This is the xtable equivalent routine of aa_split_fqname. It finds the - * split in an xtable fqname which contains an embedded \0 instead of a : - * if a namespace is specified. This is done so the xtable is constant and - * isn't re-split on every lookup. - * - * Either the profile or namespace name may be optional but if the namespace - * is specified the profile name termination must be present. This results - * in the following possible encodings: - * profile_name\0 - * :ns_name\0profile_name\0 - * :ns_name\0\0 - * - * NOTE: the xtable fqname is pre-validated at load time in unpack_trans_table - * - * Returns: profile name if it is specified else NULL - */ -static const char *separate_fqname(const char *fqname, const char **ns_name) -{ - const char *name; - - if (fqname[0] == ':') { - /* In this case there is guaranteed to be two \0 terminators - * in the string. They are verified at load time by - * by unpack_trans_table - */ - *ns_name = fqname + 1; /* skip : */ - name = *ns_name + strlen(*ns_name) + 1; - if (!*name) - name = NULL; - } else { - *ns_name = NULL; - name = fqname; - } - - return name; -} - -static const char *next_name(int xtype, const char *name) -{ - return NULL; -} - -/** - * x_table_lookup - lookup an x transition name via transition table - * @profile: current profile (NOT NULL) - * @xindex: index into x transition table - * - * Returns: refcounted profile, or NULL on failure (MAYBE NULL) - */ -static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex) -{ - struct aa_profile *new_profile = NULL; - struct aa_namespace *ns = profile->ns; - u32 xtype = xindex & AA_X_TYPE_MASK; - int index = xindex & AA_X_INDEX_MASK; - const char *name; - - /* index is guaranteed to be in range, validated at load time */ - for (name = profile->file.trans.table[index]; !new_profile && name; - name = next_name(xtype, name)) { - struct aa_namespace *new_ns; - const char *xname = NULL; - - new_ns = NULL; - if (xindex & AA_X_CHILD) { - /* release by caller */ - new_profile = aa_find_child(profile, name); - continue; - } else if (*name == ':') { - /* switching namespace */ - const char *ns_name; - xname = name = separate_fqname(name, &ns_name); - if (!xname) - /* no name so use profile name */ - xname = profile->base.hname; - if (*ns_name == '@') { - /* TODO: variable support */ - ; - } - /* released below */ - new_ns = aa_find_namespace(ns, ns_name); - if (!new_ns) - continue; - } else if (*name == '@') { - /* TODO: variable support */ - continue; - } else { - /* basic namespace lookup */ - xname = name; - } - - /* released by caller */ - new_profile = aa_lookup_profile(new_ns ? new_ns : ns, xname); - aa_put_namespace(new_ns); - } - - /* released by caller */ - return new_profile; -} - -/** - * x_to_profile - get target profile for a given xindex - * @profile: current profile (NOT NULL) - * @name: name to lookup (NOT NULL) - * @xindex: index into x transition table - * - * find profile for a transition index - * - * Returns: refcounted profile or NULL if not found available - */ -static struct aa_profile *x_to_profile(struct aa_profile *profile, - const char *name, u32 xindex) -{ - struct aa_profile *new_profile = NULL; - struct aa_namespace *ns = profile->ns; - u32 xtype = xindex & AA_X_TYPE_MASK; - - switch (xtype) { - case AA_X_NONE: - /* fail exec unless ix || ux fallback - handled by caller */ - return NULL; - case AA_X_NAME: - if (xindex & AA_X_CHILD) - /* released by caller */ - new_profile = find_attach(ns, &profile->base.profiles, - name); - else - /* released by caller */ - new_profile = find_attach(ns, &ns->base.profiles, - name); - break; - case AA_X_TABLE: - /* released by caller */ - new_profile = x_table_lookup(profile, xindex); - break; - } - - /* released by caller */ - return new_profile; -} - -/** - * apparmor_bprm_set_creds - set the new creds on the bprm struct - * @bprm: binprm for the exec (NOT NULL) - * - * Returns: %0 or error on failure - */ -int apparmor_bprm_set_creds(struct linux_binprm *bprm) -{ - struct aa_task_cxt *cxt; - struct aa_profile *profile, *new_profile = NULL; - struct aa_namespace *ns; - char *buffer = NULL; - unsigned int state; - struct file_perms perms = {}; - struct path_cond cond = { - bprm->file->f_path.dentry->d_inode->i_uid, - bprm->file->f_path.dentry->d_inode->i_mode - }; - const char *name = NULL, *target = NULL, *info = NULL; - int error = cap_bprm_set_creds(bprm); - if (error) - return error; - - if (bprm->cred_prepared) - return 0; - - cxt = bprm->cred->security; - BUG_ON(!cxt); - - profile = aa_get_profile(aa_newest_version(cxt->profile)); - /* - * get the namespace from the replacement profile as replacement - * can change the namespace - */ - ns = profile->ns; - state = profile->file.start; - - /* buffer freed below, name is pointer into buffer */ - error = aa_path_name(&bprm->file->f_path, profile->path_flags, &buffer, - &name, &info); - if (error) { - if (profile->flags & - (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED)) - error = 0; - name = bprm->filename; - goto audit; - } - - /* Test for onexec first as onexec directives override other - * x transitions. - */ - if (unconfined(profile)) { - /* unconfined task */ - if (cxt->onexec) - /* change_profile on exec already been granted */ - new_profile = aa_get_profile(cxt->onexec); - else - new_profile = find_attach(ns, &ns->base.profiles, name); - if (!new_profile) - goto cleanup; - goto apply; - } - - /* find exec permissions for name */ - state = aa_str_perms(profile->file.dfa, state, name, &cond, &perms); - if (cxt->onexec) { - struct file_perms cp; - info = "change_profile onexec"; - if (!(perms.allow & AA_MAY_ONEXEC)) - goto audit; - - /* test if this exec can be paired with change_profile onexec. - * onexec permission is linked to exec with a standard pairing - * exec\0change_profile - */ - state = aa_dfa_null_transition(profile->file.dfa, state); - cp = change_profile_perms(profile, cxt->onexec->ns, - cxt->onexec->base.name, - AA_MAY_ONEXEC, state); - - if (!(cp.allow & AA_MAY_ONEXEC)) - goto audit; - new_profile = aa_get_profile(aa_newest_version(cxt->onexec)); - goto apply; - } - - if (perms.allow & MAY_EXEC) { - /* exec permission determine how to transition */ - new_profile = x_to_profile(profile, name, perms.xindex); - if (!new_profile) { - if (perms.xindex & AA_X_INHERIT) { - /* (p|c|n)ix - don't change profile but do - * use the newest version, which was picked - * up above when getting profile - */ - info = "ix fallback"; - new_profile = aa_get_profile(profile); - goto x_clear; - } else if (perms.xindex & AA_X_UNCONFINED) { - new_profile = aa_get_profile(ns->unconfined); - info = "ux fallback"; - } else { - error = -ENOENT; - info = "profile not found"; - } - } - } else if (COMPLAIN_MODE(profile)) { - /* no exec permission - are we in learning mode */ - new_profile = aa_new_null_profile(profile, 0); - if (!new_profile) { - error = -ENOMEM; - info = "could not create null profile"; - } else { - error = -EACCES; - target = new_profile->base.hname; - } - perms.xindex |= AA_X_UNSAFE; - } else - /* fail exec */ - error = -EACCES; - - if (!new_profile) - goto audit; - - if (bprm->unsafe & LSM_UNSAFE_SHARE) { - /* FIXME: currently don't mediate shared state */ - ; - } - - if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { - error = may_change_ptraced_domain(current, new_profile); - if (error) { - aa_put_profile(new_profile); - goto audit; - } - } - - /* Determine if secure exec is needed. - * Can be at this point for the following reasons: - * 1. unconfined switching to confined - * 2. confined switching to different confinement - * 3. confined switching to unconfined - * - * Cases 2 and 3 are marked as requiring secure exec - * (unless policy specified "unsafe exec") - * - * bprm->unsafe is used to cache the AA_X_UNSAFE permission - * to avoid having to recompute in secureexec - */ - if (!(perms.xindex & AA_X_UNSAFE)) { - AA_DEBUG("scrubbing environment variables for %s profile=%s\n", - name, new_profile->base.hname); - bprm->unsafe |= AA_SECURE_X_NEEDED; - } -apply: - target = new_profile->base.hname; - /* when transitioning profiles clear unsafe personality bits */ - bprm->per_clear |= PER_CLEAR_ON_SETID; - -x_clear: - aa_put_profile(cxt->profile); - /* transfer new profile reference will be released when cxt is freed */ - cxt->profile = new_profile; - - /* clear out all temporary/transitional state from the context */ - aa_put_profile(cxt->previous); - aa_put_profile(cxt->onexec); - cxt->previous = NULL; - cxt->onexec = NULL; - cxt->token = 0; - -audit: - error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC, - name, target, cond.uid, info, error); - -cleanup: - aa_put_profile(profile); - kfree(buffer); - - return error; -} - -/** - * apparmor_bprm_secureexec - determine if secureexec is needed - * @bprm: binprm for exec (NOT NULL) - * - * Returns: %1 if secureexec is needed else %0 - */ -int apparmor_bprm_secureexec(struct linux_binprm *bprm) -{ - int ret = cap_bprm_secureexec(bprm); - - /* the decision to use secure exec is computed in set_creds - * and stored in bprm->unsafe. - */ - if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED)) - ret = 1; - - return ret; -} - -/** - * apparmor_bprm_committing_creds - do task cleanup on committing new creds - * @bprm: binprm for the exec (NOT NULL) - */ -void apparmor_bprm_committing_creds(struct linux_binprm *bprm) -{ - struct aa_profile *profile = __aa_current_profile(); - struct aa_task_cxt *new_cxt = bprm->cred->security; - - /* bail out if unconfined or not changing profile */ - if ((new_cxt->profile == profile) || - (unconfined(new_cxt->profile))) - return; - - current->pdeath_signal = 0; - - /* reset soft limits and set hard limits for the new profile */ - __aa_transition_rlimits(profile, new_cxt->profile); -} - -/** - * apparmor_bprm_commited_cred - do cleanup after new creds committed - * @bprm: binprm for the exec (NOT NULL) - */ -void apparmor_bprm_committed_creds(struct linux_binprm *bprm) -{ - /* TODO: cleanup signals - ipc mediation */ - return; -} - -/* - * Functions for self directed profile change - */ - -/** - * new_compound_name - create an hname with @n2 appended to @n1 - * @n1: base of hname (NOT NULL) - * @n2: name to append (NOT NULL) - * - * Returns: new name or NULL on error - */ -static char *new_compound_name(const char *n1, const char *n2) -{ - char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL); - if (name) - sprintf(name, "%s//%s", n1, n2); - return name; -} - -/** - * aa_change_hat - change hat to/from subprofile - * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0) - * @count: number of hat names in @hats - * @token: magic value to validate the hat change - * @permtest: true if this is just a permission test - * - * Change to the first profile specified in @hats that exists, and store - * the @hat_magic in the current task context. If the count == 0 and the - * @token matches that stored in the current task context, return to the - * top level profile. - * - * Returns %0 on success, error otherwise. - */ -int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) -{ - const struct cred *cred; - struct aa_task_cxt *cxt; - struct aa_profile *profile, *previous_profile, *hat = NULL; - char *name = NULL; - int i; - struct file_perms perms = {}; - const char *target = NULL, *info = NULL; - int error = 0; - - /* released below */ - cred = get_current_cred(); - cxt = cred->security; - profile = aa_cred_profile(cred); - previous_profile = cxt->previous; - - if (unconfined(profile)) { - info = "unconfined"; - error = -EPERM; - goto audit; - } - - if (count) { - /* attempting to change into a new hat or switch to a sibling */ - struct aa_profile *root; - root = PROFILE_IS_HAT(profile) ? profile->parent : profile; - - /* find first matching hat */ - for (i = 0; i < count && !hat; i++) - /* released below */ - hat = aa_find_child(root, hats[i]); - if (!hat) { - if (!COMPLAIN_MODE(root) || permtest) { - if (list_empty(&root->base.profiles)) - error = -ECHILD; - else - error = -ENOENT; - goto out; - } - - /* - * In complain mode and failed to match any hats. - * Audit the failure is based off of the first hat - * supplied. This is done due how userspace - * interacts with change_hat. - * - * TODO: Add logging of all failed hats - */ - - /* freed below */ - name = new_compound_name(root->base.hname, hats[0]); - target = name; - /* released below */ - hat = aa_new_null_profile(profile, 1); - if (!hat) { - info = "failed null profile create"; - error = -ENOMEM; - goto audit; - } - } else { - target = hat->base.hname; - if (!PROFILE_IS_HAT(hat)) { - info = "target not hat"; - error = -EPERM; - goto audit; - } - } - - error = may_change_ptraced_domain(current, hat); - if (error) { - info = "ptraced"; - error = -EPERM; - goto audit; - } - - if (!permtest) { - error = aa_set_current_hat(hat, token); - if (error == -EACCES) - /* kill task in case of brute force attacks */ - perms.kill = AA_MAY_CHANGEHAT; - else if (name && !error) - /* reset error for learning of new hats */ - error = -ENOENT; - } - } else if (previous_profile) { - /* Return to saved profile. Kill task if restore fails - * to avoid brute force attacks - */ - target = previous_profile->base.hname; - error = aa_restore_previous_profile(token); - perms.kill = AA_MAY_CHANGEHAT; - } else - /* ignore restores when there is no saved profile */ - goto out; - -audit: - if (!permtest) - error = aa_audit_file(profile, &perms, GFP_KERNEL, - OP_CHANGE_HAT, AA_MAY_CHANGEHAT, NULL, - target, 0, info, error); - -out: - aa_put_profile(hat); - kfree(name); - put_cred(cred); - - return error; -} - -/** - * aa_change_profile - perform a one-way profile transition - * @ns_name: name of the profile namespace to change to (MAYBE NULL) - * @hname: name of profile to change to (MAYBE NULL) - * @onexec: whether this transition is to take place immediately or at exec - * @permtest: true if this is just a permission test - * - * Change to new profile @name. Unlike with hats, there is no way - * to change back. If @name isn't specified the current profile name is - * used. - * If @onexec then the transition is delayed until - * the next exec. - * - * Returns %0 on success, error otherwise. - */ -int aa_change_profile(const char *ns_name, const char *hname, bool onexec, - bool permtest) -{ - const struct cred *cred; - struct aa_task_cxt *cxt; - struct aa_profile *profile, *target = NULL; - struct aa_namespace *ns = NULL; - struct file_perms perms = {}; - const char *name = NULL, *info = NULL; - int op, error = 0; - u32 request; - - if (!hname && !ns_name) - return -EINVAL; - - if (onexec) { - request = AA_MAY_ONEXEC; - op = OP_CHANGE_ONEXEC; - } else { - request = AA_MAY_CHANGE_PROFILE; - op = OP_CHANGE_PROFILE; - } - - cred = get_current_cred(); - cxt = cred->security; - profile = aa_cred_profile(cred); - - if (ns_name) { - /* released below */ - ns = aa_find_namespace(profile->ns, ns_name); - if (!ns) { - /* we don't create new namespace in complain mode */ - name = ns_name; - info = "namespace not found"; - error = -ENOENT; - goto audit; - } - } else - /* released below */ - ns = aa_get_namespace(profile->ns); - - /* if the name was not specified, use the name of the current profile */ - if (!hname) { - if (unconfined(profile)) - hname = ns->unconfined->base.hname; - else - hname = profile->base.hname; - } - - perms = change_profile_perms(profile, ns, hname, request, - profile->file.start); - if (!(perms.allow & request)) { - error = -EACCES; - goto audit; - } - - /* released below */ - target = aa_lookup_profile(ns, hname); - if (!target) { - info = "profile not found"; - error = -ENOENT; - if (permtest || !COMPLAIN_MODE(profile)) - goto audit; - /* released below */ - target = aa_new_null_profile(profile, 0); - if (!target) { - info = "failed null profile create"; - error = -ENOMEM; - goto audit; - } - } - - /* check if tracing task is allowed to trace target domain */ - error = may_change_ptraced_domain(current, target); - if (error) { - info = "ptrace prevents transition"; - goto audit; - } - - if (permtest) - goto audit; - - if (onexec) - error = aa_set_current_onexec(target); - else - error = aa_replace_current_profile(target); - -audit: - if (!permtest) - error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request, - name, hname, 0, info, error); - - aa_put_namespace(ns); - aa_put_profile(target); - put_cred(cred); - - return error; -} diff --git a/ANDROID_3.4.5/security/apparmor/file.c b/ANDROID_3.4.5/security/apparmor/file.c deleted file mode 100644 index 2f8fcba9..00000000 --- a/ANDROID_3.4.5/security/apparmor/file.c +++ /dev/null @@ -1,456 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor mediation of files - * - * 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 "include/apparmor.h" -#include "include/audit.h" -#include "include/file.h" -#include "include/match.h" -#include "include/path.h" -#include "include/policy.h" - -struct file_perms nullperms; - - -/** - * audit_file_mask - convert mask to permission string - * @buffer: buffer to write string to (NOT NULL) - * @mask: permission mask to convert - */ -static void audit_file_mask(struct audit_buffer *ab, u32 mask) -{ - char str[10]; - - char *m = str; - - if (mask & AA_EXEC_MMAP) - *m++ = 'm'; - if (mask & (MAY_READ | AA_MAY_META_READ)) - *m++ = 'r'; - if (mask & (MAY_WRITE | AA_MAY_META_WRITE | AA_MAY_CHMOD | - AA_MAY_CHOWN)) - *m++ = 'w'; - else if (mask & MAY_APPEND) - *m++ = 'a'; - if (mask & AA_MAY_CREATE) - *m++ = 'c'; - if (mask & AA_MAY_DELETE) - *m++ = 'd'; - if (mask & AA_MAY_LINK) - *m++ = 'l'; - if (mask & AA_MAY_LOCK) - *m++ = 'k'; - if (mask & MAY_EXEC) - *m++ = 'x'; - *m = '\0'; - - audit_log_string(ab, str); -} - -/** - * file_audit_cb - call back for file specific audit fields - * @ab: audit_buffer (NOT NULL) - * @va: audit struct to audit values of (NOT NULL) - */ -static void file_audit_cb(struct audit_buffer *ab, void *va) -{ - struct common_audit_data *sa = va; - uid_t fsuid = current_fsuid(); - - if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) { - audit_log_format(ab, " requested_mask="); - audit_file_mask(ab, sa->aad->fs.request); - } - if (sa->aad->fs.denied & AA_AUDIT_FILE_MASK) { - audit_log_format(ab, " denied_mask="); - audit_file_mask(ab, sa->aad->fs.denied); - } - if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) { - audit_log_format(ab, " fsuid=%d", fsuid); - audit_log_format(ab, " ouid=%d", sa->aad->fs.ouid); - } - - if (sa->aad->fs.target) { - audit_log_format(ab, " target="); - audit_log_untrustedstring(ab, sa->aad->fs.target); - } -} - -/** - * aa_audit_file - handle the auditing of file operations - * @profile: the profile being enforced (NOT NULL) - * @perms: the permissions computed for the request (NOT NULL) - * @gfp: allocation flags - * @op: operation being mediated - * @request: permissions requested - * @name: name of object being mediated (MAYBE NULL) - * @target: name of target (MAYBE NULL) - * @ouid: object uid - * @info: extra information message (MAYBE NULL) - * @error: 0 if operation allowed else failure error code - * - * Returns: %0 or error on failure - */ -int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, - gfp_t gfp, int op, u32 request, const char *name, - const char *target, uid_t ouid, const char *info, int error) -{ - int type = AUDIT_APPARMOR_AUTO; - struct common_audit_data sa; - struct apparmor_audit_data aad = {0,}; - COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad = &aad; - aad.op = op, - aad.fs.request = request; - aad.name = name; - aad.fs.target = target; - aad.fs.ouid = ouid; - aad.info = info; - aad.error = error; - - if (likely(!sa.aad->error)) { - u32 mask = perms->audit; - - if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL)) - mask = 0xffff; - - /* mask off perms that are not being force audited */ - sa.aad->fs.request &= mask; - - if (likely(!sa.aad->fs.request)) - return 0; - type = AUDIT_APPARMOR_AUDIT; - } else { - /* only report permissions that were denied */ - sa.aad->fs.request = sa.aad->fs.request & ~perms->allow; - - if (sa.aad->fs.request & perms->kill) - type = AUDIT_APPARMOR_KILL; - - /* quiet known rejects, assumes quiet and kill do not overlap */ - if ((sa.aad->fs.request & perms->quiet) && - AUDIT_MODE(profile) != AUDIT_NOQUIET && - AUDIT_MODE(profile) != AUDIT_ALL) - sa.aad->fs.request &= ~perms->quiet; - - if (!sa.aad->fs.request) - return COMPLAIN_MODE(profile) ? 0 : sa.aad->error; - } - - sa.aad->fs.denied = sa.aad->fs.request & ~perms->allow; - return aa_audit(type, profile, gfp, &sa, file_audit_cb); -} - -/** - * map_old_perms - map old file perms layout to the new layout - * @old: permission set in old mapping - * - * Returns: new permission mapping - */ -static u32 map_old_perms(u32 old) -{ - u32 new = old & 0xf; - if (old & MAY_READ) - new |= AA_MAY_META_READ; - if (old & MAY_WRITE) - new |= AA_MAY_META_WRITE | AA_MAY_CREATE | AA_MAY_DELETE | - AA_MAY_CHMOD | AA_MAY_CHOWN; - if (old & 0x10) - new |= AA_MAY_LINK; - /* the old mapping lock and link_subset flags where overlaid - * and use was determined by part of a pair that they were in - */ - if (old & 0x20) - new |= AA_MAY_LOCK | AA_LINK_SUBSET; - if (old & 0x40) /* AA_EXEC_MMAP */ - new |= AA_EXEC_MMAP; - - return new; -} - -/** - * compute_perms - convert dfa compressed perms to internal perms - * @dfa: dfa to compute perms for (NOT NULL) - * @state: state in dfa - * @cond: conditions to consider (NOT NULL) - * - * TODO: convert from dfa + state to permission entry, do computation conversion - * at load time. - * - * Returns: computed permission set - */ -static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state, - struct path_cond *cond) -{ - struct file_perms perms; - - /* FIXME: change over to new dfa format - * currently file perms are encoded in the dfa, new format - * splits the permissions from the dfa. This mapping can be - * done at profile load - */ - perms.kill = 0; - - if (current_fsuid() == cond->uid) { - perms.allow = map_old_perms(dfa_user_allow(dfa, state)); - perms.audit = map_old_perms(dfa_user_audit(dfa, state)); - perms.quiet = map_old_perms(dfa_user_quiet(dfa, state)); - perms.xindex = dfa_user_xindex(dfa, state); - } else { - perms.allow = map_old_perms(dfa_other_allow(dfa, state)); - perms.audit = map_old_perms(dfa_other_audit(dfa, state)); - perms.quiet = map_old_perms(dfa_other_quiet(dfa, state)); - perms.xindex = dfa_other_xindex(dfa, state); - } - perms.allow |= AA_MAY_META_READ; - - /* change_profile wasn't determined by ownership in old mapping */ - if (ACCEPT_TABLE(dfa)[state] & 0x80000000) - perms.allow |= AA_MAY_CHANGE_PROFILE; - if (ACCEPT_TABLE(dfa)[state] & 0x40000000) - perms.allow |= AA_MAY_ONEXEC; - - return perms; -} - -/** - * aa_str_perms - find permission that match @name - * @dfa: to match against (MAYBE NULL) - * @state: state to start matching in - * @name: string to match against dfa (NOT NULL) - * @cond: conditions to consider for permission set computation (NOT NULL) - * @perms: Returns - the permissions found when matching @name - * - * Returns: the final state in @dfa when beginning @start and walking @name - */ -unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start, - const char *name, struct path_cond *cond, - struct file_perms *perms) -{ - unsigned int state; - if (!dfa) { - *perms = nullperms; - return DFA_NOMATCH; - } - - state = aa_dfa_match(dfa, start, name); - *perms = compute_perms(dfa, state, cond); - - return state; -} - -/** - * is_deleted - test if a file has been completely unlinked - * @dentry: dentry of file to test for deletion (NOT NULL) - * - * Returns: %1 if deleted else %0 - */ -static inline bool is_deleted(struct dentry *dentry) -{ - if (d_unlinked(dentry) && dentry->d_inode->i_nlink == 0) - return 1; - return 0; -} - -/** - * aa_path_perm - do permissions check & audit for @path - * @op: operation being checked - * @profile: profile being enforced (NOT NULL) - * @path: path to check permissions of (NOT NULL) - * @flags: any additional path flags beyond what the profile specifies - * @request: requested permissions - * @cond: conditional info for this request (NOT NULL) - * - * Returns: %0 else error if access denied or other error - */ -int aa_path_perm(int op, struct aa_profile *profile, struct path *path, - int flags, u32 request, struct path_cond *cond) -{ - char *buffer = NULL; - struct file_perms perms = {}; - const char *name, *info = NULL; - int error; - - flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0); - error = aa_path_name(path, flags, &buffer, &name, &info); - if (error) { - if (error == -ENOENT && is_deleted(path->dentry)) { - /* Access to open files that are deleted are - * give a pass (implicit delegation) - */ - error = 0; - info = NULL; - perms.allow = request; - } - } else { - aa_str_perms(profile->file.dfa, profile->file.start, name, cond, - &perms); - if (request & ~perms.allow) - error = -EACCES; - } - error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request, name, - NULL, cond->uid, info, error); - kfree(buffer); - - return error; -} - -/** - * xindex_is_subset - helper for aa_path_link - * @link: link permission set - * @target: target permission set - * - * test target x permissions are equal OR a subset of link x permissions - * this is done as part of the subset test, where a hardlink must have - * a subset of permissions that the target has. - * - * Returns: %1 if subset else %0 - */ -static inline bool xindex_is_subset(u32 link, u32 target) -{ - if (((link & ~AA_X_UNSAFE) != (target & ~AA_X_UNSAFE)) || - ((link & AA_X_UNSAFE) && !(target & AA_X_UNSAFE))) - return 0; - - return 1; -} - -/** - * aa_path_link - Handle hard link permission check - * @profile: the profile being enforced (NOT NULL) - * @old_dentry: the target dentry (NOT NULL) - * @new_dir: directory the new link will be created in (NOT NULL) - * @new_dentry: the link being created (NOT NULL) - * - * Handle the permission test for a link & target pair. Permission - * is encoded as a pair where the link permission is determined - * first, and if allowed, the target is tested. The target test - * is done from the point of the link match (not start of DFA) - * making the target permission dependent on the link permission match. - * - * The subset test if required forces that permissions granted - * on link are a subset of the permission granted to target. - * - * Returns: %0 if allowed else error - */ -int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - struct path *new_dir, struct dentry *new_dentry) -{ - struct path link = { new_dir->mnt, new_dentry }; - struct path target = { new_dir->mnt, old_dentry }; - struct path_cond cond = { - old_dentry->d_inode->i_uid, - old_dentry->d_inode->i_mode - }; - char *buffer = NULL, *buffer2 = NULL; - const char *lname, *tname = NULL, *info = NULL; - struct file_perms lperms, perms; - u32 request = AA_MAY_LINK; - unsigned int state; - int error; - - lperms = nullperms; - - /* buffer freed below, lname is pointer in buffer */ - error = aa_path_name(&link, profile->path_flags, &buffer, &lname, - &info); - if (error) - goto audit; - - /* buffer2 freed below, tname is pointer in buffer2 */ - error = aa_path_name(&target, profile->path_flags, &buffer2, &tname, - &info); - if (error) - goto audit; - - error = -EACCES; - /* aa_str_perms - handles the case of the dfa being NULL */ - state = aa_str_perms(profile->file.dfa, profile->file.start, lname, - &cond, &lperms); - - if (!(lperms.allow & AA_MAY_LINK)) - goto audit; - - /* test to see if target can be paired with link */ - state = aa_dfa_null_transition(profile->file.dfa, state); - aa_str_perms(profile->file.dfa, state, tname, &cond, &perms); - - /* force audit/quiet masks for link are stored in the second entry - * in the link pair. - */ - lperms.audit = perms.audit; - lperms.quiet = perms.quiet; - lperms.kill = perms.kill; - - if (!(perms.allow & AA_MAY_LINK)) { - info = "target restricted"; - goto audit; - } - - /* done if link subset test is not required */ - if (!(perms.allow & AA_LINK_SUBSET)) - goto done_tests; - - /* Do link perm subset test requiring allowed permission on link are a - * subset of the allowed permissions on target. - */ - aa_str_perms(profile->file.dfa, profile->file.start, tname, &cond, - &perms); - - /* AA_MAY_LINK is not considered in the subset test */ - request = lperms.allow & ~AA_MAY_LINK; - lperms.allow &= perms.allow | AA_MAY_LINK; - - request |= AA_AUDIT_FILE_MASK & (lperms.allow & ~perms.allow); - if (request & ~lperms.allow) { - goto audit; - } else if ((lperms.allow & MAY_EXEC) && - !xindex_is_subset(lperms.xindex, perms.xindex)) { - lperms.allow &= ~MAY_EXEC; - request |= MAY_EXEC; - info = "link not subset of target"; - goto audit; - } - -done_tests: - error = 0; - -audit: - error = aa_audit_file(profile, &lperms, GFP_KERNEL, OP_LINK, request, - lname, tname, cond.uid, info, error); - kfree(buffer); - kfree(buffer2); - - return error; -} - -/** - * aa_file_perm - do permission revalidation check & audit for @file - * @op: operation being checked - * @profile: profile being enforced (NOT NULL) - * @file: file to revalidate access permissions on (NOT NULL) - * @request: requested permissions - * - * Returns: %0 if access allowed else error - */ -int aa_file_perm(int op, struct aa_profile *profile, struct file *file, - u32 request) -{ - struct path_cond cond = { - .uid = file->f_path.dentry->d_inode->i_uid, - .mode = file->f_path.dentry->d_inode->i_mode - }; - - return aa_path_perm(op, profile, &file->f_path, PATH_DELEGATE_DELETED, - request, &cond); -} diff --git a/ANDROID_3.4.5/security/apparmor/include/apparmor.h b/ANDROID_3.4.5/security/apparmor/include/apparmor.h deleted file mode 100644 index 40aedd9f..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/apparmor.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor basic global and lib definitions - * - * 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. - */ - -#ifndef __APPARMOR_H -#define __APPARMOR_H - -#include <linux/fs.h> - -#include "match.h" - -/* - * Class of mediation types in the AppArmor policy db - */ -#define AA_CLASS_ENTRY 0 -#define AA_CLASS_UNKNOWN 1 -#define AA_CLASS_FILE 2 -#define AA_CLASS_CAP 3 -#define AA_CLASS_NET 4 -#define AA_CLASS_RLIMITS 5 -#define AA_CLASS_DOMAIN 6 - -#define AA_CLASS_LAST AA_CLASS_DOMAIN - -/* Control parameters settable through module/boot flags */ -extern enum audit_mode aa_g_audit; -extern bool aa_g_audit_header; -extern bool aa_g_debug; -extern bool aa_g_lock_policy; -extern bool aa_g_logsyscall; -extern bool aa_g_paranoid_load; -extern unsigned int aa_g_path_max; - -/* - * DEBUG remains global (no per profile flag) since it is mostly used in sysctl - * which is not related to profile accesses. - */ - -#define AA_DEBUG(fmt, args...) \ - do { \ - if (aa_g_debug && printk_ratelimit()) \ - printk(KERN_DEBUG "AppArmor: " fmt, ##args); \ - } while (0) - -#define AA_ERROR(fmt, args...) \ - do { \ - if (printk_ratelimit()) \ - printk(KERN_ERR "AppArmor: " fmt, ##args); \ - } while (0) - -/* Flag indicating whether initialization completed */ -extern int apparmor_initialized __initdata; - -/* fn's in lib */ -char *aa_split_fqname(char *args, char **ns_name); -void aa_info_message(const char *str); -void *kvmalloc(size_t size); -void kvfree(void *buffer); - - -/** - * aa_strneq - compare null terminated @str to a non null terminated substring - * @str: a null terminated string - * @sub: a substring, not necessarily null terminated - * @len: length of @sub to compare - * - * The @str string must be full consumed for this to be considered a match - */ -static inline bool aa_strneq(const char *str, const char *sub, int len) -{ - return !strncmp(str, sub, len) && !str[len]; -} - -/** - * aa_dfa_null_transition - step to next state after null character - * @dfa: the dfa to match against - * @start: the state of the dfa to start matching in - * - * aa_dfa_null_transition transitions to the next state after a null - * character which is not used in standard matching and is only - * used to separate pairs. - */ -static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, - unsigned int start) -{ - /* the null transition only needs the string's null terminator byte */ - return aa_dfa_next(dfa, start, 0); -} - -static inline bool mediated_filesystem(struct inode *inode) -{ - return !(inode->i_sb->s_flags & MS_NOUSER); -} - -#endif /* __APPARMOR_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/apparmorfs.h b/ANDROID_3.4.5/security/apparmor/include/apparmorfs.h deleted file mode 100644 index 7ea4769f..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/apparmorfs.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor filesystem definitions. - * - * 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. - */ - -#ifndef __AA_APPARMORFS_H -#define __AA_APPARMORFS_H - -enum aa_fs_type { - AA_FS_TYPE_BOOLEAN, - AA_FS_TYPE_STRING, - AA_FS_TYPE_U64, - AA_FS_TYPE_FOPS, - AA_FS_TYPE_DIR, -}; - -struct aa_fs_entry; - -struct aa_fs_entry { - const char *name; - struct dentry *dentry; - umode_t mode; - enum aa_fs_type v_type; - union { - bool boolean; - char *string; - unsigned long u64; - struct aa_fs_entry *files; - } v; - const struct file_operations *file_ops; -}; - -extern const struct file_operations aa_fs_seq_file_ops; - -#define AA_FS_FILE_BOOLEAN(_name, _value) \ - { .name = (_name), .mode = 0444, \ - .v_type = AA_FS_TYPE_BOOLEAN, .v.boolean = (_value), \ - .file_ops = &aa_fs_seq_file_ops } -#define AA_FS_FILE_STRING(_name, _value) \ - { .name = (_name), .mode = 0444, \ - .v_type = AA_FS_TYPE_STRING, .v.string = (_value), \ - .file_ops = &aa_fs_seq_file_ops } -#define AA_FS_FILE_U64(_name, _value) \ - { .name = (_name), .mode = 0444, \ - .v_type = AA_FS_TYPE_U64, .v.u64 = (_value), \ - .file_ops = &aa_fs_seq_file_ops } -#define AA_FS_FILE_FOPS(_name, _mode, _fops) \ - { .name = (_name), .v_type = AA_FS_TYPE_FOPS, \ - .mode = (_mode), .file_ops = (_fops) } -#define AA_FS_DIR(_name, _value) \ - { .name = (_name), .v_type = AA_FS_TYPE_DIR, .v.files = (_value) } - -extern void __init aa_destroy_aafs(void); - -#endif /* __AA_APPARMORFS_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/audit.h b/ANDROID_3.4.5/security/apparmor/include/audit.h deleted file mode 100644 index 3868b1e5..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/audit.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor auditing function definitions. - * - * 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. - */ - -#ifndef __AA_AUDIT_H -#define __AA_AUDIT_H - -#include <linux/audit.h> -#include <linux/fs.h> -#include <linux/lsm_audit.h> -#include <linux/sched.h> -#include <linux/slab.h> - -#include "file.h" - -struct aa_profile; - -extern const char *const audit_mode_names[]; -#define AUDIT_MAX_INDEX 5 - -enum audit_mode { - AUDIT_NORMAL, /* follow normal auditing of accesses */ - AUDIT_QUIET_DENIED, /* quiet all denied access messages */ - AUDIT_QUIET, /* quiet all messages */ - AUDIT_NOQUIET, /* do not quiet audit messages */ - AUDIT_ALL /* audit all accesses */ -}; - -enum audit_type { - AUDIT_APPARMOR_AUDIT, - AUDIT_APPARMOR_ALLOWED, - AUDIT_APPARMOR_DENIED, - AUDIT_APPARMOR_HINT, - AUDIT_APPARMOR_STATUS, - AUDIT_APPARMOR_ERROR, - AUDIT_APPARMOR_KILL, - AUDIT_APPARMOR_AUTO -}; - -extern const char *const op_table[]; -enum aa_ops { - OP_NULL, - - OP_SYSCTL, - OP_CAPABLE, - - OP_UNLINK, - OP_MKDIR, - OP_RMDIR, - OP_MKNOD, - OP_TRUNC, - OP_LINK, - OP_SYMLINK, - OP_RENAME_SRC, - OP_RENAME_DEST, - OP_CHMOD, - OP_CHOWN, - OP_GETATTR, - OP_OPEN, - - OP_FPERM, - OP_FLOCK, - OP_FMMAP, - OP_FMPROT, - - OP_CREATE, - OP_POST_CREATE, - OP_BIND, - OP_CONNECT, - OP_LISTEN, - OP_ACCEPT, - OP_SENDMSG, - OP_RECVMSG, - OP_GETSOCKNAME, - OP_GETPEERNAME, - OP_GETSOCKOPT, - OP_SETSOCKOPT, - OP_SOCK_SHUTDOWN, - - OP_PTRACE, - - OP_EXEC, - OP_CHANGE_HAT, - OP_CHANGE_PROFILE, - OP_CHANGE_ONEXEC, - - OP_SETPROCATTR, - OP_SETRLIMIT, - - OP_PROF_REPL, - OP_PROF_LOAD, - OP_PROF_RM, -}; - - -struct apparmor_audit_data { - int error; - int op; - int type; - void *profile; - const char *name; - const char *info; - union { - void *target; - struct { - long pos; - void *target; - } iface; - struct { - int rlim; - unsigned long max; - } rlim; - struct { - const char *target; - u32 request; - u32 denied; - uid_t ouid; - } fs; - }; -}; - -/* define a short hand for apparmor_audit_data structure */ -#define aad apparmor_audit_data - -void aa_audit_msg(int type, struct common_audit_data *sa, - void (*cb) (struct audit_buffer *, void *)); -int aa_audit(int type, struct aa_profile *profile, gfp_t gfp, - struct common_audit_data *sa, - void (*cb) (struct audit_buffer *, void *)); - -static inline int complain_error(int error) -{ - if (error == -EPERM || error == -EACCES) - return 0; - return error; -} - -#endif /* __AA_AUDIT_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/capability.h b/ANDROID_3.4.5/security/apparmor/include/capability.h deleted file mode 100644 index c24d2959..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/capability.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor capability mediation definitions. - * - * 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. - */ - -#ifndef __AA_CAPABILITY_H -#define __AA_CAPABILITY_H - -#include <linux/sched.h> - -struct aa_profile; - -/* aa_caps - confinement data for capabilities - * @allowed: capabilities mask - * @audit: caps that are to be audited - * @quiet: caps that should not be audited - * @kill: caps that when requested will result in the task being killed - * @extended: caps that are subject finer grained mediation - */ -struct aa_caps { - kernel_cap_t allow; - kernel_cap_t audit; - kernel_cap_t quiet; - kernel_cap_t kill; - kernel_cap_t extended; -}; - -int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap, - int audit); - -static inline void aa_free_cap_rules(struct aa_caps *caps) -{ - /* NOP */ -} - -#endif /* __AA_CAPBILITY_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/context.h b/ANDROID_3.4.5/security/apparmor/include/context.h deleted file mode 100644 index a9cbee4d..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/context.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor contexts used to associate "labels" to objects. - * - * 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. - */ - -#ifndef __AA_CONTEXT_H -#define __AA_CONTEXT_H - -#include <linux/cred.h> -#include <linux/slab.h> -#include <linux/sched.h> - -#include "policy.h" - -/* struct aa_file_cxt - the AppArmor context the file was opened in - * @perms: the permission the file was opened with - * - * The file_cxt could currently be directly stored in file->f_security - * as the profile reference is now stored in the f_cred. However the - * cxt struct will expand in the future so we keep the struct. - */ -struct aa_file_cxt { - u16 allow; -}; - -/** - * aa_alloc_file_context - allocate file_cxt - * @gfp: gfp flags for allocation - * - * Returns: file_cxt or NULL on failure - */ -static inline struct aa_file_cxt *aa_alloc_file_context(gfp_t gfp) -{ - return kzalloc(sizeof(struct aa_file_cxt), gfp); -} - -/** - * aa_free_file_context - free a file_cxt - * @cxt: file_cxt to free (MAYBE_NULL) - */ -static inline void aa_free_file_context(struct aa_file_cxt *cxt) -{ - if (cxt) - kzfree(cxt); -} - -/** - * struct aa_task_cxt - primary label for confined tasks - * @profile: the current profile (NOT NULL) - * @exec: profile to transition to on next exec (MAYBE NULL) - * @previous: profile the task may return to (MAYBE NULL) - * @token: magic value the task must know for returning to @previous_profile - * - * Contains the task's current profile (which could change due to - * change_hat). Plus the hat_magic needed during change_hat. - * - * TODO: make so a task can be confined by a stack of contexts - */ -struct aa_task_cxt { - struct aa_profile *profile; - struct aa_profile *onexec; - struct aa_profile *previous; - u64 token; -}; - -struct aa_task_cxt *aa_alloc_task_context(gfp_t flags); -void aa_free_task_context(struct aa_task_cxt *cxt); -void aa_dup_task_context(struct aa_task_cxt *new, - const struct aa_task_cxt *old); -int aa_replace_current_profile(struct aa_profile *profile); -int aa_set_current_onexec(struct aa_profile *profile); -int aa_set_current_hat(struct aa_profile *profile, u64 token); -int aa_restore_previous_profile(u64 cookie); - -/** - * __aa_task_is_confined - determine if @task has any confinement - * @task: task to check confinement of (NOT NULL) - * - * If @task != current needs to be called in RCU safe critical section - */ -static inline bool __aa_task_is_confined(struct task_struct *task) -{ - struct aa_task_cxt *cxt = __task_cred(task)->security; - - BUG_ON(!cxt || !cxt->profile); - if (unconfined(aa_newest_version(cxt->profile))) - return 0; - - return 1; -} - -/** - * aa_cred_profile - obtain cred's profiles - * @cred: cred to obtain profiles from (NOT NULL) - * - * Returns: confining profile - * - * does NOT increment reference count - */ -static inline struct aa_profile *aa_cred_profile(const struct cred *cred) -{ - struct aa_task_cxt *cxt = cred->security; - BUG_ON(!cxt || !cxt->profile); - return aa_newest_version(cxt->profile); -} - -/** - * __aa_current_profile - find the current tasks confining profile - * - * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) - * - * This fn will not update the tasks cred to the most up to date version - * of the profile so it is safe to call when inside of locks. - */ -static inline struct aa_profile *__aa_current_profile(void) -{ - return aa_cred_profile(current_cred()); -} - -/** - * aa_current_profile - find the current tasks confining profile and do updates - * - * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) - * - * This fn will update the tasks cred structure if the profile has been - * replaced. Not safe to call inside locks - */ -static inline struct aa_profile *aa_current_profile(void) -{ - const struct aa_task_cxt *cxt = current_cred()->security; - struct aa_profile *profile; - BUG_ON(!cxt || !cxt->profile); - - profile = aa_newest_version(cxt->profile); - /* - * Whether or not replacement succeeds, use newest profile so - * there is no need to update it after replacement. - */ - if (unlikely((cxt->profile != profile))) - aa_replace_current_profile(profile); - - return profile; -} - -#endif /* __AA_CONTEXT_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/domain.h b/ANDROID_3.4.5/security/apparmor/include/domain.h deleted file mode 100644 index de04464f..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/domain.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor security domain transition function definitions. - * - * 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/binfmts.h> -#include <linux/types.h> - -#ifndef __AA_DOMAIN_H -#define __AA_DOMAIN_H - -struct aa_domain { - int size; - char **table; -}; - -int apparmor_bprm_set_creds(struct linux_binprm *bprm); -int apparmor_bprm_secureexec(struct linux_binprm *bprm); -void apparmor_bprm_committing_creds(struct linux_binprm *bprm); -void apparmor_bprm_committed_creds(struct linux_binprm *bprm); - -void aa_free_domain_entries(struct aa_domain *domain); -int aa_change_hat(const char *hats[], int count, u64 token, bool permtest); -int aa_change_profile(const char *ns_name, const char *name, bool onexec, - bool permtest); - -#endif /* __AA_DOMAIN_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/file.h b/ANDROID_3.4.5/security/apparmor/include/file.h deleted file mode 100644 index f98fd470..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/file.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor file mediation function definitions. - * - * 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. - */ - -#ifndef __AA_FILE_H -#define __AA_FILE_H - -#include "domain.h" -#include "match.h" - -struct aa_profile; -struct path; - -/* - * We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags - * for profile permissions - */ -#define AA_MAY_CREATE 0x0010 -#define AA_MAY_DELETE 0x0020 -#define AA_MAY_META_WRITE 0x0040 -#define AA_MAY_META_READ 0x0080 - -#define AA_MAY_CHMOD 0x0100 -#define AA_MAY_CHOWN 0x0200 -#define AA_MAY_LOCK 0x0400 -#define AA_EXEC_MMAP 0x0800 - -#define AA_MAY_LINK 0x1000 -#define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */ -#define AA_MAY_ONEXEC 0x40000000 /* exec allows onexec */ -#define AA_MAY_CHANGE_PROFILE 0x80000000 -#define AA_MAY_CHANGEHAT 0x80000000 /* ctrl auditing only */ - -#define AA_AUDIT_FILE_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\ - AA_MAY_CREATE | AA_MAY_DELETE | \ - AA_MAY_META_READ | AA_MAY_META_WRITE | \ - AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \ - AA_EXEC_MMAP | AA_MAY_LINK) - -/* - * The xindex is broken into 3 parts - * - index - an index into either the exec name table or the variable table - * - exec type - which determines how the executable name and index are used - * - flags - which modify how the destination name is applied - */ -#define AA_X_INDEX_MASK 0x03ff - -#define AA_X_TYPE_MASK 0x0c00 -#define AA_X_TYPE_SHIFT 10 -#define AA_X_NONE 0x0000 -#define AA_X_NAME 0x0400 /* use executable name px */ -#define AA_X_TABLE 0x0800 /* use a specified name ->n# */ - -#define AA_X_UNSAFE 0x1000 -#define AA_X_CHILD 0x2000 /* make >AA_X_NONE apply to children */ -#define AA_X_INHERIT 0x4000 -#define AA_X_UNCONFINED 0x8000 - -/* AA_SECURE_X_NEEDED - is passed in the bprm->unsafe field */ -#define AA_SECURE_X_NEEDED 0x8000 - -/* need to make conditional which ones are being set */ -struct path_cond { - uid_t uid; - umode_t mode; -}; - -/* struct file_perms - file permission - * @allow: mask of permissions that are allowed - * @audit: mask of permissions to force an audit message for - * @quiet: mask of permissions to quiet audit messages for - * @kill: mask of permissions that when matched will kill the task - * @xindex: exec transition index if @allow contains MAY_EXEC - * - * The @audit and @queit mask should be mutually exclusive. - */ -struct file_perms { - u32 allow; - u32 audit; - u32 quiet; - u32 kill; - u16 xindex; -}; - -extern struct file_perms nullperms; - -#define COMBINED_PERM_MASK(X) ((X).allow | (X).audit | (X).quiet | (X).kill) - -/* FIXME: split perms from dfa and match this to description - * also add delegation info. - */ -static inline u16 dfa_map_xindex(u16 mask) -{ - u16 old_index = (mask >> 10) & 0xf; - u16 index = 0; - - if (mask & 0x100) - index |= AA_X_UNSAFE; - if (mask & 0x200) - index |= AA_X_INHERIT; - if (mask & 0x80) - index |= AA_X_UNCONFINED; - - if (old_index == 1) { - index |= AA_X_UNCONFINED; - } else if (old_index == 2) { - index |= AA_X_NAME; - } else if (old_index == 3) { - index |= AA_X_NAME | AA_X_CHILD; - } else if (old_index) { - index |= AA_X_TABLE; - index |= old_index - 4; - } - - return index; -} - -/* - * map old dfa inline permissions to new format - */ -#define dfa_user_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) & 0x7f) | \ - ((ACCEPT_TABLE(dfa)[state]) & 0x80000000)) -#define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f) -#define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f) -#define dfa_user_xindex(dfa, state) \ - (dfa_map_xindex(ACCEPT_TABLE(dfa)[state] & 0x3fff)) - -#define dfa_other_allow(dfa, state) ((((ACCEPT_TABLE(dfa)[state]) >> 14) & \ - 0x7f) | \ - ((ACCEPT_TABLE(dfa)[state]) & 0x80000000)) -#define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f) -#define dfa_other_quiet(dfa, state) \ - ((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f) -#define dfa_other_xindex(dfa, state) \ - dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff) - -int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, - gfp_t gfp, int op, u32 request, const char *name, - const char *target, uid_t ouid, const char *info, int error); - -/** - * struct aa_file_rules - components used for file rule permissions - * @dfa: dfa to match path names and conditionals against - * @perms: permission table indexed by the matched state accept entry of @dfa - * @trans: transition table for indexed by named x transitions - * - * File permission are determined by matching a path against @dfa and then - * then using the value of the accept entry for the matching state as - * an index into @perms. If a named exec transition is required it is - * looked up in the transition table. - */ -struct aa_file_rules { - unsigned int start; - struct aa_dfa *dfa; - /* struct perms perms; */ - struct aa_domain trans; - /* TODO: add delegate table */ -}; - -unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start, - const char *name, struct path_cond *cond, - struct file_perms *perms); - -int aa_path_perm(int op, struct aa_profile *profile, struct path *path, - int flags, u32 request, struct path_cond *cond); - -int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - struct path *new_dir, struct dentry *new_dentry); - -int aa_file_perm(int op, struct aa_profile *profile, struct file *file, - u32 request); - -static inline void aa_free_file_rules(struct aa_file_rules *rules) -{ - aa_put_dfa(rules->dfa); - aa_free_domain_entries(&rules->trans); -} - -#define ACC_FMODE(x) (("\000\004\002\006"[(x)&O_ACCMODE]) | (((x) << 1) & 0x40)) - -/* from namei.c */ -#define MAP_OPEN_FLAGS(x) ((((x) + 1) & O_ACCMODE) ? (x) + 1 : (x)) - -/** - * aa_map_file_perms - map file flags to AppArmor permissions - * @file: open file to map flags to AppArmor permissions - * - * Returns: apparmor permission set for the file - */ -static inline u32 aa_map_file_to_perms(struct file *file) -{ - int flags = MAP_OPEN_FLAGS(file->f_flags); - u32 perms = ACC_FMODE(file->f_mode); - - if ((flags & O_APPEND) && (perms & MAY_WRITE)) - perms = (perms & ~MAY_WRITE) | MAY_APPEND; - /* trunc implies write permission */ - if (flags & O_TRUNC) - perms |= MAY_WRITE; - if (flags & O_CREAT) - perms |= AA_MAY_CREATE; - - return perms; -} - -#endif /* __AA_FILE_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/ipc.h b/ANDROID_3.4.5/security/apparmor/include/ipc.h deleted file mode 100644 index aeda0fbc..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/ipc.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor ipc mediation function definitions. - * - * 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. - */ - -#ifndef __AA_IPC_H -#define __AA_IPC_H - -#include <linux/sched.h> - -struct aa_profile; - -int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer, - struct aa_profile *tracee, unsigned int mode); - -int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee, - unsigned int mode); - -#endif /* __AA_IPC_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/match.h b/ANDROID_3.4.5/security/apparmor/include/match.h deleted file mode 100644 index 775843e7..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/match.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor policy dfa matching engine definitions. - * - * 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. - */ - -#ifndef __AA_MATCH_H -#define __AA_MATCH_H - -#include <linux/kref.h> -#include <linux/workqueue.h> - -#define DFA_NOMATCH 0 -#define DFA_START 1 - -#define DFA_VALID_PERM_MASK 0xffffffff -#define DFA_VALID_PERM2_MASK 0xffffffff - -/** - * The format used for transition tables is based on the GNU flex table - * file format (--tables-file option; see Table File Format in the flex - * info pages and the flex sources for documentation). The magic number - * used in the header is 0x1B5E783D instead of 0xF13C57B1 though, because - * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used - * slightly differently (see the apparmor-parser package). - */ - -#define YYTH_MAGIC 0x1B5E783D -#define YYTH_DEF_RECURSE 0x1 /* DEF Table is recursive */ - -struct table_set_header { - u32 th_magic; /* YYTH_MAGIC */ - u32 th_hsize; - u32 th_ssize; - u16 th_flags; - char th_version[]; -}; - -/* The YYTD_ID are one less than flex table mappings. The flex id - * has 1 subtracted at table load time, this allows us to directly use the - * ID's as indexes. - */ -#define YYTD_ID_ACCEPT 0 -#define YYTD_ID_BASE 1 -#define YYTD_ID_CHK 2 -#define YYTD_ID_DEF 3 -#define YYTD_ID_EC 4 -#define YYTD_ID_META 5 -#define YYTD_ID_ACCEPT2 6 -#define YYTD_ID_NXT 7 -#define YYTD_ID_TSIZE 8 - -#define YYTD_DATA8 1 -#define YYTD_DATA16 2 -#define YYTD_DATA32 4 -#define YYTD_DATA64 8 - -/* Each ACCEPT2 table gets 6 dedicated flags, YYTD_DATAX define the - * first flags - */ -#define ACCEPT1_FLAGS(X) ((X) & 0x3f) -#define ACCEPT2_FLAGS(X) ACCEPT1_FLAGS((X) >> YYTD_ID_ACCEPT2) -#define TO_ACCEPT1_FLAG(X) ACCEPT1_FLAGS(X) -#define TO_ACCEPT2_FLAG(X) (ACCEPT1_FLAGS(X) << YYTD_ID_ACCEPT2) -#define DFA_FLAG_VERIFY_STATES 0x1000 - -struct table_header { - u16 td_id; - u16 td_flags; - u32 td_hilen; - u32 td_lolen; - char td_data[]; -}; - -#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF]->td_data)) -#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE]->td_data)) -#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT]->td_data)) -#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK]->td_data)) -#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC]->td_data)) -#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT]->td_data)) -#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2]->td_data)) - -struct aa_dfa { - struct kref count; - u16 flags; - struct table_header *tables[YYTD_ID_TSIZE]; -}; - -#define byte_to_byte(X) (X) - -#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \ - do { \ - typeof(LEN) __i; \ - TYPE *__t = (TYPE *) TABLE; \ - TYPE *__b = (TYPE *) BLOB; \ - for (__i = 0; __i < LEN; __i++) { \ - __t[__i] = NTOHX(__b[__i]); \ - } \ - } while (0) - -static inline size_t table_size(size_t len, size_t el_size) -{ - return ALIGN(sizeof(struct table_header) + len * el_size, 8); -} - -struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags); -unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start, - const char *str, int len); -unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start, - const char *str); -unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state, - const char c); - -void aa_dfa_free_kref(struct kref *kref); - -/** - * aa_put_dfa - put a dfa refcount - * @dfa: dfa to put refcount (MAYBE NULL) - * - * Requires: if @dfa != NULL that a valid refcount be held - */ -static inline void aa_put_dfa(struct aa_dfa *dfa) -{ - if (dfa) - kref_put(&dfa->count, aa_dfa_free_kref); -} - -#endif /* __AA_MATCH_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/path.h b/ANDROID_3.4.5/security/apparmor/include/path.h deleted file mode 100644 index 286ac75d..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/path.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor basic path manipulation function definitions. - * - * 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. - */ - -#ifndef __AA_PATH_H -#define __AA_PATH_H - - -enum path_flags { - PATH_IS_DIR = 0x1, /* path is a directory */ - PATH_CONNECT_PATH = 0x4, /* connect disconnected paths to / */ - PATH_CHROOT_REL = 0x8, /* do path lookup relative to chroot */ - PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */ - - PATH_DELEGATE_DELETED = 0x08000, /* delegate deleted files */ - PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */ -}; - -int aa_path_name(struct path *path, int flags, char **buffer, - const char **name, const char **info); - -#endif /* __AA_PATH_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/policy.h b/ANDROID_3.4.5/security/apparmor/include/policy.h deleted file mode 100644 index bda4569f..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/policy.h +++ /dev/null @@ -1,318 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor policy definitions. - * - * 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. - */ - -#ifndef __AA_POLICY_H -#define __AA_POLICY_H - -#include <linux/capability.h> -#include <linux/cred.h> -#include <linux/kref.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/socket.h> - -#include "apparmor.h" -#include "audit.h" -#include "capability.h" -#include "domain.h" -#include "file.h" -#include "resource.h" - -extern const char *const profile_mode_names[]; -#define APPARMOR_NAMES_MAX_INDEX 3 - -#define COMPLAIN_MODE(_profile) \ - ((aa_g_profile_mode == APPARMOR_COMPLAIN) || \ - ((_profile)->mode == APPARMOR_COMPLAIN)) - -#define KILL_MODE(_profile) \ - ((aa_g_profile_mode == APPARMOR_KILL) || \ - ((_profile)->mode == APPARMOR_KILL)) - -#define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT) - -/* - * FIXME: currently need a clean way to replace and remove profiles as a - * set. It should be done at the namespace level. - * Either, with a set of profiles loaded at the namespace level or via - * a mark and remove marked interface. - */ -enum profile_mode { - APPARMOR_ENFORCE, /* enforce access rules */ - APPARMOR_COMPLAIN, /* allow and log access violations */ - APPARMOR_KILL, /* kill task on access violation */ -}; - -enum profile_flags { - PFLAG_HAT = 1, /* profile is a hat */ - PFLAG_UNCONFINED = 2, /* profile is an unconfined profile */ - PFLAG_NULL = 4, /* profile is null learning profile */ - PFLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */ - PFLAG_IMMUTABLE = 0x10, /* don't allow changes/replacement */ - PFLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */ - PFLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */ - PFLAG_OLD_NULL_TRANS = 0x100, /* use // as the null transition */ - - /* These flags must correspond with PATH_flags */ - PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */ -}; - -struct aa_profile; - -/* struct aa_policy - common part of both namespaces and profiles - * @name: name of the object - * @hname - The hierarchical name - * @count: reference count of the obj - * @list: list policy object is on - * @profiles: head of the profiles list contained in the object - */ -struct aa_policy { - char *name; - char *hname; - struct kref count; - struct list_head list; - struct list_head profiles; -}; - -/* struct aa_ns_acct - accounting of profiles in namespace - * @max_size: maximum space allowed for all profiles in namespace - * @max_count: maximum number of profiles that can be in this namespace - * @size: current size of profiles - * @count: current count of profiles (includes null profiles) - */ -struct aa_ns_acct { - int max_size; - int max_count; - int size; - int count; -}; - -/* struct aa_namespace - namespace for a set of profiles - * @base: common policy - * @parent: parent of namespace - * @lock: lock for modifying the object - * @acct: accounting for the namespace - * @unconfined: special unconfined profile for the namespace - * @sub_ns: list of namespaces under the current namespace. - * - * An aa_namespace defines the set profiles that are searched to determine - * which profile to attach to a task. Profiles can not be shared between - * aa_namespaces and profile names within a namespace are guaranteed to be - * unique. When profiles in separate namespaces have the same name they - * are NOT considered to be equivalent. - * - * Namespaces are hierarchical and only namespaces and profiles below the - * current namespace are visible. - * - * Namespace names must be unique and can not contain the characters :/\0 - * - * FIXME TODO: add vserver support of namespaces (can it all be done in - * userspace?) - */ -struct aa_namespace { - struct aa_policy base; - struct aa_namespace *parent; - rwlock_t lock; - struct aa_ns_acct acct; - struct aa_profile *unconfined; - struct list_head sub_ns; -}; - -/* struct aa_policydb - match engine for a policy - * dfa: dfa pattern match - * start: set of start states for the different classes of data - */ -struct aa_policydb { - /* Generic policy DFA specific rule types will be subsections of it */ - struct aa_dfa *dfa; - unsigned int start[AA_CLASS_LAST + 1]; - -}; - -/* struct aa_profile - basic confinement data - * @base - base components of the profile (name, refcount, lists, lock ...) - * @parent: parent of profile - * @ns: namespace the profile is in - * @replacedby: is set to the profile that replaced this profile - * @rename: optional profile name that this profile renamed - * @xmatch: optional extended matching for unconfined executables names - * @xmatch_len: xmatch prefix len, used to determine xmatch priority - * @sid: the unique security id number of this profile - * @audit: the auditing mode of the profile - * @mode: the enforcement mode of the profile - * @flags: flags controlling profile behavior - * @path_flags: flags controlling path generation behavior - * @size: the memory consumed by this profiles rules - * @policy: general match rules governing policy - * @file: The set of rules governing basic file access and domain transitions - * @caps: capabilities for the profile - * @rlimits: rlimits for the profile - * - * The AppArmor profile contains the basic confinement data. Each profile - * has a name, and exists in a namespace. The @name and @exec_match are - * used to determine profile attachment against unconfined tasks. All other - * attachments are determined by profile X transition rules. - * - * The @replacedby field is write protected by the profile lock. Reads - * are assumed to be atomic, and are done without locking. - * - * Profiles have a hierarchy where hats and children profiles keep - * a reference to their parent. - * - * Profile names can not begin with a : and can not contain the \0 - * character. If a profile name begins with / it will be considered when - * determining profile attachment on "unconfined" tasks. - */ -struct aa_profile { - struct aa_policy base; - struct aa_profile *parent; - - struct aa_namespace *ns; - struct aa_profile *replacedby; - const char *rename; - - struct aa_dfa *xmatch; - int xmatch_len; - u32 sid; - enum audit_mode audit; - enum profile_mode mode; - u32 flags; - u32 path_flags; - int size; - - struct aa_policydb policy; - struct aa_file_rules file; - struct aa_caps caps; - struct aa_rlimit rlimits; -}; - -extern struct aa_namespace *root_ns; -extern enum profile_mode aa_g_profile_mode; - -void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); - -bool aa_ns_visible(struct aa_namespace *curr, struct aa_namespace *view); -const char *aa_ns_name(struct aa_namespace *parent, struct aa_namespace *child); -int aa_alloc_root_ns(void); -void aa_free_root_ns(void); -void aa_free_namespace_kref(struct kref *kref); - -struct aa_namespace *aa_find_namespace(struct aa_namespace *root, - const char *name); - -static inline struct aa_policy *aa_get_common(struct aa_policy *c) -{ - if (c) - kref_get(&c->count); - - return c; -} - -/** - * aa_get_namespace - increment references count on @ns - * @ns: namespace to increment reference count of (MAYBE NULL) - * - * Returns: pointer to @ns, if @ns is NULL returns NULL - * Requires: @ns must be held with valid refcount when called - */ -static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns) -{ - if (ns) - kref_get(&(ns->base.count)); - - return ns; -} - -/** - * aa_put_namespace - decrement refcount on @ns - * @ns: namespace to put reference of - * - * Decrement reference count of @ns and if no longer in use free it - */ -static inline void aa_put_namespace(struct aa_namespace *ns) -{ - if (ns) - kref_put(&ns->base.count, aa_free_namespace_kref); -} - -struct aa_profile *aa_alloc_profile(const char *name); -struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat); -void aa_free_profile_kref(struct kref *kref); -struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name); -struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *name); -struct aa_profile *aa_match_profile(struct aa_namespace *ns, const char *name); - -ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace); -ssize_t aa_remove_profiles(char *name, size_t size); - -#define PROF_ADD 1 -#define PROF_REPLACE 0 - -#define unconfined(X) ((X)->flags & PFLAG_UNCONFINED) - -/** - * aa_newest_version - find the newest version of @profile - * @profile: the profile to check for newer versions of (NOT NULL) - * - * Returns: newest version of @profile, if @profile is the newest version - * return @profile. - * - * NOTE: the profile returned is not refcounted, The refcount on @profile - * must be held until the caller decides what to do with the returned newest - * version. - */ -static inline struct aa_profile *aa_newest_version(struct aa_profile *profile) -{ - while (profile->replacedby) - profile = profile->replacedby; - - return profile; -} - -/** - * aa_get_profile - increment refcount on profile @p - * @p: profile (MAYBE NULL) - * - * Returns: pointer to @p if @p is NULL will return NULL - * Requires: @p must be held with valid refcount when called - */ -static inline struct aa_profile *aa_get_profile(struct aa_profile *p) -{ - if (p) - kref_get(&(p->base.count)); - - return p; -} - -/** - * aa_put_profile - decrement refcount on profile @p - * @p: profile (MAYBE NULL) - */ -static inline void aa_put_profile(struct aa_profile *p) -{ - if (p) - kref_put(&p->base.count, aa_free_profile_kref); -} - -static inline int AUDIT_MODE(struct aa_profile *profile) -{ - if (aa_g_audit != AUDIT_NORMAL) - return aa_g_audit; - - return profile->audit; -} - -bool aa_may_manage_policy(int op); - -#endif /* __AA_POLICY_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/policy_unpack.h b/ANDROID_3.4.5/security/apparmor/include/policy_unpack.h deleted file mode 100644 index a2dcccac..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/policy_unpack.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor policy loading interface function definitions. - * - * 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. - */ - -#ifndef __POLICY_INTERFACE_H -#define __POLICY_INTERFACE_H - -struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns); - -#endif /* __POLICY_INTERFACE_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/procattr.h b/ANDROID_3.4.5/security/apparmor/include/procattr.h deleted file mode 100644 index 544aa6b7..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/procattr.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor /proc/<pid>/attr/ interface function definitions. - * - * 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. - */ - -#ifndef __AA_PROCATTR_H -#define __AA_PROCATTR_H - -#define AA_DO_TEST 1 -#define AA_ONEXEC 1 - -int aa_getprocattr(struct aa_profile *profile, char **string); -int aa_setprocattr_changehat(char *args, size_t size, int test); -int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test); -int aa_setprocattr_permipc(char *fqname); - -#endif /* __AA_PROCATTR_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/resource.h b/ANDROID_3.4.5/security/apparmor/include/resource.h deleted file mode 100644 index d3f4cf02..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/resource.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor resource limits function definitions. - * - * 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. - */ - -#ifndef __AA_RESOURCE_H -#define __AA_RESOURCE_H - -#include <linux/resource.h> -#include <linux/sched.h> - -#include "apparmorfs.h" - -struct aa_profile; - -/* struct aa_rlimit - rlimit settings for the profile - * @mask: which hard limits to set - * @limits: rlimit values that override task limits - * - * AppArmor rlimits are used to set confined task rlimits. Only the - * limits specified in @mask will be controlled by apparmor. - */ -struct aa_rlimit { - unsigned int mask; - struct rlimit limits[RLIM_NLIMITS]; -}; - -extern struct aa_fs_entry aa_fs_entry_rlimit[]; - -int aa_map_resource(int resource); -int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *, - unsigned int resource, struct rlimit *new_rlim); - -void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new); - -static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims) -{ - /* NOP */ -} - -#endif /* __AA_RESOURCE_H */ diff --git a/ANDROID_3.4.5/security/apparmor/include/sid.h b/ANDROID_3.4.5/security/apparmor/include/sid.h deleted file mode 100644 index 020db35c..00000000 --- a/ANDROID_3.4.5/security/apparmor/include/sid.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor security identifier (sid) definitions - * - * 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. - */ - -#ifndef __AA_SID_H -#define __AA_SID_H - -#include <linux/types.h> - -struct aa_profile; - -u32 aa_alloc_sid(void); -void aa_free_sid(u32 sid); - -#endif /* __AA_SID_H */ diff --git a/ANDROID_3.4.5/security/apparmor/ipc.c b/ANDROID_3.4.5/security/apparmor/ipc.c deleted file mode 100644 index c3da93a5..00000000 --- a/ANDROID_3.4.5/security/apparmor/ipc.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor ipc mediation - * - * 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/gfp.h> -#include <linux/ptrace.h> - -#include "include/audit.h" -#include "include/capability.h" -#include "include/context.h" -#include "include/policy.h" -#include "include/ipc.h" - -/* call back to audit ptrace fields */ -static void audit_cb(struct audit_buffer *ab, void *va) -{ - struct common_audit_data *sa = va; - audit_log_format(ab, " target="); - audit_log_untrustedstring(ab, sa->aad->target); -} - -/** - * aa_audit_ptrace - do auditing for ptrace - * @profile: profile being enforced (NOT NULL) - * @target: profile being traced (NOT NULL) - * @error: error condition - * - * Returns: %0 or error code - */ -static int aa_audit_ptrace(struct aa_profile *profile, - struct aa_profile *target, int error) -{ - struct common_audit_data sa; - struct apparmor_audit_data aad = {0,}; - COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad = &aad; - aad.op = OP_PTRACE; - aad.target = target; - aad.error = error; - - return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa, - audit_cb); -} - -/** - * aa_may_ptrace - test if tracer task can trace the tracee - * @tracer_task: task who will do the tracing (NOT NULL) - * @tracer: profile of the task doing the tracing (NOT NULL) - * @tracee: task to be traced - * @mode: whether PTRACE_MODE_READ || PTRACE_MODE_ATTACH - * - * Returns: %0 else error code if permission denied or error - */ -int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer, - struct aa_profile *tracee, unsigned int mode) -{ - /* TODO: currently only based on capability, not extended ptrace - * rules, - * Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH - */ - - if (unconfined(tracer) || tracer == tracee) - return 0; - /* log this capability request */ - return aa_capable(tracer_task, tracer, CAP_SYS_PTRACE, 1); -} - -/** - * aa_ptrace - do ptrace permission check and auditing - * @tracer: task doing the tracing (NOT NULL) - * @tracee: task being traced (NOT NULL) - * @mode: ptrace mode either PTRACE_MODE_READ || PTRACE_MODE_ATTACH - * - * Returns: %0 else error code if permission denied or error - */ -int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee, - unsigned int mode) -{ - /* - * tracer can ptrace tracee when - * - tracer is unconfined || - * - tracer is in complain mode - * - tracer has rules allowing it to trace tracee currently this is: - * - confined by the same profile || - * - tracer profile has CAP_SYS_PTRACE - */ - - struct aa_profile *tracer_p; - /* cred released below */ - const struct cred *cred = get_task_cred(tracer); - int error = 0; - tracer_p = aa_cred_profile(cred); - - if (!unconfined(tracer_p)) { - /* lcred released below */ - const struct cred *lcred = get_task_cred(tracee); - struct aa_profile *tracee_p = aa_cred_profile(lcred); - - error = aa_may_ptrace(tracer, tracer_p, tracee_p, mode); - error = aa_audit_ptrace(tracer_p, tracee_p, error); - - put_cred(lcred); - } - put_cred(cred); - - return error; -} diff --git a/ANDROID_3.4.5/security/apparmor/lib.c b/ANDROID_3.4.5/security/apparmor/lib.c deleted file mode 100644 index e75829ba..00000000 --- a/ANDROID_3.4.5/security/apparmor/lib.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * AppArmor security module - * - * This file contains basic common functions used in AppArmor - * - * 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/mm.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/vmalloc.h> - -#include "include/audit.h" -#include "include/apparmor.h" - - -/** - * aa_split_fqname - split a fqname into a profile and namespace name - * @fqname: a full qualified name in namespace profile format (NOT NULL) - * @ns_name: pointer to portion of the string containing the ns name (NOT NULL) - * - * Returns: profile name or NULL if one is not specified - * - * Split a namespace name from a profile name (see policy.c for naming - * description). If a portion of the name is missing it returns NULL for - * that portion. - * - * NOTE: may modify the @fqname string. The pointers returned point - * into the @fqname string. - */ -char *aa_split_fqname(char *fqname, char **ns_name) -{ - char *name = strim(fqname); - - *ns_name = NULL; - if (name[0] == ':') { - char *split = strchr(&name[1], ':'); - *ns_name = skip_spaces(&name[1]); - if (split) { - /* overwrite ':' with \0 */ - *split = 0; - name = skip_spaces(split + 1); - } else - /* a ns name without a following profile is allowed */ - name = NULL; - } - if (name && *name == 0) - name = NULL; - - return name; -} - -/** - * aa_info_message - log a none profile related status message - * @str: message to log - */ -void aa_info_message(const char *str) -{ - if (audit_enabled) { - struct common_audit_data sa; - struct apparmor_audit_data aad = {0,}; - COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad = &aad; - aad.info = str; - aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); - } - printk(KERN_INFO "AppArmor: %s\n", str); -} - -/** - * kvmalloc - do allocation preferring 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. - */ -void *kvmalloc(size_t size) -{ - void *buffer = NULL; - - if (size == 0) - return NULL; - - /* do not attempt kmalloc if we need more than 16 pages at once */ - if (size <= (16*PAGE_SIZE)) - buffer = kmalloc(size, GFP_NOIO | __GFP_NOWARN); - if (!buffer) { - /* see kvfree for why size must be at least work_struct size - * when allocated via vmalloc - */ - if (size < sizeof(struct work_struct)) - size = sizeof(struct work_struct); - buffer = vmalloc(size); - } - return buffer; -} - -/** - * do_vfree - workqueue routine for freeing vmalloced memory - * @work: data to be freed - * - * The work_struct is overlaid to the data being freed, as at the point - * the work is scheduled the data is no longer valid, be its freeing - * needs to be delayed until safe. - */ -static void do_vfree(struct work_struct *work) -{ - vfree(work); -} - -/** - * kvfree - free an allocation do by kvmalloc - * @buffer: buffer to free (MAYBE_NULL) - * - * Free a buffer allocated by kvmalloc - */ -void kvfree(void *buffer) -{ - if (is_vmalloc_addr(buffer)) { - /* Data is no longer valid so just use the allocated space - * as the work_struct - */ - struct work_struct *work = (struct work_struct *) buffer; - INIT_WORK(work, do_vfree); - schedule_work(work); - } else - kfree(buffer); -} diff --git a/ANDROID_3.4.5/security/apparmor/lsm.c b/ANDROID_3.4.5/security/apparmor/lsm.c deleted file mode 100644 index ad05d391..00000000 --- a/ANDROID_3.4.5/security/apparmor/lsm.c +++ /dev/null @@ -1,953 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor LSM hooks. - * - * 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/moduleparam.h> -#include <linux/mm.h> -#include <linux/mman.h> -#include <linux/mount.h> -#include <linux/namei.h> -#include <linux/ptrace.h> -#include <linux/ctype.h> -#include <linux/sysctl.h> -#include <linux/audit.h> -#include <linux/user_namespace.h> -#include <net/sock.h> - -#include "include/apparmor.h" -#include "include/apparmorfs.h" -#include "include/audit.h" -#include "include/capability.h" -#include "include/context.h" -#include "include/file.h" -#include "include/ipc.h" -#include "include/path.h" -#include "include/policy.h" -#include "include/procattr.h" - -/* Flag indicating whether initialization completed */ -int apparmor_initialized __initdata; - -/* - * LSM hook functions - */ - -/* - * free the associated aa_task_cxt and put its profiles - */ -static void apparmor_cred_free(struct cred *cred) -{ - aa_free_task_context(cred->security); - cred->security = NULL; -} - -/* - * allocate the apparmor part of blank credentials - */ -static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp) -{ - /* freed by apparmor_cred_free */ - struct aa_task_cxt *cxt = aa_alloc_task_context(gfp); - if (!cxt) - return -ENOMEM; - - cred->security = cxt; - return 0; -} - -/* - * prepare new aa_task_cxt for modification by prepare_cred block - */ -static int apparmor_cred_prepare(struct cred *new, const struct cred *old, - gfp_t gfp) -{ - /* freed by apparmor_cred_free */ - struct aa_task_cxt *cxt = aa_alloc_task_context(gfp); - if (!cxt) - return -ENOMEM; - - aa_dup_task_context(cxt, old->security); - new->security = cxt; - return 0; -} - -/* - * transfer the apparmor data to a blank set of creds - */ -static void apparmor_cred_transfer(struct cred *new, const struct cred *old) -{ - const struct aa_task_cxt *old_cxt = old->security; - struct aa_task_cxt *new_cxt = new->security; - - aa_dup_task_context(new_cxt, old_cxt); -} - -static int apparmor_ptrace_access_check(struct task_struct *child, - unsigned int mode) -{ - int error = cap_ptrace_access_check(child, mode); - if (error) - return error; - - return aa_ptrace(current, child, mode); -} - -static int apparmor_ptrace_traceme(struct task_struct *parent) -{ - int error = cap_ptrace_traceme(parent); - if (error) - return error; - - return aa_ptrace(parent, current, PTRACE_MODE_ATTACH); -} - -/* Derived from security/commoncap.c:cap_capget */ -static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, - kernel_cap_t *inheritable, kernel_cap_t *permitted) -{ - struct aa_profile *profile; - const struct cred *cred; - - rcu_read_lock(); - cred = __task_cred(target); - profile = aa_cred_profile(cred); - - *effective = cred->cap_effective; - *inheritable = cred->cap_inheritable; - *permitted = cred->cap_permitted; - - if (!unconfined(profile) && !COMPLAIN_MODE(profile)) { - *effective = cap_intersect(*effective, profile->caps.allow); - *permitted = cap_intersect(*permitted, profile->caps.allow); - } - rcu_read_unlock(); - - return 0; -} - -static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, - int cap, int audit) -{ - struct aa_profile *profile; - /* cap_capable returns 0 on success, else -EPERM */ - int error = cap_capable(cred, ns, cap, audit); - if (!error) { - profile = aa_cred_profile(cred); - if (!unconfined(profile)) - error = aa_capable(current, profile, cap, audit); - } - return error; -} - -/** - * common_perm - basic common permission check wrapper fn for paths - * @op: operation being checked - * @path: path to check permission of (NOT NULL) - * @mask: requested permissions mask - * @cond: conditional info for the permission request (NOT NULL) - * - * Returns: %0 else error code if error or permission denied - */ -static int common_perm(int op, struct path *path, u32 mask, - struct path_cond *cond) -{ - struct aa_profile *profile; - int error = 0; - - profile = __aa_current_profile(); - if (!unconfined(profile)) - error = aa_path_perm(op, profile, path, 0, mask, cond); - - return error; -} - -/** - * common_perm_dir_dentry - common permission wrapper when path is dir, dentry - * @op: operation being checked - * @dir: directory of the dentry (NOT NULL) - * @dentry: dentry to check (NOT NULL) - * @mask: requested permissions mask - * @cond: conditional info for the permission request (NOT NULL) - * - * Returns: %0 else error code if error or permission denied - */ -static int common_perm_dir_dentry(int op, struct path *dir, - struct dentry *dentry, u32 mask, - struct path_cond *cond) -{ - struct path path = { dir->mnt, dentry }; - - return common_perm(op, &path, mask, cond); -} - -/** - * common_perm_mnt_dentry - common permission wrapper when mnt, dentry - * @op: operation being checked - * @mnt: mount point of dentry (NOT NULL) - * @dentry: dentry to check (NOT NULL) - * @mask: requested permissions mask - * - * Returns: %0 else error code if error or permission denied - */ -static int common_perm_mnt_dentry(int op, struct vfsmount *mnt, - struct dentry *dentry, u32 mask) -{ - struct path path = { mnt, dentry }; - struct path_cond cond = { dentry->d_inode->i_uid, - dentry->d_inode->i_mode - }; - - return common_perm(op, &path, mask, &cond); -} - -/** - * common_perm_rm - common permission wrapper for operations doing rm - * @op: operation being checked - * @dir: directory that the dentry is in (NOT NULL) - * @dentry: dentry being rm'd (NOT NULL) - * @mask: requested permission mask - * - * Returns: %0 else error code if error or permission denied - */ -static int common_perm_rm(int op, struct path *dir, - struct dentry *dentry, u32 mask) -{ - struct inode *inode = dentry->d_inode; - struct path_cond cond = { }; - - if (!inode || !dir->mnt || !mediated_filesystem(inode)) - return 0; - - cond.uid = inode->i_uid; - cond.mode = inode->i_mode; - - return common_perm_dir_dentry(op, dir, dentry, mask, &cond); -} - -/** - * common_perm_create - common permission wrapper for operations doing create - * @op: operation being checked - * @dir: directory that dentry will be created in (NOT NULL) - * @dentry: dentry to create (NOT NULL) - * @mask: request permission mask - * @mode: created file mode - * - * Returns: %0 else error code if error or permission denied - */ -static int common_perm_create(int op, struct path *dir, struct dentry *dentry, - u32 mask, umode_t mode) -{ - struct path_cond cond = { current_fsuid(), mode }; - - if (!dir->mnt || !mediated_filesystem(dir->dentry->d_inode)) - return 0; - - return common_perm_dir_dentry(op, dir, dentry, mask, &cond); -} - -static int apparmor_path_unlink(struct path *dir, struct dentry *dentry) -{ - return common_perm_rm(OP_UNLINK, dir, dentry, AA_MAY_DELETE); -} - -static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry, - umode_t mode) -{ - return common_perm_create(OP_MKDIR, dir, dentry, AA_MAY_CREATE, - S_IFDIR); -} - -static int apparmor_path_rmdir(struct path *dir, struct dentry *dentry) -{ - return common_perm_rm(OP_RMDIR, dir, dentry, AA_MAY_DELETE); -} - -static int apparmor_path_mknod(struct path *dir, struct dentry *dentry, - umode_t mode, unsigned int dev) -{ - return common_perm_create(OP_MKNOD, dir, dentry, AA_MAY_CREATE, mode); -} - -static int apparmor_path_truncate(struct path *path) -{ - struct path_cond cond = { path->dentry->d_inode->i_uid, - path->dentry->d_inode->i_mode - }; - - if (!path->mnt || !mediated_filesystem(path->dentry->d_inode)) - return 0; - - return common_perm(OP_TRUNC, path, MAY_WRITE | AA_MAY_META_WRITE, - &cond); -} - -static int apparmor_path_symlink(struct path *dir, struct dentry *dentry, - const char *old_name) -{ - return common_perm_create(OP_SYMLINK, dir, dentry, AA_MAY_CREATE, - S_IFLNK); -} - -static int apparmor_path_link(struct dentry *old_dentry, struct path *new_dir, - struct dentry *new_dentry) -{ - struct aa_profile *profile; - int error = 0; - - if (!mediated_filesystem(old_dentry->d_inode)) - return 0; - - profile = aa_current_profile(); - if (!unconfined(profile)) - error = aa_path_link(profile, old_dentry, new_dir, new_dentry); - return error; -} - -static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry, - struct path *new_dir, struct dentry *new_dentry) -{ - struct aa_profile *profile; - int error = 0; - - if (!mediated_filesystem(old_dentry->d_inode)) - return 0; - - profile = aa_current_profile(); - if (!unconfined(profile)) { - struct path old_path = { old_dir->mnt, old_dentry }; - struct path new_path = { new_dir->mnt, new_dentry }; - struct path_cond cond = { old_dentry->d_inode->i_uid, - old_dentry->d_inode->i_mode - }; - - error = aa_path_perm(OP_RENAME_SRC, profile, &old_path, 0, - MAY_READ | AA_MAY_META_READ | MAY_WRITE | - AA_MAY_META_WRITE | AA_MAY_DELETE, - &cond); - if (!error) - error = aa_path_perm(OP_RENAME_DEST, profile, &new_path, - 0, MAY_WRITE | AA_MAY_META_WRITE | - AA_MAY_CREATE, &cond); - - } - return error; -} - -static int apparmor_path_chmod(struct path *path, umode_t mode) -{ - if (!mediated_filesystem(path->dentry->d_inode)) - return 0; - - return common_perm_mnt_dentry(OP_CHMOD, path->mnt, path->dentry, AA_MAY_CHMOD); -} - -static int apparmor_path_chown(struct path *path, uid_t uid, gid_t gid) -{ - struct path_cond cond = { path->dentry->d_inode->i_uid, - path->dentry->d_inode->i_mode - }; - - if (!mediated_filesystem(path->dentry->d_inode)) - return 0; - - return common_perm(OP_CHOWN, path, AA_MAY_CHOWN, &cond); -} - -static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) -{ - if (!mediated_filesystem(dentry->d_inode)) - return 0; - - return common_perm_mnt_dentry(OP_GETATTR, mnt, dentry, - AA_MAY_META_READ); -} - -static int apparmor_dentry_open(struct file *file, const struct cred *cred) -{ - struct aa_file_cxt *fcxt = file->f_security; - struct aa_profile *profile; - int error = 0; - - if (!mediated_filesystem(file->f_path.dentry->d_inode)) - return 0; - - /* If in exec, permission is handled by bprm hooks. - * Cache permissions granted by the previous exec check, with - * implicit read and executable mmap which are required to - * actually execute the image. - */ - if (current->in_execve) { - fcxt->allow = MAY_EXEC | MAY_READ | AA_EXEC_MMAP; - return 0; - } - - profile = aa_cred_profile(cred); - if (!unconfined(profile)) { - struct inode *inode = file->f_path.dentry->d_inode; - struct path_cond cond = { inode->i_uid, inode->i_mode }; - - error = aa_path_perm(OP_OPEN, profile, &file->f_path, 0, - aa_map_file_to_perms(file), &cond); - /* todo cache full allowed permissions set and state */ - fcxt->allow = aa_map_file_to_perms(file); - } - - return error; -} - -static int apparmor_file_alloc_security(struct file *file) -{ - /* freed by apparmor_file_free_security */ - file->f_security = aa_alloc_file_context(GFP_KERNEL); - if (!file->f_security) - return -ENOMEM; - return 0; - -} - -static void apparmor_file_free_security(struct file *file) -{ - struct aa_file_cxt *cxt = file->f_security; - - aa_free_file_context(cxt); -} - -static int common_file_perm(int op, struct file *file, u32 mask) -{ - struct aa_file_cxt *fcxt = file->f_security; - struct aa_profile *profile, *fprofile = aa_cred_profile(file->f_cred); - int error = 0; - - BUG_ON(!fprofile); - - if (!file->f_path.mnt || - !mediated_filesystem(file->f_path.dentry->d_inode)) - return 0; - - profile = __aa_current_profile(); - - /* revalidate access, if task is unconfined, or the cached cred - * doesn't match or if the request is for more permissions than - * was granted. - * - * Note: the test for !unconfined(fprofile) is to handle file - * delegation from unconfined tasks - */ - if (!unconfined(profile) && !unconfined(fprofile) && - ((fprofile != profile) || (mask & ~fcxt->allow))) - error = aa_file_perm(op, profile, file, mask); - - return error; -} - -static int apparmor_file_permission(struct file *file, int mask) -{ - return common_file_perm(OP_FPERM, file, mask); -} - -static int apparmor_file_lock(struct file *file, unsigned int cmd) -{ - u32 mask = AA_MAY_LOCK; - - if (cmd == F_WRLCK) - mask |= MAY_WRITE; - - return common_file_perm(OP_FLOCK, file, mask); -} - -static int common_mmap(int op, struct file *file, unsigned long prot, - unsigned long flags) -{ - struct dentry *dentry; - int mask = 0; - - if (!file || !file->f_security) - return 0; - - if (prot & PROT_READ) - mask |= MAY_READ; - /* - * Private mappings don't require write perms since they don't - * write back to the files - */ - if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE)) - mask |= MAY_WRITE; - if (prot & PROT_EXEC) - mask |= AA_EXEC_MMAP; - - dentry = file->f_path.dentry; - return common_file_perm(op, file, mask); -} - -static int apparmor_file_mmap(struct file *file, unsigned long reqprot, - unsigned long prot, unsigned long flags, - unsigned long addr, unsigned long addr_only) -{ - int rc = 0; - - /* do DAC check */ - rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); - if (rc || addr_only) - return rc; - - return common_mmap(OP_FMMAP, file, prot, flags); -} - -static int apparmor_file_mprotect(struct vm_area_struct *vma, - unsigned long reqprot, unsigned long prot) -{ - return common_mmap(OP_FMPROT, vma->vm_file, prot, - !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0); -} - -static int apparmor_getprocattr(struct task_struct *task, char *name, - char **value) -{ - int error = -ENOENT; - struct aa_profile *profile; - /* released below */ - const struct cred *cred = get_task_cred(task); - struct aa_task_cxt *cxt = cred->security; - profile = aa_cred_profile(cred); - - if (strcmp(name, "current") == 0) - error = aa_getprocattr(aa_newest_version(cxt->profile), - value); - else if (strcmp(name, "prev") == 0 && cxt->previous) - error = aa_getprocattr(aa_newest_version(cxt->previous), - value); - else if (strcmp(name, "exec") == 0 && cxt->onexec) - error = aa_getprocattr(aa_newest_version(cxt->onexec), - value); - else - error = -EINVAL; - - put_cred(cred); - - return error; -} - -static int apparmor_setprocattr(struct task_struct *task, char *name, - void *value, size_t size) -{ - char *command, *args = value; - size_t arg_size; - int error; - - if (size == 0) - return -EINVAL; - /* args points to a PAGE_SIZE buffer, AppArmor requires that - * the buffer must be null terminated or have size <= PAGE_SIZE -1 - * so that AppArmor can null terminate them - */ - if (args[size - 1] != '\0') { - if (size == PAGE_SIZE) - return -EINVAL; - args[size] = '\0'; - } - - /* task can only write its own attributes */ - if (current != task) - return -EACCES; - - args = value; - args = strim(args); - command = strsep(&args, " "); - if (!args) - return -EINVAL; - args = skip_spaces(args); - if (!*args) - return -EINVAL; - - arg_size = size - (args - (char *) value); - if (strcmp(name, "current") == 0) { - if (strcmp(command, "changehat") == 0) { - error = aa_setprocattr_changehat(args, arg_size, - !AA_DO_TEST); - } else if (strcmp(command, "permhat") == 0) { - error = aa_setprocattr_changehat(args, arg_size, - AA_DO_TEST); - } else if (strcmp(command, "changeprofile") == 0) { - error = aa_setprocattr_changeprofile(args, !AA_ONEXEC, - !AA_DO_TEST); - } else if (strcmp(command, "permprofile") == 0) { - error = aa_setprocattr_changeprofile(args, !AA_ONEXEC, - AA_DO_TEST); - } else if (strcmp(command, "permipc") == 0) { - error = aa_setprocattr_permipc(args); - } else { - struct common_audit_data sa; - struct apparmor_audit_data aad = {0,}; - COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad = &aad; - aad.op = OP_SETPROCATTR; - aad.info = name; - aad.error = -EINVAL; - return aa_audit(AUDIT_APPARMOR_DENIED, - __aa_current_profile(), GFP_KERNEL, - &sa, NULL); - } - } else if (strcmp(name, "exec") == 0) { - error = aa_setprocattr_changeprofile(args, AA_ONEXEC, - !AA_DO_TEST); - } else { - /* only support the "current" and "exec" process attributes */ - return -EINVAL; - } - if (!error) - error = size; - return error; -} - -static int apparmor_task_setrlimit(struct task_struct *task, - unsigned int resource, struct rlimit *new_rlim) -{ - struct aa_profile *profile = __aa_current_profile(); - int error = 0; - - if (!unconfined(profile)) - error = aa_task_setrlimit(profile, task, resource, new_rlim); - - return error; -} - -static struct security_operations apparmor_ops = { - .name = "apparmor", - - .ptrace_access_check = apparmor_ptrace_access_check, - .ptrace_traceme = apparmor_ptrace_traceme, - .capget = apparmor_capget, - .capable = apparmor_capable, - - .path_link = apparmor_path_link, - .path_unlink = apparmor_path_unlink, - .path_symlink = apparmor_path_symlink, - .path_mkdir = apparmor_path_mkdir, - .path_rmdir = apparmor_path_rmdir, - .path_mknod = apparmor_path_mknod, - .path_rename = apparmor_path_rename, - .path_chmod = apparmor_path_chmod, - .path_chown = apparmor_path_chown, - .path_truncate = apparmor_path_truncate, - .dentry_open = apparmor_dentry_open, - .inode_getattr = apparmor_inode_getattr, - - .file_permission = apparmor_file_permission, - .file_alloc_security = apparmor_file_alloc_security, - .file_free_security = apparmor_file_free_security, - .file_mmap = apparmor_file_mmap, - .file_mprotect = apparmor_file_mprotect, - .file_lock = apparmor_file_lock, - - .getprocattr = apparmor_getprocattr, - .setprocattr = apparmor_setprocattr, - - .cred_alloc_blank = apparmor_cred_alloc_blank, - .cred_free = apparmor_cred_free, - .cred_prepare = apparmor_cred_prepare, - .cred_transfer = apparmor_cred_transfer, - - .bprm_set_creds = apparmor_bprm_set_creds, - .bprm_committing_creds = apparmor_bprm_committing_creds, - .bprm_committed_creds = apparmor_bprm_committed_creds, - .bprm_secureexec = apparmor_bprm_secureexec, - - .task_setrlimit = apparmor_task_setrlimit, -}; - -/* - * AppArmor sysfs module parameters - */ - -static int param_set_aabool(const char *val, const struct kernel_param *kp); -static int param_get_aabool(char *buffer, const struct kernel_param *kp); -#define param_check_aabool param_check_bool -static struct kernel_param_ops param_ops_aabool = { - .set = param_set_aabool, - .get = param_get_aabool -}; - -static int param_set_aauint(const char *val, const struct kernel_param *kp); -static int param_get_aauint(char *buffer, const struct kernel_param *kp); -#define param_check_aauint param_check_uint -static struct kernel_param_ops param_ops_aauint = { - .set = param_set_aauint, - .get = param_get_aauint -}; - -static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp); -static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp); -#define param_check_aalockpolicy param_check_bool -static struct kernel_param_ops param_ops_aalockpolicy = { - .set = param_set_aalockpolicy, - .get = param_get_aalockpolicy -}; - -static int param_set_audit(const char *val, struct kernel_param *kp); -static int param_get_audit(char *buffer, struct kernel_param *kp); - -static int param_set_mode(const char *val, struct kernel_param *kp); -static int param_get_mode(char *buffer, struct kernel_param *kp); - -/* Flag values, also controllable via /sys/module/apparmor/parameters - * We define special types as we want to do additional mediation. - */ - -/* AppArmor global enforcement switch - complain, enforce, kill */ -enum profile_mode aa_g_profile_mode = APPARMOR_ENFORCE; -module_param_call(mode, param_set_mode, param_get_mode, - &aa_g_profile_mode, S_IRUSR | S_IWUSR); - -/* Debug mode */ -bool aa_g_debug; -module_param_named(debug, aa_g_debug, aabool, S_IRUSR | S_IWUSR); - -/* Audit mode */ -enum audit_mode aa_g_audit; -module_param_call(audit, param_set_audit, param_get_audit, - &aa_g_audit, S_IRUSR | S_IWUSR); - -/* Determines if audit header is included in audited messages. This - * provides more context if the audit daemon is not running - */ -bool aa_g_audit_header = 1; -module_param_named(audit_header, aa_g_audit_header, aabool, - S_IRUSR | S_IWUSR); - -/* lock out loading/removal of policy - * TODO: add in at boot loading of policy, which is the only way to - * load policy, if lock_policy is set - */ -bool aa_g_lock_policy; -module_param_named(lock_policy, aa_g_lock_policy, aalockpolicy, - S_IRUSR | S_IWUSR); - -/* Syscall logging mode */ -bool aa_g_logsyscall; -module_param_named(logsyscall, aa_g_logsyscall, aabool, S_IRUSR | S_IWUSR); - -/* Maximum pathname length before accesses will start getting rejected */ -unsigned int aa_g_path_max = 2 * PATH_MAX; -module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR | S_IWUSR); - -/* Determines how paranoid loading of policy is and how much verification - * on the loaded policy is done. - */ -bool aa_g_paranoid_load = 1; -module_param_named(paranoid_load, aa_g_paranoid_load, aabool, - S_IRUSR | S_IWUSR); - -/* Boot time disable flag */ -static bool apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE; -module_param_named(enabled, apparmor_enabled, aabool, S_IRUSR); - -static int __init apparmor_enabled_setup(char *str) -{ - unsigned long enabled; - int error = strict_strtoul(str, 0, &enabled); - if (!error) - apparmor_enabled = enabled ? 1 : 0; - return 1; -} - -__setup("apparmor=", apparmor_enabled_setup); - -/* set global flag turning off the ability to load policy */ -static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp) -{ - if (!capable(CAP_MAC_ADMIN)) - return -EPERM; - if (aa_g_lock_policy) - return -EACCES; - return param_set_bool(val, kp); -} - -static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp) -{ - if (!capable(CAP_MAC_ADMIN)) - return -EPERM; - return param_get_bool(buffer, kp); -} - -static int param_set_aabool(const char *val, const struct kernel_param *kp) -{ - if (!capable(CAP_MAC_ADMIN)) - return -EPERM; - return param_set_bool(val, kp); -} - -static int param_get_aabool(char *buffer, const struct kernel_param *kp) -{ - if (!capable(CAP_MAC_ADMIN)) - return -EPERM; - return param_get_bool(buffer, kp); -} - -static int param_set_aauint(const char *val, const struct kernel_param *kp) -{ - if (!capable(CAP_MAC_ADMIN)) - return -EPERM; - return param_set_uint(val, kp); -} - -static int param_get_aauint(char *buffer, const struct kernel_param *kp) -{ - if (!capable(CAP_MAC_ADMIN)) - return -EPERM; - return param_get_uint(buffer, kp); -} - -static int param_get_audit(char *buffer, struct kernel_param *kp) -{ - if (!capable(CAP_MAC_ADMIN)) - return -EPERM; - - if (!apparmor_enabled) - return -EINVAL; - - return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]); -} - -static int param_set_audit(const char *val, struct kernel_param *kp) -{ - int i; - if (!capable(CAP_MAC_ADMIN)) - return -EPERM; - - if (!apparmor_enabled) - return -EINVAL; - - if (!val) - return -EINVAL; - - for (i = 0; i < AUDIT_MAX_INDEX; i++) { - if (strcmp(val, audit_mode_names[i]) == 0) { - aa_g_audit = i; - return 0; - } - } - - return -EINVAL; -} - -static int param_get_mode(char *buffer, struct kernel_param *kp) -{ - if (!capable(CAP_MAC_ADMIN)) - return -EPERM; - - if (!apparmor_enabled) - return -EINVAL; - - return sprintf(buffer, "%s", profile_mode_names[aa_g_profile_mode]); -} - -static int param_set_mode(const char *val, struct kernel_param *kp) -{ - int i; - if (!capable(CAP_MAC_ADMIN)) - return -EPERM; - - if (!apparmor_enabled) - return -EINVAL; - - if (!val) - return -EINVAL; - - for (i = 0; i < APPARMOR_NAMES_MAX_INDEX; i++) { - if (strcmp(val, profile_mode_names[i]) == 0) { - aa_g_profile_mode = i; - return 0; - } - } - - return -EINVAL; -} - -/* - * AppArmor init functions - */ - -/** - * set_init_cxt - set a task context and profile on the first task. - * - * TODO: allow setting an alternate profile than unconfined - */ -static int __init set_init_cxt(void) -{ - struct cred *cred = (struct cred *)current->real_cred; - struct aa_task_cxt *cxt; - - cxt = aa_alloc_task_context(GFP_KERNEL); - if (!cxt) - return -ENOMEM; - - cxt->profile = aa_get_profile(root_ns->unconfined); - cred->security = cxt; - - return 0; -} - -static int __init apparmor_init(void) -{ - int error; - - if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) { - aa_info_message("AppArmor disabled by boot time parameter"); - apparmor_enabled = 0; - return 0; - } - - error = aa_alloc_root_ns(); - if (error) { - AA_ERROR("Unable to allocate default profile namespace\n"); - goto alloc_out; - } - - error = set_init_cxt(); - if (error) { - AA_ERROR("Failed to set context on init task\n"); - goto register_security_out; - } - - error = register_security(&apparmor_ops); - if (error) { - AA_ERROR("Unable to register AppArmor\n"); - goto set_init_cxt_out; - } - - /* Report that AppArmor successfully initialized */ - apparmor_initialized = 1; - if (aa_g_profile_mode == APPARMOR_COMPLAIN) - aa_info_message("AppArmor initialized: complain mode enabled"); - else if (aa_g_profile_mode == APPARMOR_KILL) - aa_info_message("AppArmor initialized: kill mode enabled"); - else - aa_info_message("AppArmor initialized"); - - return error; - -set_init_cxt_out: - aa_free_task_context(current->real_cred->security); - -register_security_out: - aa_free_root_ns(); - -alloc_out: - aa_destroy_aafs(); - - apparmor_enabled = 0; - return error; -} - -security_initcall(apparmor_init); diff --git a/ANDROID_3.4.5/security/apparmor/match.c b/ANDROID_3.4.5/security/apparmor/match.c deleted file mode 100644 index 90971a8c..00000000 --- a/ANDROID_3.4.5/security/apparmor/match.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor dfa based regular expression matching engine - * - * 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/errno.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/err.h> -#include <linux/kref.h> - -#include "include/apparmor.h" -#include "include/match.h" - -/** - * unpack_table - unpack a dfa table (one of accept, default, base, next check) - * @blob: data to unpack (NOT NULL) - * @bsize: size of blob - * - * Returns: pointer to table else NULL on failure - * - * NOTE: must be freed by kvfree (not kmalloc) - */ -static struct table_header *unpack_table(char *blob, size_t bsize) -{ - struct table_header *table = NULL; - struct table_header th; - size_t tsize; - - if (bsize < sizeof(struct table_header)) - goto out; - - /* loaded td_id's start at 1, subtract 1 now to avoid doing - * it every time we use td_id as an index - */ - th.td_id = be16_to_cpu(*(u16 *) (blob)) - 1; - 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 || - th.td_flags == YYTD_DATA8)) - goto out; - - tsize = table_size(th.td_lolen, th.td_flags); - if (bsize < tsize) - goto out; - - table = kvmalloc(tsize); - if (table) { - *table = th; - if (th.td_flags == YYTD_DATA8) - UNPACK_ARRAY(table->td_data, blob, th.td_lolen, - u8, byte_to_byte); - else if (th.td_flags == YYTD_DATA16) - UNPACK_ARRAY(table->td_data, blob, th.td_lolen, - u16, be16_to_cpu); - else if (th.td_flags == YYTD_DATA32) - UNPACK_ARRAY(table->td_data, blob, th.td_lolen, - u32, be32_to_cpu); - else - goto fail; - } - -out: - /* if table was vmalloced make sure the page tables are synced - * before it is used, as it goes live to all cpus. - */ - if (is_vmalloc_addr(table)) - vm_unmap_aliases(); - return table; -fail: - kvfree(table); - return NULL; -} - -/** - * verify_dfa - verify that transitions and states in the tables are in bounds. - * @dfa: dfa to test (NOT NULL) - * @flags: flags controlling what type of accept table are acceptable - * - * Assumes dfa has gone through the first pass verification done by unpacking - * NOTE: this does not valid accept table values - * - * Returns: %0 else error code on failure to verify - */ -static int verify_dfa(struct aa_dfa *dfa, int flags) -{ - size_t i, state_count, trans_count; - int error = -EPROTO; - - /* check that required tables exist */ - if (!(dfa->tables[YYTD_ID_DEF] && - dfa->tables[YYTD_ID_BASE] && - dfa->tables[YYTD_ID_NXT] && dfa->tables[YYTD_ID_CHK])) - goto out; - - /* accept.size == default.size == base.size */ - state_count = dfa->tables[YYTD_ID_BASE]->td_lolen; - if (ACCEPT1_FLAGS(flags)) { - if (!dfa->tables[YYTD_ID_ACCEPT]) - goto out; - if (state_count != dfa->tables[YYTD_ID_ACCEPT]->td_lolen) - goto out; - } - if (ACCEPT2_FLAGS(flags)) { - if (!dfa->tables[YYTD_ID_ACCEPT2]) - goto out; - if (state_count != dfa->tables[YYTD_ID_ACCEPT2]->td_lolen) - goto out; - } - if (state_count != dfa->tables[YYTD_ID_DEF]->td_lolen) - goto out; - - /* next.size == chk.size */ - trans_count = dfa->tables[YYTD_ID_NXT]->td_lolen; - if (trans_count != dfa->tables[YYTD_ID_CHK]->td_lolen) - goto out; - - /* if equivalence classes then its table size must be 256 */ - if (dfa->tables[YYTD_ID_EC] && - dfa->tables[YYTD_ID_EC]->td_lolen != 256) - goto out; - - if (flags & DFA_FLAG_VERIFY_STATES) { - for (i = 0; i < state_count; i++) { - if (DEFAULT_TABLE(dfa)[i] >= state_count) - goto out; - /* TODO: do check that DEF state recursion terminates */ - if (BASE_TABLE(dfa)[i] + 255 >= trans_count) { - printk(KERN_ERR "AppArmor DFA next/check upper " - "bounds error\n"); - goto out; - } - } - - for (i = 0; i < trans_count; i++) { - if (NEXT_TABLE(dfa)[i] >= state_count) - goto out; - if (CHECK_TABLE(dfa)[i] >= state_count) - goto out; - } - } - - error = 0; -out: - return error; -} - -/** - * dfa_free - free a dfa allocated by aa_dfa_unpack - * @dfa: the dfa to free (MAYBE NULL) - * - * Requires: reference count to dfa == 0 - */ -static void dfa_free(struct aa_dfa *dfa) -{ - if (dfa) { - int i; - - for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) { - kvfree(dfa->tables[i]); - dfa->tables[i] = NULL; - } - kfree(dfa); - } -} - -/** - * aa_dfa_free_kref - free aa_dfa by kref (called by aa_put_dfa) - * @kr: kref callback for freeing of a dfa (NOT NULL) - */ -void aa_dfa_free_kref(struct kref *kref) -{ - struct aa_dfa *dfa = container_of(kref, struct aa_dfa, count); - dfa_free(dfa); -} - -/** - * aa_dfa_unpack - unpack the binary tables of a serialized dfa - * @blob: aligned serialized stream of data to unpack (NOT NULL) - * @size: size of data to unpack - * @flags: flags controlling what type of accept tables are acceptable - * - * Unpack a dfa that has been serialized. To find information on the dfa - * format look in Documentation/security/apparmor.txt - * Assumes the dfa @blob stream has been aligned on a 8 byte boundary - * - * Returns: an unpacked dfa ready for matching or ERR_PTR on failure - */ -struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags) -{ - int hsize; - int error = -ENOMEM; - char *data = blob; - struct table_header *table = NULL; - struct aa_dfa *dfa = kzalloc(sizeof(struct aa_dfa), GFP_KERNEL); - if (!dfa) - goto fail; - - kref_init(&dfa->count); - - error = -EPROTO; - - /* get dfa table set header */ - if (size < sizeof(struct table_set_header)) - goto fail; - - if (ntohl(*(u32 *) data) != YYTH_MAGIC) - goto fail; - - hsize = ntohl(*(u32 *) (data + 4)); - if (size < hsize) - goto fail; - - dfa->flags = ntohs(*(u16 *) (data + 12)); - data += hsize; - size -= hsize; - - while (size > 0) { - table = unpack_table(data, size); - if (!table) - goto fail; - - switch (table->td_id) { - case YYTD_ID_ACCEPT: - if (!(table->td_flags & ACCEPT1_FLAGS(flags))) - goto fail; - break; - case YYTD_ID_ACCEPT2: - if (!(table->td_flags & ACCEPT2_FLAGS(flags))) - goto fail; - break; - case YYTD_ID_BASE: - if (table->td_flags != YYTD_DATA32) - goto fail; - break; - case YYTD_ID_DEF: - case YYTD_ID_NXT: - case YYTD_ID_CHK: - if (table->td_flags != YYTD_DATA16) - goto fail; - break; - case YYTD_ID_EC: - if (table->td_flags != YYTD_DATA8) - goto fail; - break; - default: - goto fail; - } - /* check for duplicate table entry */ - if (dfa->tables[table->td_id]) - goto fail; - dfa->tables[table->td_id] = table; - data += table_size(table->td_lolen, table->td_flags); - size -= table_size(table->td_lolen, table->td_flags); - table = NULL; - } - - error = verify_dfa(dfa, flags); - if (error) - goto fail; - - return dfa; - -fail: - kvfree(table); - dfa_free(dfa); - return ERR_PTR(error); -} - -/** - * aa_dfa_match_len - traverse @dfa to find state @str stops at - * @dfa: the dfa to match @str against (NOT NULL) - * @start: the state of the dfa to start matching in - * @str: the string of bytes to match against the dfa (NOT NULL) - * @len: length of the string of bytes to match - * - * aa_dfa_match_len will match @str against the dfa and return the state it - * finished matching in. The final state can be used to look up the accepting - * label, or as the start state of a continuing match. - * - * This function will happily match again the 0 byte and only finishes - * when @len input is consumed. - * - * Returns: final state reached after input is consumed - */ -unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start, - const char *str, int len) -{ - u16 *def = DEFAULT_TABLE(dfa); - u32 *base = BASE_TABLE(dfa); - u16 *next = NEXT_TABLE(dfa); - u16 *check = CHECK_TABLE(dfa); - unsigned int state = start, pos; - - if (state == 0) - return 0; - - /* current state is <state>, matching character *str */ - if (dfa->tables[YYTD_ID_EC]) { - /* Equivalence class table defined */ - u8 *equiv = EQUIV_TABLE(dfa); - /* default is direct to next state */ - for (; len; len--) { - pos = base[state] + equiv[(u8) *str++]; - if (check[pos] == state) - state = next[pos]; - else - state = def[state]; - } - } else { - /* default is direct to next state */ - for (; len; len--) { - pos = base[state] + (u8) *str++; - if (check[pos] == state) - state = next[pos]; - else - state = def[state]; - } - } - - return state; -} - -/** - * aa_dfa_match - traverse @dfa to find state @str stops at - * @dfa: the dfa to match @str against (NOT NULL) - * @start: the state of the dfa to start matching in - * @str: the null terminated string of bytes to match against the dfa (NOT NULL) - * - * aa_dfa_match will match @str against the dfa and return the state it - * finished matching in. The final state can be used to look up the accepting - * label, or as the start state of a continuing match. - * - * Returns: final state reached after input is consumed - */ -unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start, - const char *str) -{ - u16 *def = DEFAULT_TABLE(dfa); - u32 *base = BASE_TABLE(dfa); - u16 *next = NEXT_TABLE(dfa); - u16 *check = CHECK_TABLE(dfa); - unsigned int state = start, pos; - - if (state == 0) - return 0; - - /* current state is <state>, matching character *str */ - if (dfa->tables[YYTD_ID_EC]) { - /* Equivalence class table defined */ - u8 *equiv = EQUIV_TABLE(dfa); - /* default is direct to next state */ - while (*str) { - pos = base[state] + equiv[(u8) *str++]; - if (check[pos] == state) - state = next[pos]; - else - state = def[state]; - } - } else { - /* default is direct to next state */ - while (*str) { - pos = base[state] + (u8) *str++; - if (check[pos] == state) - state = next[pos]; - else - state = def[state]; - } - } - - return state; -} - -/** - * aa_dfa_next - step one character to the next state in the dfa - * @dfa: the dfa to tranverse (NOT NULL) - * @state: the state to start in - * @c: the input character to transition on - * - * aa_dfa_match will step through the dfa by one input character @c - * - * Returns: state reach after input @c - */ -unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state, - const char c) -{ - u16 *def = DEFAULT_TABLE(dfa); - u32 *base = BASE_TABLE(dfa); - u16 *next = NEXT_TABLE(dfa); - u16 *check = CHECK_TABLE(dfa); - unsigned int pos; - - /* current state is <state>, matching character *str */ - if (dfa->tables[YYTD_ID_EC]) { - /* Equivalence class table defined */ - u8 *equiv = EQUIV_TABLE(dfa); - /* default is direct to next state */ - - pos = base[state] + equiv[(u8) c]; - if (check[pos] == state) - state = next[pos]; - else - state = def[state]; - } else { - /* default is direct to next state */ - pos = base[state] + (u8) c; - if (check[pos] == state) - state = next[pos]; - else - state = def[state]; - } - - return state; -} diff --git a/ANDROID_3.4.5/security/apparmor/path.c b/ANDROID_3.4.5/security/apparmor/path.c deleted file mode 100644 index 2daeea4f..00000000 --- a/ANDROID_3.4.5/security/apparmor/path.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor function for pathnames - * - * 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/magic.h> -#include <linux/mount.h> -#include <linux/namei.h> -#include <linux/nsproxy.h> -#include <linux/path.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/fs_struct.h> - -#include "include/apparmor.h" -#include "include/path.h" -#include "include/policy.h" - - -/* modified from dcache.c */ -static int prepend(char **buffer, int buflen, const char *str, int namelen) -{ - buflen -= namelen; - if (buflen < 0) - return -ENAMETOOLONG; - *buffer -= namelen; - memcpy(*buffer, str, namelen); - return 0; -} - -#define CHROOT_NSCONNECT (PATH_CHROOT_REL | PATH_CHROOT_NSCONNECT) - -/** - * d_namespace_path - lookup a name associated with a given path - * @path: path to lookup (NOT NULL) - * @buf: buffer to store path to (NOT NULL) - * @buflen: length of @buf - * @name: Returns - pointer for start of path name with in @buf (NOT NULL) - * @flags: flags controlling path lookup - * - * Handle path name lookup. - * - * Returns: %0 else error code if path lookup fails - * When no error the path name is returned in @name which points to - * to a position in @buf - */ -static int d_namespace_path(struct path *path, char *buf, int buflen, - char **name, int flags) -{ - char *res; - int error = 0; - int connected = 1; - - if (path->mnt->mnt_flags & MNT_INTERNAL) { - /* it's not mounted anywhere */ - res = dentry_path(path->dentry, buf, buflen); - *name = res; - if (IS_ERR(res)) { - *name = buf; - return PTR_ERR(res); - } - if (path->dentry->d_sb->s_magic == PROC_SUPER_MAGIC && - strncmp(*name, "/sys/", 5) == 0) { - /* TODO: convert over to using a per namespace - * control instead of hard coded /proc - */ - return prepend(name, *name - buf, "/proc", 5); - } - return 0; - } - - /* resolve paths relative to chroot?*/ - if (flags & PATH_CHROOT_REL) { - struct path root; - get_fs_root(current->fs, &root); - res = __d_path(path, &root, buf, buflen); - path_put(&root); - } else { - res = d_absolute_path(path, buf, buflen); - if (!our_mnt(path->mnt)) - connected = 0; - } - - /* handle error conditions - and still allow a partial path to - * be returned. - */ - if (!res || IS_ERR(res)) { - connected = 0; - res = dentry_path_raw(path->dentry, buf, buflen); - if (IS_ERR(res)) { - error = PTR_ERR(res); - *name = buf; - goto out; - }; - } else if (!our_mnt(path->mnt)) - connected = 0; - - *name = res; - - /* Handle two cases: - * 1. A deleted dentry && profile is not allowing mediation of deleted - * 2. On some filesystems, newly allocated dentries appear to the - * security_path hooks as a deleted dentry except without an inode - * allocated. - */ - if (d_unlinked(path->dentry) && path->dentry->d_inode && - !(flags & PATH_MEDIATE_DELETED)) { - error = -ENOENT; - goto out; - } - - /* If the path is not connected to the expected root, - * check if it is a sysctl and handle specially else remove any - * leading / that __d_path may have returned. - * Unless - * specifically directed to connect the path, - * OR - * if in a chroot and doing chroot relative paths and the path - * resolves to the namespace root (would be connected outside - * of chroot) and specifically directed to connect paths to - * namespace root. - */ - if (!connected) { - if (!(flags & PATH_CONNECT_PATH) && - !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) && - our_mnt(path->mnt))) { - /* disconnected path, don't return pathname starting - * with '/' - */ - error = -EACCES; - if (*res == '/') - *name = res + 1; - } - } - -out: - return error; -} - -/** - * get_name_to_buffer - get the pathname to a buffer ensure dir / is appended - * @path: path to get name for (NOT NULL) - * @flags: flags controlling path lookup - * @buffer: buffer to put name in (NOT NULL) - * @size: size of buffer - * @name: Returns - contains position of path name in @buffer (NOT NULL) - * - * Returns: %0 else error on failure - */ -static int get_name_to_buffer(struct path *path, int flags, char *buffer, - int size, char **name, const char **info) -{ - int adjust = (flags & PATH_IS_DIR) ? 1 : 0; - int error = d_namespace_path(path, buffer, size - adjust, name, flags); - - if (!error && (flags & PATH_IS_DIR) && (*name)[1] != '\0') - /* - * Append "/" to the pathname. The root directory is a special - * case; it already ends in slash. - */ - strcpy(&buffer[size - 2], "/"); - - if (info && error) { - if (error == -ENOENT) - *info = "Failed name lookup - deleted entry"; - else if (error == -ESTALE) - *info = "Failed name lookup - disconnected path"; - else if (error == -ENAMETOOLONG) - *info = "Failed name lookup - name too long"; - else - *info = "Failed name lookup"; - } - - return error; -} - -/** - * aa_path_name - compute the pathname of a file - * @path: path the file (NOT NULL) - * @flags: flags controlling path name generation - * @buffer: buffer that aa_get_name() allocated (NOT NULL) - * @name: Returns - the generated path name if !error (NOT NULL) - * @info: Returns - information on why the path lookup failed (MAYBE NULL) - * - * @name is a pointer to the beginning of the pathname (which usually differs - * from the beginning of the buffer), or NULL. If there is an error @name - * may contain a partial or invalid name that can be used for audit purposes, - * but it can not be used for mediation. - * - * We need PATH_IS_DIR to indicate whether the file is a directory or not - * because the file may not yet exist, and so we cannot check the inode's - * file type. - * - * Returns: %0 else error code if could retrieve name - */ -int aa_path_name(struct path *path, int flags, char **buffer, const char **name, - const char **info) -{ - char *buf, *str = NULL; - int size = 256; - int error; - - *name = NULL; - *buffer = NULL; - for (;;) { - /* freed by caller */ - buf = kmalloc(size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - error = get_name_to_buffer(path, flags, buf, size, &str, info); - if (error != -ENAMETOOLONG) - break; - - kfree(buf); - size <<= 1; - if (size > aa_g_path_max) - return -ENAMETOOLONG; - *info = NULL; - } - *buffer = buf; - *name = str; - - return error; -} diff --git a/ANDROID_3.4.5/security/apparmor/policy.c b/ANDROID_3.4.5/security/apparmor/policy.c deleted file mode 100644 index f1f7506a..00000000 --- a/ANDROID_3.4.5/security/apparmor/policy.c +++ /dev/null @@ -1,1189 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor policy manipulation 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. - * - * - * AppArmor policy is based around profiles, which contain the rules a - * task is confined by. Every task in the system has a profile attached - * to it determined either by matching "unconfined" tasks against the - * visible set of profiles or by following a profiles attachment rules. - * - * Each profile exists in a profile namespace which is a container of - * visible profiles. Each namespace contains a special "unconfined" profile, - * which doesn't enforce any confinement on a task beyond DAC. - * - * Namespace and profile names can be written together in either - * of two syntaxes. - * :namespace:profile - used by kernel interfaces for easy detection - * namespace://profile - used by policy - * - * Profile names can not start with : or @ or ^ and may not contain \0 - * - * Reserved profile names - * unconfined - special automatically generated unconfined profile - * inherit - special name to indicate profile inheritance - * null-XXXX-YYYY - special automatically generated learning profiles - * - * Namespace names may not start with / or @ and may not contain \0 or : - * Reserved namespace names - * user-XXXX - user defined profiles - * - * a // in a profile or namespace name indicates a hierarchical name with the - * name before the // being the parent and the name after the child. - * - * Profile and namespace hierarchies serve two different but similar purposes. - * The namespace contains the set of visible profiles that are considered - * for attachment. The hierarchy of namespaces allows for virtualizing - * the namespace so that for example a chroot can have its own set of profiles - * which may define some local user namespaces. - * The profile hierarchy severs two distinct purposes, - * - it allows for sub profiles or hats, which allows an application to run - * subprograms under its own profile with different restriction than it - * self, and not have it use the system profile. - * eg. if a mail program starts an editor, the policy might make the - * restrictions tighter on the editor tighter than the mail program, - * and definitely different than general editor restrictions - * - it allows for binary hierarchy of profiles, so that execution history - * is preserved. This feature isn't exploited by AppArmor reference policy - * but is allowed. NOTE: this is currently suboptimal because profile - * aliasing is not currently implemented so that a profile for each - * level must be defined. - * eg. /bin/bash///bin/ls as a name would indicate /bin/ls was started - * from /bin/bash - * - * A profile or namespace name that can contain one or more // separators - * is referred to as an hname (hierarchical). - * eg. /bin/bash//bin/ls - * - * An fqname is a name that may contain both namespace and profile hnames. - * eg. :ns:/bin/bash//bin/ls - * - * NOTES: - * - locking of profile lists is currently fairly coarse. All profile - * lists within a namespace use the namespace lock. - * FIXME: move profile lists to using rcu_lists - */ - -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/string.h> - -#include "include/apparmor.h" -#include "include/capability.h" -#include "include/context.h" -#include "include/file.h" -#include "include/ipc.h" -#include "include/match.h" -#include "include/path.h" -#include "include/policy.h" -#include "include/policy_unpack.h" -#include "include/resource.h" -#include "include/sid.h" - - -/* root profile namespace */ -struct aa_namespace *root_ns; - -const char *const profile_mode_names[] = { - "enforce", - "complain", - "kill", -}; - -/** - * hname_tail - find the last component of an hname - * @name: hname to find the base profile name component of (NOT NULL) - * - * Returns: the tail (base profile name) name component of an hname - */ -static const char *hname_tail(const char *hname) -{ - char *split; - hname = strim((char *)hname); - for (split = strstr(hname, "//"); split; split = strstr(hname, "//")) - hname = split + 2; - - return hname; -} - -/** - * policy_init - initialize a policy structure - * @policy: policy to initialize (NOT NULL) - * @prefix: prefix name if any is required. (MAYBE NULL) - * @name: name of the policy, init will make a copy of it (NOT NULL) - * - * Note: this fn creates a copy of strings passed in - * - * Returns: true if policy init successful - */ -static bool policy_init(struct aa_policy *policy, const char *prefix, - const char *name) -{ - /* freed by policy_free */ - if (prefix) { - policy->hname = kmalloc(strlen(prefix) + strlen(name) + 3, - GFP_KERNEL); - if (policy->hname) - sprintf(policy->hname, "%s//%s", prefix, name); - } else - policy->hname = kstrdup(name, GFP_KERNEL); - if (!policy->hname) - return 0; - /* base.name is a substring of fqname */ - policy->name = (char *)hname_tail(policy->hname); - INIT_LIST_HEAD(&policy->list); - INIT_LIST_HEAD(&policy->profiles); - kref_init(&policy->count); - - return 1; -} - -/** - * policy_destroy - free the elements referenced by @policy - * @policy: policy that is to have its elements freed (NOT NULL) - */ -static void policy_destroy(struct aa_policy *policy) -{ - /* still contains profiles -- invalid */ - if (!list_empty(&policy->profiles)) { - AA_ERROR("%s: internal error, " - "policy '%s' still contains profiles\n", - __func__, policy->name); - BUG(); - } - if (!list_empty(&policy->list)) { - AA_ERROR("%s: internal error, policy '%s' still on list\n", - __func__, policy->name); - BUG(); - } - - /* don't free name as its a subset of hname */ - kzfree(policy->hname); -} - -/** - * __policy_find - find a policy by @name on a policy list - * @head: list to search (NOT NULL) - * @name: name to search for (NOT NULL) - * - * Requires: correct locks for the @head list be held - * - * Returns: unrefcounted policy that match @name or NULL if not found - */ -static struct aa_policy *__policy_find(struct list_head *head, const char *name) -{ - struct aa_policy *policy; - - list_for_each_entry(policy, head, list) { - if (!strcmp(policy->name, name)) - return policy; - } - return NULL; -} - -/** - * __policy_strn_find - find a policy that's name matches @len chars of @str - * @head: list to search (NOT NULL) - * @str: string to search for (NOT NULL) - * @len: length of match required - * - * Requires: correct locks for the @head list be held - * - * Returns: unrefcounted policy that match @str or NULL if not found - * - * if @len == strlen(@strlen) then this is equiv to __policy_find - * other wise it allows searching for policy by a partial match of name - */ -static struct aa_policy *__policy_strn_find(struct list_head *head, - const char *str, int len) -{ - struct aa_policy *policy; - - list_for_each_entry(policy, head, list) { - if (aa_strneq(policy->name, str, len)) - return policy; - } - - return NULL; -} - -/* - * Routines for AppArmor namespaces - */ - -static const char *hidden_ns_name = "---"; -/** - * aa_ns_visible - test if @view is visible from @curr - * @curr: namespace to treat as the parent (NOT NULL) - * @view: namespace to test if visible from @curr (NOT NULL) - * - * Returns: true if @view is visible from @curr else false - */ -bool aa_ns_visible(struct aa_namespace *curr, struct aa_namespace *view) -{ - if (curr == view) - return true; - - for ( ; view; view = view->parent) { - if (view->parent == curr) - return true; - } - return false; -} - -/** - * aa_na_name - Find the ns name to display for @view from @curr - * @curr - current namespace (NOT NULL) - * @view - namespace attempting to view (NOT NULL) - * - * Returns: name of @view visible from @curr - */ -const char *aa_ns_name(struct aa_namespace *curr, struct aa_namespace *view) -{ - /* if view == curr then the namespace name isn't displayed */ - if (curr == view) - return ""; - - if (aa_ns_visible(curr, view)) { - /* at this point if a ns is visible it is in a view ns - * thus the curr ns.hname is a prefix of its name. - * Only output the virtualized portion of the name - * Add + 2 to skip over // separating curr hname prefix - * from the visible tail of the views hname - */ - return view->base.hname + strlen(curr->base.hname) + 2; - } else - return hidden_ns_name; -} - -/** - * alloc_namespace - allocate, initialize and return a new namespace - * @prefix: parent namespace name (MAYBE NULL) - * @name: a preallocated name (NOT NULL) - * - * Returns: refcounted namespace or NULL on failure. - */ -static struct aa_namespace *alloc_namespace(const char *prefix, - const char *name) -{ - struct aa_namespace *ns; - - ns = kzalloc(sizeof(*ns), GFP_KERNEL); - AA_DEBUG("%s(%p)\n", __func__, ns); - if (!ns) - return NULL; - if (!policy_init(&ns->base, prefix, name)) - goto fail_ns; - - INIT_LIST_HEAD(&ns->sub_ns); - rwlock_init(&ns->lock); - - /* released by free_namespace */ - ns->unconfined = aa_alloc_profile("unconfined"); - if (!ns->unconfined) - goto fail_unconfined; - - ns->unconfined->sid = aa_alloc_sid(); - ns->unconfined->flags = PFLAG_UNCONFINED | PFLAG_IX_ON_NAME_ERROR | - PFLAG_IMMUTABLE; - - /* - * released by free_namespace, however __remove_namespace breaks - * the cyclic references (ns->unconfined, and unconfined->ns) and - * replaces with refs to parent namespace unconfined - */ - ns->unconfined->ns = aa_get_namespace(ns); - - return ns; - -fail_unconfined: - kzfree(ns->base.hname); -fail_ns: - kzfree(ns); - return NULL; -} - -/** - * free_namespace - free a profile namespace - * @ns: the namespace to free (MAYBE NULL) - * - * Requires: All references to the namespace must have been put, if the - * namespace was referenced by a profile confining a task, - */ -static void free_namespace(struct aa_namespace *ns) -{ - if (!ns) - return; - - policy_destroy(&ns->base); - aa_put_namespace(ns->parent); - - if (ns->unconfined && ns->unconfined->ns == ns) - ns->unconfined->ns = NULL; - - aa_put_profile(ns->unconfined); - kzfree(ns); -} - -/** - * aa_free_namespace_kref - free aa_namespace by kref (see aa_put_namespace) - * @kr: kref callback for freeing of a namespace (NOT NULL) - */ -void aa_free_namespace_kref(struct kref *kref) -{ - free_namespace(container_of(kref, struct aa_namespace, base.count)); -} - -/** - * __aa_find_namespace - find a namespace on a list by @name - * @head: list to search for namespace on (NOT NULL) - * @name: name of namespace to look for (NOT NULL) - * - * Returns: unrefcounted namespace - * - * Requires: ns lock be held - */ -static struct aa_namespace *__aa_find_namespace(struct list_head *head, - const char *name) -{ - return (struct aa_namespace *)__policy_find(head, name); -} - -/** - * aa_find_namespace - look up a profile namespace on the namespace list - * @root: namespace to search in (NOT NULL) - * @name: name of namespace to find (NOT NULL) - * - * Returns: a refcounted namespace on the list, or NULL if no namespace - * called @name exists. - * - * refcount released by caller - */ -struct aa_namespace *aa_find_namespace(struct aa_namespace *root, - const char *name) -{ - struct aa_namespace *ns = NULL; - - read_lock(&root->lock); - ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name)); - read_unlock(&root->lock); - - return ns; -} - -/** - * aa_prepare_namespace - find an existing or create a new namespace of @name - * @name: the namespace to find or add (MAYBE NULL) - * - * Returns: refcounted namespace or NULL if failed to create one - */ -static struct aa_namespace *aa_prepare_namespace(const char *name) -{ - struct aa_namespace *ns, *root; - - root = aa_current_profile()->ns; - - write_lock(&root->lock); - - /* if name isn't specified the profile is loaded to the current ns */ - if (!name) { - /* released by caller */ - ns = aa_get_namespace(root); - goto out; - } - - /* try and find the specified ns and if it doesn't exist create it */ - /* released by caller */ - ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name)); - if (!ns) { - /* namespace not found */ - struct aa_namespace *new_ns; - write_unlock(&root->lock); - new_ns = alloc_namespace(root->base.hname, name); - if (!new_ns) - return NULL; - write_lock(&root->lock); - /* test for race when new_ns was allocated */ - ns = __aa_find_namespace(&root->sub_ns, name); - if (!ns) { - /* add parent ref */ - new_ns->parent = aa_get_namespace(root); - - list_add(&new_ns->base.list, &root->sub_ns); - /* add list ref */ - ns = aa_get_namespace(new_ns); - } else { - /* raced so free the new one */ - free_namespace(new_ns); - /* get reference on namespace */ - aa_get_namespace(ns); - } - } -out: - write_unlock(&root->lock); - - /* return ref */ - return ns; -} - -/** - * __list_add_profile - add a profile to a list - * @list: list to add it to (NOT NULL) - * @profile: the profile to add (NOT NULL) - * - * refcount @profile, should be put by __list_remove_profile - * - * Requires: namespace lock be held, or list not be shared - */ -static void __list_add_profile(struct list_head *list, - struct aa_profile *profile) -{ - list_add(&profile->base.list, list); - /* get list reference */ - aa_get_profile(profile); -} - -/** - * __list_remove_profile - remove a profile from the list it is on - * @profile: the profile to remove (NOT NULL) - * - * remove a profile from the list, warning generally removal should - * be done with __replace_profile as most profile removals are - * replacements to the unconfined profile. - * - * put @profile list refcount - * - * Requires: namespace lock be held, or list not have been live - */ -static void __list_remove_profile(struct aa_profile *profile) -{ - list_del_init(&profile->base.list); - if (!(profile->flags & PFLAG_NO_LIST_REF)) - /* release list reference */ - aa_put_profile(profile); -} - -/** - * __replace_profile - replace @old with @new on a list - * @old: profile to be replaced (NOT NULL) - * @new: profile to replace @old with (NOT NULL) - * - * Will duplicate and refcount elements that @new inherits from @old - * and will inherit @old children. - * - * refcount @new for list, put @old list refcount - * - * Requires: namespace list lock be held, or list not be shared - */ -static void __replace_profile(struct aa_profile *old, struct aa_profile *new) -{ - struct aa_policy *policy; - struct aa_profile *child, *tmp; - - if (old->parent) - policy = &old->parent->base; - else - policy = &old->ns->base; - - /* released when @new is freed */ - new->parent = aa_get_profile(old->parent); - new->ns = aa_get_namespace(old->ns); - new->sid = old->sid; - __list_add_profile(&policy->profiles, new); - /* inherit children */ - list_for_each_entry_safe(child, tmp, &old->base.profiles, base.list) { - aa_put_profile(child->parent); - child->parent = aa_get_profile(new); - /* list refcount transferred to @new*/ - list_move(&child->base.list, &new->base.profiles); - } - - /* released by free_profile */ - old->replacedby = aa_get_profile(new); - __list_remove_profile(old); -} - -static void __profile_list_release(struct list_head *head); - -/** - * __remove_profile - remove old profile, and children - * @profile: profile to be replaced (NOT NULL) - * - * Requires: namespace list lock be held, or list not be shared - */ -static void __remove_profile(struct aa_profile *profile) -{ - /* release any children lists first */ - __profile_list_release(&profile->base.profiles); - /* released by free_profile */ - profile->replacedby = aa_get_profile(profile->ns->unconfined); - __list_remove_profile(profile); -} - -/** - * __profile_list_release - remove all profiles on the list and put refs - * @head: list of profiles (NOT NULL) - * - * Requires: namespace lock be held - */ -static void __profile_list_release(struct list_head *head) -{ - struct aa_profile *profile, *tmp; - list_for_each_entry_safe(profile, tmp, head, base.list) - __remove_profile(profile); -} - -static void __ns_list_release(struct list_head *head); - -/** - * destroy_namespace - remove everything contained by @ns - * @ns: namespace to have it contents removed (NOT NULL) - */ -static void destroy_namespace(struct aa_namespace *ns) -{ - if (!ns) - return; - - write_lock(&ns->lock); - /* release all profiles in this namespace */ - __profile_list_release(&ns->base.profiles); - - /* release all sub namespaces */ - __ns_list_release(&ns->sub_ns); - - write_unlock(&ns->lock); -} - -/** - * __remove_namespace - remove a namespace and all its children - * @ns: namespace to be removed (NOT NULL) - * - * Requires: ns->parent->lock be held and ns removed from parent. - */ -static void __remove_namespace(struct aa_namespace *ns) -{ - struct aa_profile *unconfined = ns->unconfined; - - /* remove ns from namespace list */ - list_del_init(&ns->base.list); - - /* - * break the ns, unconfined profile cyclic reference and forward - * all new unconfined profiles requests to the parent namespace - * This will result in all confined tasks that have a profile - * being removed, inheriting the parent->unconfined profile. - */ - if (ns->parent) - ns->unconfined = aa_get_profile(ns->parent->unconfined); - - destroy_namespace(ns); - - /* release original ns->unconfined ref */ - aa_put_profile(unconfined); - /* release ns->base.list ref, from removal above */ - aa_put_namespace(ns); -} - -/** - * __ns_list_release - remove all profile namespaces on the list put refs - * @head: list of profile namespaces (NOT NULL) - * - * Requires: namespace lock be held - */ -static void __ns_list_release(struct list_head *head) -{ - struct aa_namespace *ns, *tmp; - list_for_each_entry_safe(ns, tmp, head, base.list) - __remove_namespace(ns); - -} - -/** - * aa_alloc_root_ns - allocate the root profile namespace - * - * Returns: %0 on success else error - * - */ -int __init aa_alloc_root_ns(void) -{ - /* released by aa_free_root_ns - used as list ref*/ - root_ns = alloc_namespace(NULL, "root"); - if (!root_ns) - return -ENOMEM; - - return 0; -} - - /** - * aa_free_root_ns - free the root profile namespace - */ -void __init aa_free_root_ns(void) - { - struct aa_namespace *ns = root_ns; - root_ns = NULL; - - destroy_namespace(ns); - aa_put_namespace(ns); -} - -/** - * aa_alloc_profile - allocate, initialize and return a new profile - * @hname: name of the profile (NOT NULL) - * - * Returns: refcount profile or NULL on failure - */ -struct aa_profile *aa_alloc_profile(const char *hname) -{ - struct aa_profile *profile; - - /* freed by free_profile - usually through aa_put_profile */ - profile = kzalloc(sizeof(*profile), GFP_KERNEL); - if (!profile) - return NULL; - - if (!policy_init(&profile->base, NULL, hname)) { - kzfree(profile); - return NULL; - } - - /* refcount released by caller */ - return profile; -} - -/** - * aa_new_null_profile - create a new null-X learning profile - * @parent: profile that caused this profile to be created (NOT NULL) - * @hat: true if the null- learning profile is a hat - * - * Create a null- complain mode profile used in learning mode. The name of - * the profile is unique and follows the format of parent//null-sid. - * - * null profiles are added to the profile list but the list does not - * hold a count on them so that they are automatically released when - * not in use. - * - * Returns: new refcounted profile else NULL on failure - */ -struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat) -{ - struct aa_profile *profile = NULL; - char *name; - u32 sid = aa_alloc_sid(); - - /* freed below */ - name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, GFP_KERNEL); - if (!name) - goto fail; - sprintf(name, "%s//null-%x", parent->base.hname, sid); - - profile = aa_alloc_profile(name); - kfree(name); - if (!profile) - goto fail; - - profile->sid = sid; - profile->mode = APPARMOR_COMPLAIN; - profile->flags = PFLAG_NULL; - if (hat) - profile->flags |= PFLAG_HAT; - - /* released on free_profile */ - profile->parent = aa_get_profile(parent); - profile->ns = aa_get_namespace(parent->ns); - - write_lock(&profile->ns->lock); - __list_add_profile(&parent->base.profiles, profile); - write_unlock(&profile->ns->lock); - - /* refcount released by caller */ - return profile; - -fail: - aa_free_sid(sid); - return NULL; -} - -/** - * free_profile - free a profile - * @profile: the profile to free (MAYBE NULL) - * - * Free a profile, its hats and null_profile. All references to the profile, - * its hats and null_profile must have been put. - * - * If the profile was referenced from a task context, free_profile() will - * be called from an rcu callback routine, so we must not sleep here. - */ -static void free_profile(struct aa_profile *profile) -{ - AA_DEBUG("%s(%p)\n", __func__, profile); - - if (!profile) - return; - - if (!list_empty(&profile->base.list)) { - AA_ERROR("%s: internal error, " - "profile '%s' still on ns list\n", - __func__, profile->base.name); - BUG(); - } - - /* free children profiles */ - policy_destroy(&profile->base); - aa_put_profile(profile->parent); - - aa_put_namespace(profile->ns); - kzfree(profile->rename); - - aa_free_file_rules(&profile->file); - aa_free_cap_rules(&profile->caps); - aa_free_rlimit_rules(&profile->rlimits); - - aa_free_sid(profile->sid); - aa_put_dfa(profile->xmatch); - aa_put_dfa(profile->policy.dfa); - - aa_put_profile(profile->replacedby); - - kzfree(profile); -} - -/** - * aa_free_profile_kref - free aa_profile by kref (called by aa_put_profile) - * @kr: kref callback for freeing of a profile (NOT NULL) - */ -void aa_free_profile_kref(struct kref *kref) -{ - struct aa_profile *p = container_of(kref, struct aa_profile, - base.count); - - free_profile(p); -} - -/* TODO: profile accounting - setup in remove */ - -/** - * __find_child - find a profile on @head list with a name matching @name - * @head: list to search (NOT NULL) - * @name: name of profile (NOT NULL) - * - * Requires: ns lock protecting list be held - * - * Returns: unrefcounted profile ptr, or NULL if not found - */ -static struct aa_profile *__find_child(struct list_head *head, const char *name) -{ - return (struct aa_profile *)__policy_find(head, name); -} - -/** - * __strn_find_child - find a profile on @head list using substring of @name - * @head: list to search (NOT NULL) - * @name: name of profile (NOT NULL) - * @len: length of @name substring to match - * - * Requires: ns lock protecting list be held - * - * Returns: unrefcounted profile ptr, or NULL if not found - */ -static struct aa_profile *__strn_find_child(struct list_head *head, - const char *name, int len) -{ - return (struct aa_profile *)__policy_strn_find(head, name, len); -} - -/** - * aa_find_child - find a profile by @name in @parent - * @parent: profile to search (NOT NULL) - * @name: profile name to search for (NOT NULL) - * - * Returns: a refcounted profile or NULL if not found - */ -struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name) -{ - struct aa_profile *profile; - - read_lock(&parent->ns->lock); - profile = aa_get_profile(__find_child(&parent->base.profiles, name)); - read_unlock(&parent->ns->lock); - - /* refcount released by caller */ - return profile; -} - -/** - * __lookup_parent - lookup the parent of a profile of name @hname - * @ns: namespace to lookup profile in (NOT NULL) - * @hname: hierarchical profile name to find parent of (NOT NULL) - * - * Lookups up the parent of a fully qualified profile name, the profile - * that matches hname does not need to exist, in general this - * is used to load a new profile. - * - * Requires: ns->lock be held - * - * Returns: unrefcounted policy or NULL if not found - */ -static struct aa_policy *__lookup_parent(struct aa_namespace *ns, - const char *hname) -{ - struct aa_policy *policy; - struct aa_profile *profile = NULL; - char *split; - - policy = &ns->base; - - for (split = strstr(hname, "//"); split;) { - profile = __strn_find_child(&policy->profiles, hname, - split - hname); - if (!profile) - return NULL; - policy = &profile->base; - hname = split + 2; - split = strstr(hname, "//"); - } - if (!profile) - return &ns->base; - return &profile->base; -} - -/** - * __lookup_profile - lookup the profile matching @hname - * @base: base list to start looking up profile name from (NOT NULL) - * @hname: hierarchical profile name (NOT NULL) - * - * Requires: ns->lock be held - * - * Returns: unrefcounted profile pointer or NULL if not found - * - * Do a relative name lookup, recursing through profile tree. - */ -static struct aa_profile *__lookup_profile(struct aa_policy *base, - const char *hname) -{ - struct aa_profile *profile = NULL; - char *split; - - for (split = strstr(hname, "//"); split;) { - profile = __strn_find_child(&base->profiles, hname, - split - hname); - if (!profile) - return NULL; - - base = &profile->base; - hname = split + 2; - split = strstr(hname, "//"); - } - - profile = __find_child(&base->profiles, hname); - - return profile; -} - -/** - * aa_lookup_profile - find a profile by its full or partial name - * @ns: the namespace to start from (NOT NULL) - * @hname: name to do lookup on. Does not contain namespace prefix (NOT NULL) - * - * Returns: refcounted profile or NULL if not found - */ -struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *hname) -{ - struct aa_profile *profile; - - read_lock(&ns->lock); - profile = aa_get_profile(__lookup_profile(&ns->base, hname)); - read_unlock(&ns->lock); - - /* refcount released by caller */ - return profile; -} - -/** - * replacement_allowed - test to see if replacement is allowed - * @profile: profile to test if it can be replaced (MAYBE NULL) - * @noreplace: true if replacement shouldn't be allowed but addition is okay - * @info: Returns - info about why replacement failed (NOT NULL) - * - * Returns: %0 if replacement allowed else error code - */ -static int replacement_allowed(struct aa_profile *profile, int noreplace, - const char **info) -{ - if (profile) { - if (profile->flags & PFLAG_IMMUTABLE) { - *info = "cannot replace immutible profile"; - return -EPERM; - } else if (noreplace) { - *info = "profile already exists"; - return -EEXIST; - } - } - return 0; -} - -/** - * __add_new_profile - simple wrapper around __list_add_profile - * @ns: namespace that profile is being added to (NOT NULL) - * @policy: the policy container to add the profile to (NOT NULL) - * @profile: profile to add (NOT NULL) - * - * add a profile to a list and do other required basic allocations - */ -static void __add_new_profile(struct aa_namespace *ns, struct aa_policy *policy, - struct aa_profile *profile) -{ - if (policy != &ns->base) - /* released on profile replacement or free_profile */ - profile->parent = aa_get_profile((struct aa_profile *) policy); - __list_add_profile(&policy->profiles, profile); - /* released on free_profile */ - profile->sid = aa_alloc_sid(); - profile->ns = aa_get_namespace(ns); -} - -/** - * aa_audit_policy - Do auditing of policy changes - * @op: policy operation being performed - * @gfp: memory allocation flags - * @name: name of profile being manipulated (NOT NULL) - * @info: any extra information to be audited (MAYBE NULL) - * @error: error code - * - * Returns: the error to be returned after audit is done - */ -static int audit_policy(int op, gfp_t gfp, const char *name, const char *info, - int error) -{ - struct common_audit_data sa; - struct apparmor_audit_data aad = {0,}; - COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad = &aad; - aad.op = op; - aad.name = name; - aad.info = info; - aad.error = error; - - return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp, - &sa, NULL); -} - -/** - * aa_may_manage_policy - can the current task manage policy - * @op: the policy manipulation operation being done - * - * Returns: true if the task is allowed to manipulate policy - */ -bool aa_may_manage_policy(int op) -{ - /* check if loading policy is locked out */ - if (aa_g_lock_policy) { - audit_policy(op, GFP_KERNEL, NULL, "policy_locked", -EACCES); - return 0; - } - - if (!capable(CAP_MAC_ADMIN)) { - audit_policy(op, GFP_KERNEL, NULL, "not policy admin", -EACCES); - return 0; - } - - return 1; -} - -/** - * aa_replace_profiles - replace profile(s) on the profile list - * @udata: serialized data stream (NOT NULL) - * @size: size of the serialized data stream - * @noreplace: true if only doing addition, no replacement allowed - * - * unpack and replace a profile on the profile list and uses of that profile - * by any aa_task_cxt. If the profile does not exist on the profile list - * it is added. - * - * Returns: size of data consumed else error code on failure. - */ -ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace) -{ - struct aa_policy *policy; - struct aa_profile *old_profile = NULL, *new_profile = NULL; - struct aa_profile *rename_profile = NULL; - struct aa_namespace *ns = NULL; - const char *ns_name, *name = NULL, *info = NULL; - int op = OP_PROF_REPL; - ssize_t error; - - /* released below */ - new_profile = aa_unpack(udata, size, &ns_name); - if (IS_ERR(new_profile)) { - error = PTR_ERR(new_profile); - new_profile = NULL; - goto fail; - } - - /* released below */ - ns = aa_prepare_namespace(ns_name); - if (!ns) { - info = "failed to prepare namespace"; - error = -ENOMEM; - name = ns_name; - goto fail; - } - - name = new_profile->base.hname; - - write_lock(&ns->lock); - /* no ref on policy only use inside lock */ - policy = __lookup_parent(ns, new_profile->base.hname); - - if (!policy) { - info = "parent does not exist"; - error = -ENOENT; - goto audit; - } - - old_profile = __find_child(&policy->profiles, new_profile->base.name); - /* released below */ - aa_get_profile(old_profile); - - if (new_profile->rename) { - rename_profile = __lookup_profile(&ns->base, - new_profile->rename); - /* released below */ - aa_get_profile(rename_profile); - - if (!rename_profile) { - info = "profile to rename does not exist"; - name = new_profile->rename; - error = -ENOENT; - goto audit; - } - } - - error = replacement_allowed(old_profile, noreplace, &info); - if (error) - goto audit; - - error = replacement_allowed(rename_profile, noreplace, &info); - if (error) - goto audit; - -audit: - if (!old_profile && !rename_profile) - op = OP_PROF_LOAD; - - error = audit_policy(op, GFP_ATOMIC, name, info, error); - - if (!error) { - if (rename_profile) - __replace_profile(rename_profile, new_profile); - if (old_profile) { - /* when there are both rename and old profiles - * inherit old profiles sid - */ - if (rename_profile) - aa_free_sid(new_profile->sid); - __replace_profile(old_profile, new_profile); - } - if (!(old_profile || rename_profile)) - __add_new_profile(ns, policy, new_profile); - } - write_unlock(&ns->lock); - -out: - aa_put_namespace(ns); - aa_put_profile(rename_profile); - aa_put_profile(old_profile); - aa_put_profile(new_profile); - if (error) - return error; - return size; - -fail: - error = audit_policy(op, GFP_KERNEL, name, info, error); - goto out; -} - -/** - * aa_remove_profiles - remove profile(s) from the system - * @fqname: name of the profile or namespace to remove (NOT NULL) - * @size: size of the name - * - * Remove a profile or sub namespace from the current namespace, so that - * they can not be found anymore and mark them as replaced by unconfined - * - * NOTE: removing confinement does not restore rlimits to preconfinemnet values - * - * Returns: size of data consume else error code if fails - */ -ssize_t aa_remove_profiles(char *fqname, size_t size) -{ - struct aa_namespace *root, *ns = NULL; - struct aa_profile *profile = NULL; - const char *name = fqname, *info = NULL; - ssize_t error = 0; - - if (*fqname == 0) { - info = "no profile specified"; - error = -ENOENT; - goto fail; - } - - root = aa_current_profile()->ns; - - if (fqname[0] == ':') { - char *ns_name; - name = aa_split_fqname(fqname, &ns_name); - if (ns_name) { - /* released below */ - ns = aa_find_namespace(root, ns_name); - if (!ns) { - info = "namespace does not exist"; - error = -ENOENT; - goto fail; - } - } - } else - /* released below */ - ns = aa_get_namespace(root); - - if (!name) { - /* remove namespace - can only happen if fqname[0] == ':' */ - write_lock(&ns->parent->lock); - __remove_namespace(ns); - write_unlock(&ns->parent->lock); - } else { - /* remove profile */ - write_lock(&ns->lock); - profile = aa_get_profile(__lookup_profile(&ns->base, name)); - if (!profile) { - error = -ENOENT; - info = "profile does not exist"; - goto fail_ns_lock; - } - name = profile->base.hname; - __remove_profile(profile); - write_unlock(&ns->lock); - } - - /* don't fail removal if audit fails */ - (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error); - aa_put_namespace(ns); - aa_put_profile(profile); - return size; - -fail_ns_lock: - write_unlock(&ns->lock); - aa_put_namespace(ns); - -fail: - (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error); - return error; -} diff --git a/ANDROID_3.4.5/security/apparmor/policy_unpack.c b/ANDROID_3.4.5/security/apparmor/policy_unpack.c deleted file mode 100644 index deab7c7e..00000000 --- a/ANDROID_3.4.5/security/apparmor/policy_unpack.c +++ /dev/null @@ -1,730 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor functions for unpacking policy loaded from - * userspace. - * - * 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. - * - * AppArmor uses a serialized binary format for loading policy. To find - * policy format documentation look in Documentation/security/apparmor.txt - * All policy is validated before it is used. - */ - -#include <asm/unaligned.h> -#include <linux/ctype.h> -#include <linux/errno.h> - -#include "include/apparmor.h" -#include "include/audit.h" -#include "include/context.h" -#include "include/match.h" -#include "include/policy.h" -#include "include/policy_unpack.h" -#include "include/sid.h" - -/* - * The AppArmor interface treats data as a type byte followed by the - * actual data. The interface has the notion of a a named entry - * which has a name (AA_NAME typecode followed by name string) followed by - * the entries typecode and data. Named types allow for optional - * elements and extensions to be added and tested for without breaking - * backwards compatibility. - */ - -enum aa_code { - AA_U8, - AA_U16, - AA_U32, - AA_U64, - AA_NAME, /* same as string except it is items name */ - AA_STRING, - AA_BLOB, - AA_STRUCT, - AA_STRUCTEND, - AA_LIST, - AA_LISTEND, - AA_ARRAY, - AA_ARRAYEND, -}; - -/* - * aa_ext is the read of the buffer containing the serialized profile. The - * data is copied into a kernel buffer in apparmorfs and then handed off to - * the unpack routines. - */ -struct aa_ext { - void *start; - void *end; - void *pos; /* pointer to current position in the buffer */ - u32 version; -}; - -/* audit callback for unpack fields */ -static void audit_cb(struct audit_buffer *ab, void *va) -{ - struct common_audit_data *sa = va; - if (sa->aad->iface.target) { - struct aa_profile *name = sa->aad->iface.target; - audit_log_format(ab, " name="); - audit_log_untrustedstring(ab, name->base.hname); - } - if (sa->aad->iface.pos) - audit_log_format(ab, " offset=%ld", sa->aad->iface.pos); -} - -/** - * audit_iface - do audit message for policy unpacking/load/replace/remove - * @new: profile if it has been allocated (MAYBE NULL) - * @name: name of the profile being manipulated (MAYBE NULL) - * @info: any extra info about the failure (MAYBE NULL) - * @e: buffer position info - * @error: error code - * - * Returns: %0 or error - */ -static int audit_iface(struct aa_profile *new, const char *name, - const char *info, struct aa_ext *e, int error) -{ - struct aa_profile *profile = __aa_current_profile(); - struct common_audit_data sa; - struct apparmor_audit_data aad = {0,}; - COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad = &aad; - if (e) - aad.iface.pos = e->pos - e->start; - aad.iface.target = new; - aad.name = name; - aad.info = info; - aad.error = error; - - return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa, - audit_cb); -} - -/* test if read will be in packed data bounds */ -static bool inbounds(struct aa_ext *e, size_t size) -{ - return (size <= e->end - e->pos); -} - -/** - * aa_u16_chunck - test and do bounds checking for a u16 size based chunk - * @e: serialized data read head (NOT NULL) - * @chunk: start address for chunk of data (NOT NULL) - * - * Returns: the size of chunk found with the read head at the end of the chunk. - */ -static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk) -{ - size_t size = 0; - - if (!inbounds(e, sizeof(u16))) - return 0; - size = le16_to_cpu(get_unaligned((u16 *) e->pos)); - e->pos += sizeof(u16); - if (!inbounds(e, size)) - return 0; - *chunk = e->pos; - e->pos += size; - return size; -} - -/* unpack control byte */ -static bool unpack_X(struct aa_ext *e, enum aa_code code) -{ - if (!inbounds(e, 1)) - return 0; - if (*(u8 *) e->pos != code) - return 0; - e->pos++; - return 1; -} - -/** - * unpack_nameX - check is the next element is of type X with a name of @name - * @e: serialized data extent information (NOT NULL) - * @code: type code - * @name: name to match to the serialized element. (MAYBE NULL) - * - * check that the next serialized data element is of type X and has a tag - * name @name. If @name is specified then there must be a matching - * name element in the stream. If @name is NULL any name element will be - * skipped and only the typecode will be tested. - * - * Returns 1 on success (both type code and name tests match) and the read - * head is advanced past the headers - * - * Returns: 0 if either match fails, the read head does not move - */ -static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name) -{ - /* - * May need to reset pos if name or type doesn't match - */ - void *pos = e->pos; - /* - * Check for presence of a tagname, and if present name size - * AA_NAME tag value is a u16. - */ - if (unpack_X(e, AA_NAME)) { - char *tag = NULL; - size_t size = unpack_u16_chunk(e, &tag); - /* if a name is specified it must match. otherwise skip tag */ - if (name && (!size || strcmp(name, tag))) - goto fail; - } else if (name) { - /* if a name is specified and there is no name tag fail */ - goto fail; - } - - /* now check if type code matches */ - if (unpack_X(e, code)) - return 1; - -fail: - e->pos = pos; - return 0; -} - -static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) -{ - if (unpack_nameX(e, AA_U32, name)) { - if (!inbounds(e, sizeof(u32))) - return 0; - if (data) - *data = le32_to_cpu(get_unaligned((u32 *) e->pos)); - e->pos += sizeof(u32); - return 1; - } - return 0; -} - -static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name) -{ - if (unpack_nameX(e, AA_U64, name)) { - if (!inbounds(e, sizeof(u64))) - return 0; - if (data) - *data = le64_to_cpu(get_unaligned((u64 *) e->pos)); - e->pos += sizeof(u64); - return 1; - } - return 0; -} - -static size_t unpack_array(struct aa_ext *e, const char *name) -{ - if (unpack_nameX(e, AA_ARRAY, name)) { - int size; - if (!inbounds(e, sizeof(u16))) - return 0; - size = (int)le16_to_cpu(get_unaligned((u16 *) e->pos)); - e->pos += sizeof(u16); - return size; - } - return 0; -} - -static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name) -{ - if (unpack_nameX(e, AA_BLOB, name)) { - u32 size; - if (!inbounds(e, sizeof(u32))) - return 0; - size = le32_to_cpu(get_unaligned((u32 *) e->pos)); - e->pos += sizeof(u32); - if (inbounds(e, (size_t) size)) { - *blob = e->pos; - e->pos += size; - return size; - } - } - return 0; -} - -static int unpack_str(struct aa_ext *e, const char **string, const char *name) -{ - char *src_str; - size_t size = 0; - void *pos = e->pos; - *string = NULL; - if (unpack_nameX(e, AA_STRING, name)) { - size = unpack_u16_chunk(e, &src_str); - if (size) { - /* strings are null terminated, length is size - 1 */ - if (src_str[size - 1] != 0) - goto fail; - *string = src_str; - } - } - return size; - -fail: - e->pos = pos; - return 0; -} - -static int unpack_strdup(struct aa_ext *e, char **string, const char *name) -{ - const char *tmp; - void *pos = e->pos; - int res = unpack_str(e, &tmp, name); - *string = NULL; - - if (!res) - return 0; - - *string = kmemdup(tmp, res, GFP_KERNEL); - if (!*string) { - e->pos = pos; - return 0; - } - - return res; -} - -/** - * verify_accept - verify the accept tables of a dfa - * @dfa: dfa to verify accept tables of (NOT NULL) - * @flags: flags governing dfa - * - * Returns: 1 if valid accept tables else 0 if error - */ -static bool verify_accept(struct aa_dfa *dfa, int flags) -{ - int i; - - /* verify accept permissions */ - for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) { - int mode = ACCEPT_TABLE(dfa)[i]; - - if (mode & ~DFA_VALID_PERM_MASK) - return 0; - - if (ACCEPT_TABLE2(dfa)[i] & ~DFA_VALID_PERM2_MASK) - return 0; - } - return 1; -} - -/** - * unpack_dfa - unpack a file rule dfa - * @e: serialized data extent information (NOT NULL) - * - * returns dfa or ERR_PTR or NULL if no dfa - */ -static struct aa_dfa *unpack_dfa(struct aa_ext *e) -{ - char *blob = NULL; - size_t size; - struct aa_dfa *dfa = NULL; - - size = unpack_blob(e, &blob, "aadfa"); - if (size) { - /* - * The dfa is aligned with in the blob to 8 bytes - * from the beginning of the stream. - */ - size_t sz = blob - (char *)e->start; - size_t pad = ALIGN(sz, 8) - sz; - int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) | - TO_ACCEPT2_FLAG(YYTD_DATA32); - - - if (aa_g_paranoid_load) - flags |= DFA_FLAG_VERIFY_STATES; - - dfa = aa_dfa_unpack(blob + pad, size - pad, flags); - - if (IS_ERR(dfa)) - return dfa; - - if (!verify_accept(dfa, flags)) - goto fail; - } - - return dfa; - -fail: - aa_put_dfa(dfa); - return ERR_PTR(-EPROTO); -} - -/** - * unpack_trans_table - unpack a profile transition table - * @e: serialized data extent information (NOT NULL) - * @profile: profile to add the accept table to (NOT NULL) - * - * Returns: 1 if table successfully unpacked - */ -static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile) -{ - void *pos = e->pos; - - /* exec table is optional */ - if (unpack_nameX(e, AA_STRUCT, "xtable")) { - int i, size; - - size = unpack_array(e, NULL); - /* currently 4 exec bits and entries 0-3 are reserved iupcx */ - if (size > 16 - 4) - goto fail; - profile->file.trans.table = kzalloc(sizeof(char *) * size, - GFP_KERNEL); - if (!profile->file.trans.table) - goto fail; - - profile->file.trans.size = size; - for (i = 0; i < size; i++) { - char *str; - int c, j, size2 = unpack_strdup(e, &str, NULL); - /* unpack_strdup verifies that the last character is - * null termination byte. - */ - if (!size2) - goto fail; - profile->file.trans.table[i] = str; - /* verify that name doesn't start with space */ - if (isspace(*str)) - goto fail; - - /* count internal # of internal \0 */ - for (c = j = 0; j < size2 - 2; j++) { - if (!str[j]) - c++; - } - if (*str == ':') { - /* beginning with : requires an embedded \0, - * verify that exactly 1 internal \0 exists - * trailing \0 already verified by unpack_strdup - */ - if (c != 1) - goto fail; - /* first character after : must be valid */ - if (!str[1]) - goto fail; - } else if (c) - /* fail - all other cases with embedded \0 */ - goto fail; - } - if (!unpack_nameX(e, AA_ARRAYEND, NULL)) - goto fail; - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) - goto fail; - } - return 1; - -fail: - aa_free_domain_entries(&profile->file.trans); - e->pos = pos; - return 0; -} - -static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) -{ - void *pos = e->pos; - - /* rlimits are optional */ - if (unpack_nameX(e, AA_STRUCT, "rlimits")) { - int i, size; - u32 tmp = 0; - if (!unpack_u32(e, &tmp, NULL)) - goto fail; - profile->rlimits.mask = tmp; - - size = unpack_array(e, NULL); - if (size > RLIM_NLIMITS) - goto fail; - for (i = 0; i < size; i++) { - u64 tmp2 = 0; - int a = aa_map_resource(i); - if (!unpack_u64(e, &tmp2, NULL)) - goto fail; - profile->rlimits.limits[a].rlim_max = tmp2; - } - if (!unpack_nameX(e, AA_ARRAYEND, NULL)) - goto fail; - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) - goto fail; - } - return 1; - -fail: - e->pos = pos; - return 0; -} - -/** - * unpack_profile - unpack a serialized profile - * @e: serialized data extent information (NOT NULL) - * - * NOTE: unpack profile sets audit struct if there is a failure - */ -static struct aa_profile *unpack_profile(struct aa_ext *e) -{ - struct aa_profile *profile = NULL; - const char *name = NULL; - int i, error = -EPROTO; - kernel_cap_t tmpcap; - u32 tmp; - - /* check that we have the right struct being passed */ - if (!unpack_nameX(e, AA_STRUCT, "profile")) - goto fail; - if (!unpack_str(e, &name, NULL)) - goto fail; - - profile = aa_alloc_profile(name); - if (!profile) - return ERR_PTR(-ENOMEM); - - /* profile renaming is optional */ - (void) unpack_str(e, &profile->rename, "rename"); - - /* xmatch is optional and may be NULL */ - profile->xmatch = unpack_dfa(e); - if (IS_ERR(profile->xmatch)) { - error = PTR_ERR(profile->xmatch); - profile->xmatch = NULL; - goto fail; - } - /* xmatch_len is not optional if xmatch is set */ - if (profile->xmatch) { - if (!unpack_u32(e, &tmp, NULL)) - goto fail; - profile->xmatch_len = tmp; - } - - /* per profile debug flags (complain, audit) */ - if (!unpack_nameX(e, AA_STRUCT, "flags")) - goto fail; - if (!unpack_u32(e, &tmp, NULL)) - goto fail; - if (tmp) - profile->flags |= PFLAG_HAT; - if (!unpack_u32(e, &tmp, NULL)) - goto fail; - if (tmp) - profile->mode = APPARMOR_COMPLAIN; - if (!unpack_u32(e, &tmp, NULL)) - goto fail; - if (tmp) - profile->audit = AUDIT_ALL; - - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) - goto fail; - - /* path_flags is optional */ - if (unpack_u32(e, &profile->path_flags, "path_flags")) - profile->path_flags |= profile->flags & PFLAG_MEDIATE_DELETED; - else - /* set a default value if path_flags field is not present */ - profile->path_flags = PFLAG_MEDIATE_DELETED; - - if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL)) - goto fail; - if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL)) - goto fail; - if (!unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL)) - goto fail; - if (!unpack_u32(e, &tmpcap.cap[0], NULL)) - goto fail; - - if (unpack_nameX(e, AA_STRUCT, "caps64")) { - /* optional upper half of 64 bit caps */ - if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL)) - goto fail; - if (!unpack_u32(e, &(profile->caps.audit.cap[1]), NULL)) - goto fail; - if (!unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL)) - goto fail; - if (!unpack_u32(e, &(tmpcap.cap[1]), NULL)) - goto fail; - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) - goto fail; - } - - if (unpack_nameX(e, AA_STRUCT, "capsx")) { - /* optional extended caps mediation mask */ - if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL)) - goto fail; - if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL)) - goto fail; - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) - goto fail; - } - - if (!unpack_rlimits(e, profile)) - goto fail; - - if (unpack_nameX(e, AA_STRUCT, "policydb")) { - /* generic policy dfa - optional and may be NULL */ - profile->policy.dfa = unpack_dfa(e); - if (IS_ERR(profile->policy.dfa)) { - error = PTR_ERR(profile->policy.dfa); - profile->policy.dfa = NULL; - goto fail; - } - if (!unpack_u32(e, &profile->policy.start[0], "start")) - /* default start state */ - profile->policy.start[0] = DFA_START; - /* setup class index */ - for (i = AA_CLASS_FILE; i <= AA_CLASS_LAST; i++) { - profile->policy.start[i] = - aa_dfa_next(profile->policy.dfa, - profile->policy.start[0], - i); - } - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) - goto fail; - } - - /* get file rules */ - profile->file.dfa = unpack_dfa(e); - if (IS_ERR(profile->file.dfa)) { - error = PTR_ERR(profile->file.dfa); - profile->file.dfa = NULL; - goto fail; - } - - if (!unpack_u32(e, &profile->file.start, "dfa_start")) - /* default start state */ - profile->file.start = DFA_START; - - if (!unpack_trans_table(e, profile)) - goto fail; - - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) - goto fail; - - return profile; - -fail: - if (profile) - name = NULL; - else if (!name) - name = "unknown"; - audit_iface(profile, name, "failed to unpack profile", e, error); - aa_put_profile(profile); - - return ERR_PTR(error); -} - -/** - * verify_head - unpack serialized stream header - * @e: serialized data read head (NOT NULL) - * @ns: Returns - namespace if one is specified else NULL (NOT NULL) - * - * Returns: error or 0 if header is good - */ -static int verify_header(struct aa_ext *e, const char **ns) -{ - int error = -EPROTONOSUPPORT; - /* get the interface version */ - if (!unpack_u32(e, &e->version, "version")) { - audit_iface(NULL, NULL, "invalid profile format", e, error); - return error; - } - - /* check that the interface version is currently supported */ - if (e->version != 5) { - audit_iface(NULL, NULL, "unsupported interface version", e, - error); - return error; - } - - /* read the namespace if present */ - if (!unpack_str(e, ns, "namespace")) - *ns = NULL; - - return 0; -} - -static bool verify_xindex(int xindex, int table_size) -{ - int index, xtype; - xtype = xindex & AA_X_TYPE_MASK; - index = xindex & AA_X_INDEX_MASK; - if (xtype == AA_X_TABLE && index > table_size) - return 0; - return 1; -} - -/* verify dfa xindexes are in range of transition tables */ -static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size) -{ - int i; - for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) { - if (!verify_xindex(dfa_user_xindex(dfa, i), table_size)) - return 0; - if (!verify_xindex(dfa_other_xindex(dfa, i), table_size)) - return 0; - } - return 1; -} - -/** - * verify_profile - Do post unpack analysis to verify profile consistency - * @profile: profile to verify (NOT NULL) - * - * Returns: 0 if passes verification else error - */ -static int verify_profile(struct aa_profile *profile) -{ - if (aa_g_paranoid_load) { - if (profile->file.dfa && - !verify_dfa_xindex(profile->file.dfa, - profile->file.trans.size)) { - audit_iface(profile, NULL, "Invalid named transition", - NULL, -EPROTO); - return -EPROTO; - } - } - - return 0; -} - -/** - * aa_unpack - unpack packed binary profile data loaded from user space - * @udata: user data copied to kmem (NOT NULL) - * @size: the size of the user data - * @ns: Returns namespace profile is in if specified else NULL (NOT NULL) - * - * Unpack user data and return refcounted allocated profile or ERR_PTR - * - * Returns: profile else error pointer if fails to unpack - */ -struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns) -{ - struct aa_profile *profile = NULL; - int error; - struct aa_ext e = { - .start = udata, - .end = udata + size, - .pos = udata, - }; - - error = verify_header(&e, ns); - if (error) - return ERR_PTR(error); - - profile = unpack_profile(&e); - if (IS_ERR(profile)) - return profile; - - error = verify_profile(profile); - if (error) { - aa_put_profile(profile); - profile = ERR_PTR(error); - } - - /* return refcount */ - return profile; -} diff --git a/ANDROID_3.4.5/security/apparmor/procattr.c b/ANDROID_3.4.5/security/apparmor/procattr.c deleted file mode 100644 index 1b41c542..00000000 --- a/ANDROID_3.4.5/security/apparmor/procattr.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor /proc/<pid>/attr/ 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 "include/apparmor.h" -#include "include/context.h" -#include "include/policy.h" -#include "include/domain.h" -#include "include/procattr.h" - - -/** - * aa_getprocattr - Return the profile information for @profile - * @profile: the profile to print profile info about (NOT NULL) - * @string: Returns - string containing the profile info (NOT NULL) - * - * Returns: length of @string on success else error on failure - * - * Requires: profile != NULL - * - * Creates a string containing the namespace_name://profile_name for - * @profile. - * - * Returns: size of string placed in @string else error code on failure - */ -int aa_getprocattr(struct aa_profile *profile, char **string) -{ - char *str; - int len = 0, mode_len = 0, ns_len = 0, name_len; - const char *mode_str = profile_mode_names[profile->mode]; - const char *ns_name = NULL; - struct aa_namespace *ns = profile->ns; - struct aa_namespace *current_ns = __aa_current_profile()->ns; - char *s; - - if (!aa_ns_visible(current_ns, ns)) - return -EACCES; - - ns_name = aa_ns_name(current_ns, ns); - ns_len = strlen(ns_name); - - /* if the visible ns_name is > 0 increase size for : :// seperator */ - if (ns_len) - ns_len += 4; - - /* unconfined profiles don't have a mode string appended */ - if (!unconfined(profile)) - mode_len = strlen(mode_str) + 3; /* + 3 for _() */ - - name_len = strlen(profile->base.hname); - len = mode_len + ns_len + name_len + 1; /* + 1 for \n */ - s = str = kmalloc(len + 1, GFP_KERNEL); /* + 1 \0 */ - if (!str) - return -ENOMEM; - - if (ns_len) { - /* skip over prefix current_ns->base.hname and separating // */ - sprintf(s, ":%s://", ns_name); - s += ns_len; - } - if (unconfined(profile)) - /* mode string not being appended */ - sprintf(s, "%s\n", profile->base.hname); - else - sprintf(s, "%s (%s)\n", profile->base.hname, mode_str); - *string = str; - - /* NOTE: len does not include \0 of string, not saved as part of file */ - return len; -} - -/** - * split_token_from_name - separate a string of form <token>^<name> - * @op: operation being checked - * @args: string to parse (NOT NULL) - * @token: stores returned parsed token value (NOT NULL) - * - * Returns: start position of name after token else NULL on failure - */ -static char *split_token_from_name(int op, char *args, u64 * token) -{ - char *name; - - *token = simple_strtoull(args, &name, 16); - if ((name == args) || *name != '^') { - AA_ERROR("%s: Invalid input '%s'", op_table[op], args); - return ERR_PTR(-EINVAL); - } - - name++; /* skip ^ */ - if (!*name) - name = NULL; - return name; -} - -/** - * aa_setprocattr_chagnehat - handle procattr interface to change_hat - * @args: args received from writing to /proc/<pid>/attr/current (NOT NULL) - * @size: size of the args - * @test: true if this is a test of change_hat permissions - * - * Returns: %0 or error code if change_hat fails - */ -int aa_setprocattr_changehat(char *args, size_t size, int test) -{ - char *hat; - u64 token; - const char *hats[16]; /* current hard limit on # of names */ - int count = 0; - - hat = split_token_from_name(OP_CHANGE_HAT, args, &token); - if (IS_ERR(hat)) - return PTR_ERR(hat); - - if (!hat && !token) { - AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic"); - return -EINVAL; - } - - if (hat) { - /* set up hat name vector, args guaranteed null terminated - * at args[size] by setprocattr. - * - * If there are multiple hat names in the buffer each is - * separated by a \0. Ie. userspace writes them pre tokenized - */ - char *end = args + size; - for (count = 0; (hat < end) && count < 16; ++count) { - char *next = hat + strlen(hat) + 1; - hats[count] = hat; - hat = next; - } - } - - AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n", - __func__, token, hat ? hat : NULL); - - return aa_change_hat(hats, count, token, test); -} - -/** - * aa_setprocattr_changeprofile - handle procattr interface to changeprofile - * @fqname: args received from writting to /proc/<pid>/attr/current (NOT NULL) - * @onexec: true if change_profile should be delayed until exec - * @test: true if this is a test of change_profile permissions - * - * Returns: %0 or error code if change_profile fails - */ -int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test) -{ - char *name, *ns_name; - - name = aa_split_fqname(fqname, &ns_name); - return aa_change_profile(ns_name, name, onexec, test); -} - -int aa_setprocattr_permipc(char *fqname) -{ - /* TODO: add ipc permission querying */ - return -ENOTSUPP; -} diff --git a/ANDROID_3.4.5/security/apparmor/resource.c b/ANDROID_3.4.5/security/apparmor/resource.c deleted file mode 100644 index 2fe8613e..00000000 --- a/ANDROID_3.4.5/security/apparmor/resource.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor resource mediation and attachment - * - * 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/audit.h> - -#include "include/audit.h" -#include "include/resource.h" -#include "include/policy.h" - -/* - * Table of rlimit names: we generate it from resource.h. - */ -#include "rlim_names.h" - -struct aa_fs_entry aa_fs_entry_rlimit[] = { - AA_FS_FILE_STRING("mask", AA_FS_RLIMIT_MASK), - { } -}; - -/* audit callback for resource specific fields */ -static void audit_cb(struct audit_buffer *ab, void *va) -{ - struct common_audit_data *sa = va; - - audit_log_format(ab, " rlimit=%s value=%lu", - rlim_names[sa->aad->rlim.rlim], sa->aad->rlim.max); -} - -/** - * audit_resource - audit setting resource limit - * @profile: profile being enforced (NOT NULL) - * @resoure: rlimit being auditing - * @value: value being set - * @error: error value - * - * Returns: 0 or sa->error else other error code on failure - */ -static int audit_resource(struct aa_profile *profile, unsigned int resource, - unsigned long value, int error) -{ - struct common_audit_data sa; - struct apparmor_audit_data aad = {0,}; - - COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad = &aad; - aad.op = OP_SETRLIMIT, - aad.rlim.rlim = resource; - aad.rlim.max = value; - aad.error = error; - return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa, - audit_cb); -} - -/** - * aa_map_resouce - map compiled policy resource to internal # - * @resource: flattened policy resource number - * - * Returns: resource # for the current architecture. - * - * rlimit resource can vary based on architecture, map the compiled policy - * resource # to the internal representation for the architecture. - */ -int aa_map_resource(int resource) -{ - return rlim_map[resource]; -} - -/** - * aa_task_setrlimit - test permission to set an rlimit - * @profile - profile confining the task (NOT NULL) - * @task - task the resource is being set on - * @resource - the resource being set - * @new_rlim - the new resource limit (NOT NULL) - * - * Control raising the processes hard limit. - * - * Returns: 0 or error code if setting resource failed - */ -int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, - unsigned int resource, struct rlimit *new_rlim) -{ - int error = 0; - - /* TODO: extend resource control to handle other (non current) - * processes. AppArmor rules currently have the implicit assumption - * that the task is setting the resource of the current process - */ - if ((task != current->group_leader) || - (profile->rlimits.mask & (1 << resource) && - new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)) - error = -EACCES; - - return audit_resource(profile, resource, new_rlim->rlim_max, error); -} - -/** - * __aa_transition_rlimits - apply new profile rlimits - * @old: old profile on task (NOT NULL) - * @new: new profile with rlimits to apply (NOT NULL) - */ -void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new) -{ - unsigned int mask = 0; - struct rlimit *rlim, *initrlim; - int i; - - /* for any rlimits the profile controlled reset the soft limit - * to the less of the tasks hard limit and the init tasks soft limit - */ - if (old->rlimits.mask) { - for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) { - if (old->rlimits.mask & mask) { - rlim = current->signal->rlim + i; - initrlim = init_task.signal->rlim + i; - rlim->rlim_cur = min(rlim->rlim_max, - initrlim->rlim_cur); - } - } - } - - /* set any new hard limits as dictated by the new profile */ - if (!new->rlimits.mask) - return; - for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) { - if (!(new->rlimits.mask & mask)) - continue; - - rlim = current->signal->rlim + i; - rlim->rlim_max = min(rlim->rlim_max, - new->rlimits.limits[i].rlim_max); - /* soft limit should not exceed hard limit */ - rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max); - } -} diff --git a/ANDROID_3.4.5/security/apparmor/sid.c b/ANDROID_3.4.5/security/apparmor/sid.c deleted file mode 100644 index f0b34f76..00000000 --- a/ANDROID_3.4.5/security/apparmor/sid.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor security identifier (sid) manipulation fns - * - * 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. - * - * - * AppArmor allocates a unique sid for every profile loaded. If a profile - * is replaced it receives the sid of the profile it is replacing. - * - * The sid value of 0 is invalid. - */ - -#include <linux/spinlock.h> -#include <linux/errno.h> -#include <linux/err.h> - -#include "include/sid.h" - -/* global counter from which sids are allocated */ -static u32 global_sid; -static DEFINE_SPINLOCK(sid_lock); - -/* TODO FIXME: add sid to profile mapping, and sid recycling */ - -/** - * aa_alloc_sid - allocate a new sid for a profile - */ -u32 aa_alloc_sid(void) -{ - u32 sid; - - /* - * TODO FIXME: sid recycling - part of profile mapping table - */ - spin_lock(&sid_lock); - sid = (++global_sid); - spin_unlock(&sid_lock); - return sid; -} - -/** - * aa_free_sid - free a sid - * @sid: sid to free - */ -void aa_free_sid(u32 sid) -{ - ; /* NOP ATM */ -} |