diff options
Diffstat (limited to 'ANDROID_3.4.5/security/integrity/ima')
-rw-r--r-- | ANDROID_3.4.5/security/integrity/ima/Kconfig | 56 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/integrity/ima/Makefile | 9 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/integrity/ima/ima.h | 146 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/integrity/ima/ima_api.c | 185 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/integrity/ima/ima_audit.c | 66 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/integrity/ima/ima_crypto.c | 143 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/integrity/ima/ima_fs.c | 386 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/integrity/ima/ima_init.c | 97 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/integrity/ima/ima_main.c | 241 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/integrity/ima/ima_policy.c | 493 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/integrity/ima/ima_queue.c | 149 |
11 files changed, 0 insertions, 1971 deletions
diff --git a/ANDROID_3.4.5/security/integrity/ima/Kconfig b/ANDROID_3.4.5/security/integrity/ima/Kconfig deleted file mode 100644 index 35664fe6..00000000 --- a/ANDROID_3.4.5/security/integrity/ima/Kconfig +++ /dev/null @@ -1,56 +0,0 @@ -# IBM Integrity Measurement Architecture -# -config IMA - bool "Integrity Measurement Architecture(IMA)" - depends on SECURITY - select INTEGRITY - select SECURITYFS - select CRYPTO - select CRYPTO_HMAC - select CRYPTO_MD5 - select CRYPTO_SHA1 - select TCG_TPM if HAS_IOMEM && !UML - select TCG_TIS if TCG_TPM && X86 - help - The Trusted Computing Group(TCG) runtime Integrity - Measurement Architecture(IMA) maintains a list of hash - values of executables and other sensitive system files, - as they are read or executed. If an attacker manages - to change the contents of an important system file - being measured, we can tell. - - If your system has a TPM chip, then IMA also maintains - an aggregate integrity value over this list inside the - TPM hardware, so that the TPM can prove to a third party - whether or not critical system files have been modified. - Read <http://www.usenix.org/events/sec04/tech/sailer.html> - to learn more about IMA. - If unsure, say N. - -config IMA_MEASURE_PCR_IDX - int - depends on IMA - range 8 14 - default 10 - help - IMA_MEASURE_PCR_IDX determines the TPM PCR register index - that IMA uses to maintain the integrity aggregate of the - measurement list. If unsure, use the default 10. - -config IMA_AUDIT - bool - depends on IMA - default y - help - This option adds a kernel parameter 'ima_audit', which - allows informational auditing messages to be enabled - at boot. If this option is selected, informational integrity - auditing messages can be enabled with 'ima_audit=1' on - the kernel command line. - -config IMA_LSM_RULES - bool - depends on IMA && AUDIT && (SECURITY_SELINUX || SECURITY_SMACK) - default y - help - Disabling this option will disregard LSM based policy rules. diff --git a/ANDROID_3.4.5/security/integrity/ima/Makefile b/ANDROID_3.4.5/security/integrity/ima/Makefile deleted file mode 100644 index 5690c021..00000000 --- a/ANDROID_3.4.5/security/integrity/ima/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for building Trusted Computing Group's(TCG) runtime Integrity -# Measurement Architecture(IMA). -# - -obj-$(CONFIG_IMA) += ima.o - -ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ - ima_policy.o ima_audit.o diff --git a/ANDROID_3.4.5/security/integrity/ima/ima.h b/ANDROID_3.4.5/security/integrity/ima/ima.h deleted file mode 100644 index 3ccf7aca..00000000 --- a/ANDROID_3.4.5/security/integrity/ima/ima.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2005,2006,2007,2008 IBM Corporation - * - * Authors: - * Reiner Sailer <sailer@watson.ibm.com> - * Mimi Zohar <zohar@us.ibm.com> - * - * 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. - * - * File: ima.h - * internal Integrity Measurement Architecture (IMA) definitions - */ - -#ifndef __LINUX_IMA_H -#define __LINUX_IMA_H - -#include <linux/types.h> -#include <linux/crypto.h> -#include <linux/security.h> -#include <linux/hash.h> -#include <linux/tpm.h> -#include <linux/audit.h> - -#include "../integrity.h" - -enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_ASCII }; -enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; - -/* digest size for IMA, fits SHA1 or MD5 */ -#define IMA_DIGEST_SIZE SHA1_DIGEST_SIZE -#define IMA_EVENT_NAME_LEN_MAX 255 - -#define IMA_HASH_BITS 9 -#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) - -/* set during initialization */ -extern int ima_initialized; -extern int ima_used_chip; -extern char *ima_hash; - -/* IMA inode template definition */ -struct ima_template_data { - u8 digest[IMA_DIGEST_SIZE]; /* sha1/md5 measurement hash */ - char file_name[IMA_EVENT_NAME_LEN_MAX + 1]; /* name + \0 */ -}; - -struct ima_template_entry { - u8 digest[IMA_DIGEST_SIZE]; /* sha1 or md5 measurement hash */ - const char *template_name; - int template_len; - struct ima_template_data template; -}; - -struct ima_queue_entry { - struct hlist_node hnext; /* place in hash collision list */ - struct list_head later; /* place in ima_measurements list */ - struct ima_template_entry *entry; -}; -extern struct list_head ima_measurements; /* list of all measurements */ - -/* declarations */ -void integrity_audit_msg(int audit_msgno, struct inode *inode, - const unsigned char *fname, const char *op, - const char *cause, int result, int info); - -/* Internal IMA function definitions */ -int ima_init(void); -void ima_cleanup(void); -int ima_fs_init(void); -void ima_fs_cleanup(void); -int ima_inode_alloc(struct inode *inode); -int ima_add_template_entry(struct ima_template_entry *entry, int violation, - const char *op, struct inode *inode); -int ima_calc_hash(struct file *file, char *digest); -int ima_calc_template_hash(int template_len, void *template, char *digest); -int ima_calc_boot_aggregate(char *digest); -void ima_add_violation(struct inode *inode, const unsigned char *filename, - const char *op, const char *cause); - -/* - * used to protect h_table and sha_table - */ -extern spinlock_t ima_queue_lock; - -struct ima_h_table { - atomic_long_t len; /* number of stored measurements in the list */ - atomic_long_t violations; - struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE]; -}; -extern struct ima_h_table ima_htable; - -static inline unsigned long ima_hash_key(u8 *digest) -{ - return hash_long(*digest, IMA_HASH_BITS); -} - -/* LIM API function definitions */ -int ima_must_measure(struct inode *inode, int mask, int function); -int ima_collect_measurement(struct integrity_iint_cache *iint, - struct file *file); -void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, - const unsigned char *filename); -int ima_store_template(struct ima_template_entry *entry, int violation, - struct inode *inode); -void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show); - -/* rbtree tree calls to lookup, insert, delete - * integrity data associated with an inode. - */ -struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); -struct integrity_iint_cache *integrity_iint_find(struct inode *inode); - -/* IMA policy related functions */ -enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK }; - -int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); -void ima_init_policy(void); -void ima_update_policy(void); -ssize_t ima_parse_add_rule(char *); -void ima_delete_rules(void); - -/* LSM based policy rules require audit */ -#ifdef CONFIG_IMA_LSM_RULES - -#define security_filter_rule_init security_audit_rule_init -#define security_filter_rule_match security_audit_rule_match - -#else - -static inline int security_filter_rule_init(u32 field, u32 op, char *rulestr, - void **lsmrule) -{ - return -EINVAL; -} - -static inline int security_filter_rule_match(u32 secid, u32 field, u32 op, - void *lsmrule, - struct audit_context *actx) -{ - return -EINVAL; -} -#endif /* CONFIG_IMA_LSM_RULES */ -#endif diff --git a/ANDROID_3.4.5/security/integrity/ima/ima_api.c b/ANDROID_3.4.5/security/integrity/ima/ima_api.c deleted file mode 100644 index 88a2788b..00000000 --- a/ANDROID_3.4.5/security/integrity/ima/ima_api.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2008 IBM Corporation - * - * Author: Mimi Zohar <zohar@us.ibm.com> - * - * 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. - * - * File: ima_api.c - * Implements must_measure, collect_measurement, store_measurement, - * and store_template. - */ -#include <linux/module.h> -#include <linux/slab.h> - -#include "ima.h" -static const char *IMA_TEMPLATE_NAME = "ima"; - -/* - * ima_store_template - store ima template measurements - * - * Calculate the hash of a template entry, add the template entry - * to an ordered list of measurement entries maintained inside the kernel, - * and also update the aggregate integrity value (maintained inside the - * configured TPM PCR) over the hashes of the current list of measurement - * entries. - * - * Applications retrieve the current kernel-held measurement list through - * the securityfs entries in /sys/kernel/security/ima. The signed aggregate - * TPM PCR (called quote) can be retrieved using a TPM user space library - * and is used to validate the measurement list. - * - * Returns 0 on success, error code otherwise - */ -int ima_store_template(struct ima_template_entry *entry, - int violation, struct inode *inode) -{ - const char *op = "add_template_measure"; - const char *audit_cause = "hashing_error"; - int result; - - memset(entry->digest, 0, sizeof(entry->digest)); - entry->template_name = IMA_TEMPLATE_NAME; - entry->template_len = sizeof(entry->template); - - if (!violation) { - result = ima_calc_template_hash(entry->template_len, - &entry->template, - entry->digest); - if (result < 0) { - integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, - entry->template_name, op, - audit_cause, result, 0); - return result; - } - } - result = ima_add_template_entry(entry, violation, op, inode); - return result; -} - -/* - * ima_add_violation - add violation to measurement list. - * - * Violations are flagged in the measurement list with zero hash values. - * By extending the PCR with 0xFF's instead of with zeroes, the PCR - * value is invalidated. - */ -void ima_add_violation(struct inode *inode, const unsigned char *filename, - const char *op, const char *cause) -{ - struct ima_template_entry *entry; - int violation = 1; - int result; - - /* can overflow, only indicator */ - atomic_long_inc(&ima_htable.violations); - - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) { - result = -ENOMEM; - goto err_out; - } - memset(&entry->template, 0, sizeof(entry->template)); - strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX); - result = ima_store_template(entry, violation, inode); - if (result < 0) - kfree(entry); -err_out: - integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, - op, cause, result, 0); -} - -/** - * ima_must_measure - measure decision based on policy. - * @inode: pointer to inode to measure - * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) - * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP) - * - * The policy is defined in terms of keypairs: - * subj=, obj=, type=, func=, mask=, fsmagic= - * subj,obj, and type: are LSM specific. - * func: FILE_CHECK | BPRM_CHECK | FILE_MMAP - * mask: contains the permission mask - * fsmagic: hex value - * - * Return 0 to measure. For matching a DONT_MEASURE policy, no policy, - * or other error, return an error code. -*/ -int ima_must_measure(struct inode *inode, int mask, int function) -{ - int must_measure; - - must_measure = ima_match_policy(inode, function, mask); - return must_measure ? 0 : -EACCES; -} - -/* - * ima_collect_measurement - collect file measurement - * - * Calculate the file hash, if it doesn't already exist, - * storing the measurement and i_version in the iint. - * - * Must be called with iint->mutex held. - * - * Return 0 on success, error code otherwise - */ -int ima_collect_measurement(struct integrity_iint_cache *iint, - struct file *file) -{ - int result = -EEXIST; - - if (!(iint->flags & IMA_MEASURED)) { - u64 i_version = file->f_dentry->d_inode->i_version; - - memset(iint->digest, 0, IMA_DIGEST_SIZE); - result = ima_calc_hash(file, iint->digest); - if (!result) - iint->version = i_version; - } - return result; -} - -/* - * ima_store_measurement - store file measurement - * - * Create an "ima" template and then store the template by calling - * ima_store_template. - * - * We only get here if the inode has not already been measured, - * but the measurement could already exist: - * - multiple copies of the same file on either the same or - * different filesystems. - * - the inode was previously flushed as well as the iint info, - * containing the hashing info. - * - * Must be called with iint->mutex held. - */ -void ima_store_measurement(struct integrity_iint_cache *iint, - struct file *file, const unsigned char *filename) -{ - const char *op = "add_template_measure"; - const char *audit_cause = "ENOMEM"; - int result = -ENOMEM; - struct inode *inode = file->f_dentry->d_inode; - struct ima_template_entry *entry; - int violation = 0; - - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) { - integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, - op, audit_cause, result, 0); - return; - } - memset(&entry->template, 0, sizeof(entry->template)); - memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE); - strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX); - - result = ima_store_template(entry, violation, inode); - if (!result || result == -EEXIST) - iint->flags |= IMA_MEASURED; - if (result < 0) - kfree(entry); -} diff --git a/ANDROID_3.4.5/security/integrity/ima/ima_audit.c b/ANDROID_3.4.5/security/integrity/ima/ima_audit.c deleted file mode 100644 index 21e96bf1..00000000 --- a/ANDROID_3.4.5/security/integrity/ima/ima_audit.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2008 IBM Corporation - * Author: Mimi Zohar <zohar@us.ibm.com> - * - * 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. - * - * File: integrity_audit.c - * Audit calls for the integrity subsystem - */ - -#include <linux/fs.h> -#include <linux/gfp.h> -#include <linux/audit.h> -#include "ima.h" - -static int ima_audit; - -#ifdef CONFIG_IMA_AUDIT - -/* ima_audit_setup - enable informational auditing messages */ -static int __init ima_audit_setup(char *str) -{ - unsigned long audit; - - if (!strict_strtoul(str, 0, &audit)) - ima_audit = audit ? 1 : 0; - return 1; -} -__setup("ima_audit=", ima_audit_setup); -#endif - -void integrity_audit_msg(int audit_msgno, struct inode *inode, - const unsigned char *fname, const char *op, - const char *cause, int result, int audit_info) -{ - struct audit_buffer *ab; - - if (!ima_audit && audit_info == 1) /* Skip informational messages */ - return; - - ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno); - audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u", - current->pid, current_cred()->uid, - audit_get_loginuid(current), - audit_get_sessionid(current)); - audit_log_task_context(ab); - audit_log_format(ab, " op="); - audit_log_string(ab, op); - audit_log_format(ab, " cause="); - audit_log_string(ab, cause); - audit_log_format(ab, " comm="); - audit_log_untrustedstring(ab, current->comm); - if (fname) { - audit_log_format(ab, " name="); - audit_log_untrustedstring(ab, fname); - } - if (inode) { - audit_log_format(ab, " dev="); - audit_log_untrustedstring(ab, inode->i_sb->s_id); - audit_log_format(ab, " ino=%lu", inode->i_ino); - } - audit_log_format(ab, " res=%d", !result); - audit_log_end(ab); -} diff --git a/ANDROID_3.4.5/security/integrity/ima/ima_crypto.c b/ANDROID_3.4.5/security/integrity/ima/ima_crypto.c deleted file mode 100644 index 9b3ade74..00000000 --- a/ANDROID_3.4.5/security/integrity/ima/ima_crypto.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2005,2006,2007,2008 IBM Corporation - * - * Authors: - * Mimi Zohar <zohar@us.ibm.com> - * Kylene Hall <kjhall@us.ibm.com> - * - * 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. - * - * File: ima_crypto.c - * Calculates md5/sha1 file hash, template hash, boot-aggreate hash - */ - -#include <linux/kernel.h> -#include <linux/file.h> -#include <linux/crypto.h> -#include <linux/scatterlist.h> -#include <linux/err.h> -#include <linux/slab.h> -#include "ima.h" - -static int init_desc(struct hash_desc *desc) -{ - int rc; - - desc->tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(desc->tfm)) { - pr_info("IMA: failed to load %s transform: %ld\n", - ima_hash, PTR_ERR(desc->tfm)); - rc = PTR_ERR(desc->tfm); - return rc; - } - desc->flags = 0; - rc = crypto_hash_init(desc); - if (rc) - crypto_free_hash(desc->tfm); - return rc; -} - -/* - * Calculate the MD5/SHA1 file digest - */ -int ima_calc_hash(struct file *file, char *digest) -{ - struct hash_desc desc; - struct scatterlist sg[1]; - loff_t i_size, offset = 0; - char *rbuf; - int rc; - - rc = init_desc(&desc); - if (rc != 0) - return rc; - - rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); - if (!rbuf) { - rc = -ENOMEM; - goto out; - } - i_size = i_size_read(file->f_dentry->d_inode); - while (offset < i_size) { - int rbuf_len; - - rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE); - if (rbuf_len < 0) { - rc = rbuf_len; - break; - } - if (rbuf_len == 0) - break; - offset += rbuf_len; - sg_init_one(sg, rbuf, rbuf_len); - - rc = crypto_hash_update(&desc, sg, rbuf_len); - if (rc) - break; - } - kfree(rbuf); - if (!rc) - rc = crypto_hash_final(&desc, digest); -out: - crypto_free_hash(desc.tfm); - return rc; -} - -/* - * Calculate the hash of a given template - */ -int ima_calc_template_hash(int template_len, void *template, char *digest) -{ - struct hash_desc desc; - struct scatterlist sg[1]; - int rc; - - rc = init_desc(&desc); - if (rc != 0) - return rc; - - sg_init_one(sg, template, template_len); - rc = crypto_hash_update(&desc, sg, template_len); - if (!rc) - rc = crypto_hash_final(&desc, digest); - crypto_free_hash(desc.tfm); - return rc; -} - -static void __init ima_pcrread(int idx, u8 *pcr) -{ - if (!ima_used_chip) - return; - - if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0) - pr_err("IMA: Error Communicating to TPM chip\n"); -} - -/* - * Calculate the boot aggregate hash - */ -int __init ima_calc_boot_aggregate(char *digest) -{ - struct hash_desc desc; - struct scatterlist sg; - u8 pcr_i[IMA_DIGEST_SIZE]; - int rc, i; - - rc = init_desc(&desc); - if (rc != 0) - return rc; - - /* cumulative sha1 over tpm registers 0-7 */ - for (i = TPM_PCR0; i < TPM_PCR8; i++) { - ima_pcrread(i, pcr_i); - /* now accumulate with current aggregate */ - sg_init_one(&sg, pcr_i, IMA_DIGEST_SIZE); - rc = crypto_hash_update(&desc, &sg, IMA_DIGEST_SIZE); - } - if (!rc) - crypto_hash_final(&desc, digest); - crypto_free_hash(desc.tfm); - return rc; -} diff --git a/ANDROID_3.4.5/security/integrity/ima/ima_fs.c b/ANDROID_3.4.5/security/integrity/ima/ima_fs.c deleted file mode 100644 index e1aa2b48..00000000 --- a/ANDROID_3.4.5/security/integrity/ima/ima_fs.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2005,2006,2007,2008 IBM Corporation - * - * Authors: - * Kylene Hall <kjhall@us.ibm.com> - * Reiner Sailer <sailer@us.ibm.com> - * Mimi Zohar <zohar@us.ibm.com> - * - * 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. - * - * File: ima_fs.c - * implemenents security file system for reporting - * current measurement list and IMA statistics - */ -#include <linux/fcntl.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/seq_file.h> -#include <linux/rculist.h> -#include <linux/rcupdate.h> -#include <linux/parser.h> - -#include "ima.h" - -static int valid_policy = 1; -#define TMPBUFLEN 12 -static ssize_t ima_show_htable_value(char __user *buf, size_t count, - loff_t *ppos, atomic_long_t *val) -{ - char tmpbuf[TMPBUFLEN]; - ssize_t len; - - len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val)); - return simple_read_from_buffer(buf, count, ppos, tmpbuf, len); -} - -static ssize_t ima_show_htable_violations(struct file *filp, - char __user *buf, - size_t count, loff_t *ppos) -{ - return ima_show_htable_value(buf, count, ppos, &ima_htable.violations); -} - -static const struct file_operations ima_htable_violations_ops = { - .read = ima_show_htable_violations, - .llseek = generic_file_llseek, -}; - -static ssize_t ima_show_measurements_count(struct file *filp, - char __user *buf, - size_t count, loff_t *ppos) -{ - return ima_show_htable_value(buf, count, ppos, &ima_htable.len); - -} - -static const struct file_operations ima_measurements_count_ops = { - .read = ima_show_measurements_count, - .llseek = generic_file_llseek, -}; - -/* returns pointer to hlist_node */ -static void *ima_measurements_start(struct seq_file *m, loff_t *pos) -{ - loff_t l = *pos; - struct ima_queue_entry *qe; - - /* we need a lock since pos could point beyond last element */ - rcu_read_lock(); - list_for_each_entry_rcu(qe, &ima_measurements, later) { - if (!l--) { - rcu_read_unlock(); - return qe; - } - } - rcu_read_unlock(); - return NULL; -} - -static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos) -{ - struct ima_queue_entry *qe = v; - - /* lock protects when reading beyond last element - * against concurrent list-extension - */ - rcu_read_lock(); - qe = list_entry_rcu(qe->later.next, - struct ima_queue_entry, later); - rcu_read_unlock(); - (*pos)++; - - return (&qe->later == &ima_measurements) ? NULL : qe; -} - -static void ima_measurements_stop(struct seq_file *m, void *v) -{ -} - -static void ima_putc(struct seq_file *m, void *data, int datalen) -{ - while (datalen--) - seq_putc(m, *(char *)data++); -} - -/* print format: - * 32bit-le=pcr# - * char[20]=template digest - * 32bit-le=template name size - * char[n]=template name - * eventdata[n]=template specific data - */ -static int ima_measurements_show(struct seq_file *m, void *v) -{ - /* the list never shrinks, so we don't need a lock here */ - struct ima_queue_entry *qe = v; - struct ima_template_entry *e; - int namelen; - u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX; - - /* get entry */ - e = qe->entry; - if (e == NULL) - return -1; - - /* - * 1st: PCRIndex - * PCR used is always the same (config option) in - * little-endian format - */ - ima_putc(m, &pcr, sizeof pcr); - - /* 2nd: template digest */ - ima_putc(m, e->digest, IMA_DIGEST_SIZE); - - /* 3rd: template name size */ - namelen = strlen(e->template_name); - ima_putc(m, &namelen, sizeof namelen); - - /* 4th: template name */ - ima_putc(m, (void *)e->template_name, namelen); - - /* 5th: template specific data */ - ima_template_show(m, (struct ima_template_data *)&e->template, - IMA_SHOW_BINARY); - return 0; -} - -static const struct seq_operations ima_measurments_seqops = { - .start = ima_measurements_start, - .next = ima_measurements_next, - .stop = ima_measurements_stop, - .show = ima_measurements_show -}; - -static int ima_measurements_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &ima_measurments_seqops); -} - -static const struct file_operations ima_measurements_ops = { - .open = ima_measurements_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static void ima_print_digest(struct seq_file *m, u8 *digest) -{ - int i; - - for (i = 0; i < IMA_DIGEST_SIZE; i++) - seq_printf(m, "%02x", *(digest + i)); -} - -void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show) -{ - struct ima_template_data *entry = e; - int namelen; - - switch (show) { - case IMA_SHOW_ASCII: - ima_print_digest(m, entry->digest); - seq_printf(m, " %s\n", entry->file_name); - break; - case IMA_SHOW_BINARY: - ima_putc(m, entry->digest, IMA_DIGEST_SIZE); - - namelen = strlen(entry->file_name); - ima_putc(m, &namelen, sizeof namelen); - ima_putc(m, entry->file_name, namelen); - default: - break; - } -} - -/* print in ascii */ -static int ima_ascii_measurements_show(struct seq_file *m, void *v) -{ - /* the list never shrinks, so we don't need a lock here */ - struct ima_queue_entry *qe = v; - struct ima_template_entry *e; - - /* get entry */ - e = qe->entry; - if (e == NULL) - return -1; - - /* 1st: PCR used (config option) */ - seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX); - - /* 2nd: SHA1 template hash */ - ima_print_digest(m, e->digest); - - /* 3th: template name */ - seq_printf(m, " %s ", e->template_name); - - /* 4th: template specific data */ - ima_template_show(m, (struct ima_template_data *)&e->template, - IMA_SHOW_ASCII); - return 0; -} - -static const struct seq_operations ima_ascii_measurements_seqops = { - .start = ima_measurements_start, - .next = ima_measurements_next, - .stop = ima_measurements_stop, - .show = ima_ascii_measurements_show -}; - -static int ima_ascii_measurements_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &ima_ascii_measurements_seqops); -} - -static const struct file_operations ima_ascii_measurements_ops = { - .open = ima_ascii_measurements_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static ssize_t ima_write_policy(struct file *file, const char __user *buf, - size_t datalen, loff_t *ppos) -{ - char *data = NULL; - ssize_t result; - - if (datalen >= PAGE_SIZE) - datalen = PAGE_SIZE - 1; - - /* No partial writes. */ - result = -EINVAL; - if (*ppos != 0) - goto out; - - result = -ENOMEM; - data = kmalloc(datalen + 1, GFP_KERNEL); - if (!data) - goto out; - - *(data + datalen) = '\0'; - - result = -EFAULT; - if (copy_from_user(data, buf, datalen)) - goto out; - - result = ima_parse_add_rule(data); -out: - if (result < 0) - valid_policy = 0; - kfree(data); - return result; -} - -static struct dentry *ima_dir; -static struct dentry *binary_runtime_measurements; -static struct dentry *ascii_runtime_measurements; -static struct dentry *runtime_measurements_count; -static struct dentry *violations; -static struct dentry *ima_policy; - -static atomic_t policy_opencount = ATOMIC_INIT(1); -/* - * ima_open_policy: sequentialize access to the policy file - */ -static int ima_open_policy(struct inode * inode, struct file * filp) -{ - /* No point in being allowed to open it if you aren't going to write */ - if (!(filp->f_flags & O_WRONLY)) - return -EACCES; - if (atomic_dec_and_test(&policy_opencount)) - return 0; - return -EBUSY; -} - -/* - * ima_release_policy - start using the new measure policy rules. - * - * Initially, ima_measure points to the default policy rules, now - * point to the new policy rules, and remove the securityfs policy file, - * assuming a valid policy. - */ -static int ima_release_policy(struct inode *inode, struct file *file) -{ - if (!valid_policy) { - ima_delete_rules(); - valid_policy = 1; - atomic_set(&policy_opencount, 1); - return 0; - } - ima_update_policy(); - securityfs_remove(ima_policy); - ima_policy = NULL; - return 0; -} - -static const struct file_operations ima_measure_policy_ops = { - .open = ima_open_policy, - .write = ima_write_policy, - .release = ima_release_policy, - .llseek = generic_file_llseek, -}; - -int __init ima_fs_init(void) -{ - ima_dir = securityfs_create_dir("ima", NULL); - if (IS_ERR(ima_dir)) - return -1; - - binary_runtime_measurements = - securityfs_create_file("binary_runtime_measurements", - S_IRUSR | S_IRGRP, ima_dir, NULL, - &ima_measurements_ops); - if (IS_ERR(binary_runtime_measurements)) - goto out; - - ascii_runtime_measurements = - securityfs_create_file("ascii_runtime_measurements", - S_IRUSR | S_IRGRP, ima_dir, NULL, - &ima_ascii_measurements_ops); - if (IS_ERR(ascii_runtime_measurements)) - goto out; - - runtime_measurements_count = - securityfs_create_file("runtime_measurements_count", - S_IRUSR | S_IRGRP, ima_dir, NULL, - &ima_measurements_count_ops); - if (IS_ERR(runtime_measurements_count)) - goto out; - - violations = - securityfs_create_file("violations", S_IRUSR | S_IRGRP, - ima_dir, NULL, &ima_htable_violations_ops); - if (IS_ERR(violations)) - goto out; - - ima_policy = securityfs_create_file("policy", - S_IWUSR, - ima_dir, NULL, - &ima_measure_policy_ops); - if (IS_ERR(ima_policy)) - goto out; - - return 0; -out: - securityfs_remove(runtime_measurements_count); - securityfs_remove(ascii_runtime_measurements); - securityfs_remove(binary_runtime_measurements); - securityfs_remove(ima_dir); - securityfs_remove(ima_policy); - return -1; -} - -void __exit ima_fs_cleanup(void) -{ - securityfs_remove(violations); - securityfs_remove(runtime_measurements_count); - securityfs_remove(ascii_runtime_measurements); - securityfs_remove(binary_runtime_measurements); - securityfs_remove(ima_dir); - securityfs_remove(ima_policy); -} diff --git a/ANDROID_3.4.5/security/integrity/ima/ima_init.c b/ANDROID_3.4.5/security/integrity/ima/ima_init.c deleted file mode 100644 index 17f1f060..00000000 --- a/ANDROID_3.4.5/security/integrity/ima/ima_init.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2005,2006,2007,2008 IBM Corporation - * - * Authors: - * Reiner Sailer <sailer@watson.ibm.com> - * Leendert van Doorn <leendert@watson.ibm.com> - * Mimi Zohar <zohar@us.ibm.com> - * - * 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. - * - * File: ima_init.c - * initialization and cleanup functions - */ -#include <linux/module.h> -#include <linux/scatterlist.h> -#include <linux/slab.h> -#include <linux/err.h> -#include "ima.h" - -/* name for boot aggregate entry */ -static const char *boot_aggregate_name = "boot_aggregate"; -int ima_used_chip; - -/* Add the boot aggregate to the IMA measurement list and extend - * the PCR register. - * - * Calculate the boot aggregate, a SHA1 over tpm registers 0-7, - * assuming a TPM chip exists, and zeroes if the TPM chip does not - * exist. Add the boot aggregate measurement to the measurement - * list and extend the PCR register. - * - * If a tpm chip does not exist, indicate the core root of trust is - * not hardware based by invalidating the aggregate PCR value. - * (The aggregate PCR value is invalidated by adding one value to - * the measurement list and extending the aggregate PCR value with - * a different value.) Violations add a zero entry to the measurement - * list and extend the aggregate PCR value with ff...ff's. - */ -static void __init ima_add_boot_aggregate(void) -{ - struct ima_template_entry *entry; - const char *op = "add_boot_aggregate"; - const char *audit_cause = "ENOMEM"; - int result = -ENOMEM; - int violation = 1; - - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) - goto err_out; - - memset(&entry->template, 0, sizeof(entry->template)); - strncpy(entry->template.file_name, boot_aggregate_name, - IMA_EVENT_NAME_LEN_MAX); - if (ima_used_chip) { - violation = 0; - result = ima_calc_boot_aggregate(entry->template.digest); - if (result < 0) { - audit_cause = "hashing_error"; - kfree(entry); - goto err_out; - } - } - result = ima_store_template(entry, violation, NULL); - if (result < 0) - kfree(entry); - return; -err_out: - integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op, - audit_cause, result, 0); -} - -int __init ima_init(void) -{ - u8 pcr_i[IMA_DIGEST_SIZE]; - int rc; - - ima_used_chip = 0; - rc = tpm_pcr_read(TPM_ANY_NUM, 0, pcr_i); - if (rc == 0) - ima_used_chip = 1; - - if (!ima_used_chip) - pr_info("IMA: No TPM chip found, activating TPM-bypass!\n"); - - ima_add_boot_aggregate(); /* boot aggregate must be first entry */ - ima_init_policy(); - - return ima_fs_init(); -} - -void __exit ima_cleanup(void) -{ - ima_fs_cleanup(); -} diff --git a/ANDROID_3.4.5/security/integrity/ima/ima_main.c b/ANDROID_3.4.5/security/integrity/ima/ima_main.c deleted file mode 100644 index 1eff5cb0..00000000 --- a/ANDROID_3.4.5/security/integrity/ima/ima_main.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (C) 2005,2006,2007,2008 IBM Corporation - * - * Authors: - * Reiner Sailer <sailer@watson.ibm.com> - * Serge Hallyn <serue@us.ibm.com> - * Kylene Hall <kylene@us.ibm.com> - * Mimi Zohar <zohar@us.ibm.com> - * - * 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. - * - * File: ima_main.c - * implements the IMA hooks: ima_bprm_check, ima_file_mmap, - * and ima_file_check. - */ -#include <linux/module.h> -#include <linux/file.h> -#include <linux/binfmts.h> -#include <linux/mount.h> -#include <linux/mman.h> -#include <linux/slab.h> -#include <linux/ima.h> - -#include "ima.h" - -int ima_initialized; - -char *ima_hash = "sha1"; -static int __init hash_setup(char *str) -{ - if (strncmp(str, "md5", 3) == 0) - ima_hash = "md5"; - return 1; -} -__setup("ima_hash=", hash_setup); - -/* - * ima_rdwr_violation_check - * - * Only invalidate the PCR for measured files: - * - Opening a file for write when already open for read, - * results in a time of measure, time of use (ToMToU) error. - * - Opening a file for read when already open for write, - * could result in a file measurement error. - * - */ -static void ima_rdwr_violation_check(struct file *file) -{ - struct dentry *dentry = file->f_path.dentry; - struct inode *inode = dentry->d_inode; - fmode_t mode = file->f_mode; - int rc; - bool send_tomtou = false, send_writers = false; - - if (!S_ISREG(inode->i_mode) || !ima_initialized) - return; - - mutex_lock(&inode->i_mutex); /* file metadata: permissions, xattr */ - - if (mode & FMODE_WRITE) { - if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) - send_tomtou = true; - goto out; - } - - rc = ima_must_measure(inode, MAY_READ, FILE_CHECK); - if (rc < 0) - goto out; - - if (atomic_read(&inode->i_writecount) > 0) - send_writers = true; -out: - mutex_unlock(&inode->i_mutex); - - if (send_tomtou) - ima_add_violation(inode, dentry->d_name.name, "invalid_pcr", - "ToMToU"); - if (send_writers) - ima_add_violation(inode, dentry->d_name.name, "invalid_pcr", - "open_writers"); -} - -static void ima_check_last_writer(struct integrity_iint_cache *iint, - struct inode *inode, - struct file *file) -{ - fmode_t mode = file->f_mode; - - mutex_lock(&iint->mutex); - if (mode & FMODE_WRITE && - atomic_read(&inode->i_writecount) == 1 && - iint->version != inode->i_version) - iint->flags &= ~IMA_MEASURED; - mutex_unlock(&iint->mutex); -} - -/** - * ima_file_free - called on __fput() - * @file: pointer to file structure being freed - * - * Flag files that changed, based on i_version - */ -void ima_file_free(struct file *file) -{ - struct inode *inode = file->f_dentry->d_inode; - struct integrity_iint_cache *iint; - - if (!iint_initialized || !S_ISREG(inode->i_mode)) - return; - - iint = integrity_iint_find(inode); - if (!iint) - return; - - ima_check_last_writer(iint, inode, file); -} - -static int process_measurement(struct file *file, const unsigned char *filename, - int mask, int function) -{ - struct inode *inode = file->f_dentry->d_inode; - struct integrity_iint_cache *iint; - int rc = 0; - - if (!ima_initialized || !S_ISREG(inode->i_mode)) - return 0; - - rc = ima_must_measure(inode, mask, function); - if (rc != 0) - return rc; -retry: - iint = integrity_iint_find(inode); - if (!iint) { - rc = integrity_inode_alloc(inode); - if (!rc || rc == -EEXIST) - goto retry; - return rc; - } - - mutex_lock(&iint->mutex); - - rc = iint->flags & IMA_MEASURED ? 1 : 0; - if (rc != 0) - goto out; - - rc = ima_collect_measurement(iint, file); - if (!rc) - ima_store_measurement(iint, file, filename); -out: - mutex_unlock(&iint->mutex); - return rc; -} - -/** - * ima_file_mmap - based on policy, collect/store measurement. - * @file: pointer to the file to be measured (May be NULL) - * @prot: contains the protection that will be applied by the kernel. - * - * Measure files being mmapped executable based on the ima_must_measure() - * policy decision. - * - * Return 0 on success, an error code on failure. - * (Based on the results of appraise_measurement().) - */ -int ima_file_mmap(struct file *file, unsigned long prot) -{ - int rc; - - if (!file) - return 0; - if (prot & PROT_EXEC) - rc = process_measurement(file, file->f_dentry->d_name.name, - MAY_EXEC, FILE_MMAP); - return 0; -} - -/** - * ima_bprm_check - based on policy, collect/store measurement. - * @bprm: contains the linux_binprm structure - * - * The OS protects against an executable file, already open for write, - * from being executed in deny_write_access() and an executable file, - * already open for execute, from being modified in get_write_access(). - * So we can be certain that what we verify and measure here is actually - * what is being executed. - * - * Return 0 on success, an error code on failure. - * (Based on the results of appraise_measurement().) - */ -int ima_bprm_check(struct linux_binprm *bprm) -{ - int rc; - - rc = process_measurement(bprm->file, bprm->filename, - MAY_EXEC, BPRM_CHECK); - return 0; -} - -/** - * ima_path_check - based on policy, collect/store measurement. - * @file: pointer to the file to be measured - * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE - * - * Measure files based on the ima_must_measure() policy decision. - * - * Always return 0 and audit dentry_open failures. - * (Return code will be based upon measurement appraisal.) - */ -int ima_file_check(struct file *file, int mask) -{ - int rc; - - ima_rdwr_violation_check(file); - rc = process_measurement(file, file->f_dentry->d_name.name, - mask & (MAY_READ | MAY_WRITE | MAY_EXEC), - FILE_CHECK); - return 0; -} -EXPORT_SYMBOL_GPL(ima_file_check); - -static int __init init_ima(void) -{ - int error; - - error = ima_init(); - ima_initialized = 1; - return error; -} - -static void __exit cleanup_ima(void) -{ - ima_cleanup(); -} - -late_initcall(init_ima); /* Start IMA after the TPM is available */ - -MODULE_DESCRIPTION("Integrity Measurement Architecture"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/security/integrity/ima/ima_policy.c b/ANDROID_3.4.5/security/integrity/ima/ima_policy.c deleted file mode 100644 index d8edff20..00000000 --- a/ANDROID_3.4.5/security/integrity/ima/ima_policy.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright (C) 2008 IBM Corporation - * Author: Mimi Zohar <zohar@us.ibm.com> - * - * 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. - * - * ima_policy.c - * - initialize default measure policy rules - * - */ -#include <linux/module.h> -#include <linux/list.h> -#include <linux/security.h> -#include <linux/magic.h> -#include <linux/parser.h> -#include <linux/slab.h> - -#include "ima.h" - -/* flags definitions */ -#define IMA_FUNC 0x0001 -#define IMA_MASK 0x0002 -#define IMA_FSMAGIC 0x0004 -#define IMA_UID 0x0008 - -enum ima_action { UNKNOWN = -1, DONT_MEASURE = 0, MEASURE }; - -#define MAX_LSM_RULES 6 -enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, - LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE -}; - -struct ima_measure_rule_entry { - struct list_head list; - enum ima_action action; - unsigned int flags; - enum ima_hooks func; - int mask; - unsigned long fsmagic; - uid_t uid; - struct { - void *rule; /* LSM file metadata specific */ - int type; /* audit type */ - } lsm[MAX_LSM_RULES]; -}; - -/* - * Without LSM specific knowledge, the default policy can only be - * written in terms of .action, .func, .mask, .fsmagic, and .uid - */ - -/* - * The minimum rule set to allow for full TCB coverage. Measures all files - * opened or mmap for exec and everything read by root. Dangerous because - * normal users can easily run the machine out of memory simply building - * and running executables. - */ -static struct ima_measure_rule_entry default_rules[] = { - {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC}, - {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC}, - {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC}, - {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC}, - {.action = DONT_MEASURE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC}, - {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC}, - {.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC}, - {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC, - .flags = IMA_FUNC | IMA_MASK}, - {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, - .flags = IMA_FUNC | IMA_MASK}, - {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = 0, - .flags = IMA_FUNC | IMA_MASK | IMA_UID}, -}; - -static LIST_HEAD(measure_default_rules); -static LIST_HEAD(measure_policy_rules); -static struct list_head *ima_measure; - -static DEFINE_MUTEX(ima_measure_mutex); - -static bool ima_use_tcb __initdata; -static int __init default_policy_setup(char *str) -{ - ima_use_tcb = 1; - return 1; -} -__setup("ima_tcb", default_policy_setup); - -/** - * ima_match_rules - determine whether an inode matches the measure rule. - * @rule: a pointer to a rule - * @inode: a pointer to an inode - * @func: LIM hook identifier - * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) - * - * Returns true on rule match, false on failure. - */ -static bool ima_match_rules(struct ima_measure_rule_entry *rule, - struct inode *inode, enum ima_hooks func, int mask) -{ - struct task_struct *tsk = current; - const struct cred *cred = current_cred(); - int i; - - if ((rule->flags & IMA_FUNC) && rule->func != func) - return false; - if ((rule->flags & IMA_MASK) && rule->mask != mask) - return false; - if ((rule->flags & IMA_FSMAGIC) - && rule->fsmagic != inode->i_sb->s_magic) - return false; - if ((rule->flags & IMA_UID) && rule->uid != cred->uid) - return false; - for (i = 0; i < MAX_LSM_RULES; i++) { - int rc = 0; - u32 osid, sid; - - if (!rule->lsm[i].rule) - continue; - - switch (i) { - case LSM_OBJ_USER: - case LSM_OBJ_ROLE: - case LSM_OBJ_TYPE: - security_inode_getsecid(inode, &osid); - rc = security_filter_rule_match(osid, - rule->lsm[i].type, - Audit_equal, - rule->lsm[i].rule, - NULL); - break; - case LSM_SUBJ_USER: - case LSM_SUBJ_ROLE: - case LSM_SUBJ_TYPE: - security_task_getsecid(tsk, &sid); - rc = security_filter_rule_match(sid, - rule->lsm[i].type, - Audit_equal, - rule->lsm[i].rule, - NULL); - default: - break; - } - if (!rc) - return false; - } - return true; -} - -/** - * ima_match_policy - decision based on LSM and other conditions - * @inode: pointer to an inode for which the policy decision is being made - * @func: IMA hook identifier - * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) - * - * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type) - * conditions. - * - * (There is no need for locking when walking the policy list, - * as elements in the list are never deleted, nor does the list - * change.) - */ -int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask) -{ - struct ima_measure_rule_entry *entry; - - list_for_each_entry(entry, ima_measure, list) { - bool rc; - - rc = ima_match_rules(entry, inode, func, mask); - if (rc) - return entry->action; - } - return 0; -} - -/** - * ima_init_policy - initialize the default measure rules. - * - * ima_measure points to either the measure_default_rules or the - * the new measure_policy_rules. - */ -void __init ima_init_policy(void) -{ - int i, entries; - - /* if !ima_use_tcb set entries = 0 so we load NO default rules */ - if (ima_use_tcb) - entries = ARRAY_SIZE(default_rules); - else - entries = 0; - - for (i = 0; i < entries; i++) - list_add_tail(&default_rules[i].list, &measure_default_rules); - ima_measure = &measure_default_rules; -} - -/** - * ima_update_policy - update default_rules with new measure rules - * - * Called on file .release to update the default rules with a complete new - * policy. Once updated, the policy is locked, no additional rules can be - * added to the policy. - */ -void ima_update_policy(void) -{ - const char *op = "policy_update"; - const char *cause = "already exists"; - int result = 1; - int audit_info = 0; - - if (ima_measure == &measure_default_rules) { - ima_measure = &measure_policy_rules; - cause = "complete"; - result = 0; - } - integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, - NULL, op, cause, result, audit_info); -} - -enum { - Opt_err = -1, - Opt_measure = 1, Opt_dont_measure, - Opt_obj_user, Opt_obj_role, Opt_obj_type, - Opt_subj_user, Opt_subj_role, Opt_subj_type, - Opt_func, Opt_mask, Opt_fsmagic, Opt_uid -}; - -static match_table_t policy_tokens = { - {Opt_measure, "measure"}, - {Opt_dont_measure, "dont_measure"}, - {Opt_obj_user, "obj_user=%s"}, - {Opt_obj_role, "obj_role=%s"}, - {Opt_obj_type, "obj_type=%s"}, - {Opt_subj_user, "subj_user=%s"}, - {Opt_subj_role, "subj_role=%s"}, - {Opt_subj_type, "subj_type=%s"}, - {Opt_func, "func=%s"}, - {Opt_mask, "mask=%s"}, - {Opt_fsmagic, "fsmagic=%s"}, - {Opt_uid, "uid=%s"}, - {Opt_err, NULL} -}; - -static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry, - char *args, int lsm_rule, int audit_type) -{ - int result; - - if (entry->lsm[lsm_rule].rule) - return -EINVAL; - - entry->lsm[lsm_rule].type = audit_type; - result = security_filter_rule_init(entry->lsm[lsm_rule].type, - Audit_equal, args, - &entry->lsm[lsm_rule].rule); - if (!entry->lsm[lsm_rule].rule) - return -EINVAL; - return result; -} - -static void ima_log_string(struct audit_buffer *ab, char *key, char *value) -{ - audit_log_format(ab, "%s=", key); - audit_log_untrustedstring(ab, value); - audit_log_format(ab, " "); -} - -static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) -{ - struct audit_buffer *ab; - char *p; - int result = 0; - - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE); - - entry->uid = -1; - entry->action = UNKNOWN; - while ((p = strsep(&rule, " \t")) != NULL) { - substring_t args[MAX_OPT_ARGS]; - int token; - unsigned long lnum; - - if (result < 0) - break; - if ((*p == '\0') || (*p == ' ') || (*p == '\t')) - continue; - token = match_token(p, policy_tokens, args); - switch (token) { - case Opt_measure: - ima_log_string(ab, "action", "measure"); - - if (entry->action != UNKNOWN) - result = -EINVAL; - - entry->action = MEASURE; - break; - case Opt_dont_measure: - ima_log_string(ab, "action", "dont_measure"); - - if (entry->action != UNKNOWN) - result = -EINVAL; - - entry->action = DONT_MEASURE; - break; - case Opt_func: - ima_log_string(ab, "func", args[0].from); - - if (entry->func) - result = -EINVAL; - - if (strcmp(args[0].from, "FILE_CHECK") == 0) - entry->func = FILE_CHECK; - /* PATH_CHECK is for backwards compat */ - else if (strcmp(args[0].from, "PATH_CHECK") == 0) - entry->func = FILE_CHECK; - else if (strcmp(args[0].from, "FILE_MMAP") == 0) - entry->func = FILE_MMAP; - else if (strcmp(args[0].from, "BPRM_CHECK") == 0) - entry->func = BPRM_CHECK; - else - result = -EINVAL; - if (!result) - entry->flags |= IMA_FUNC; - break; - case Opt_mask: - ima_log_string(ab, "mask", args[0].from); - - if (entry->mask) - result = -EINVAL; - - if ((strcmp(args[0].from, "MAY_EXEC")) == 0) - entry->mask = MAY_EXEC; - else if (strcmp(args[0].from, "MAY_WRITE") == 0) - entry->mask = MAY_WRITE; - else if (strcmp(args[0].from, "MAY_READ") == 0) - entry->mask = MAY_READ; - else if (strcmp(args[0].from, "MAY_APPEND") == 0) - entry->mask = MAY_APPEND; - else - result = -EINVAL; - if (!result) - entry->flags |= IMA_MASK; - break; - case Opt_fsmagic: - ima_log_string(ab, "fsmagic", args[0].from); - - if (entry->fsmagic) { - result = -EINVAL; - break; - } - - result = strict_strtoul(args[0].from, 16, - &entry->fsmagic); - if (!result) - entry->flags |= IMA_FSMAGIC; - break; - case Opt_uid: - ima_log_string(ab, "uid", args[0].from); - - if (entry->uid != -1) { - result = -EINVAL; - break; - } - - result = strict_strtoul(args[0].from, 10, &lnum); - if (!result) { - entry->uid = (uid_t) lnum; - if (entry->uid != lnum) - result = -EINVAL; - else - entry->flags |= IMA_UID; - } - break; - case Opt_obj_user: - ima_log_string(ab, "obj_user", args[0].from); - result = ima_lsm_rule_init(entry, args[0].from, - LSM_OBJ_USER, - AUDIT_OBJ_USER); - break; - case Opt_obj_role: - ima_log_string(ab, "obj_role", args[0].from); - result = ima_lsm_rule_init(entry, args[0].from, - LSM_OBJ_ROLE, - AUDIT_OBJ_ROLE); - break; - case Opt_obj_type: - ima_log_string(ab, "obj_type", args[0].from); - result = ima_lsm_rule_init(entry, args[0].from, - LSM_OBJ_TYPE, - AUDIT_OBJ_TYPE); - break; - case Opt_subj_user: - ima_log_string(ab, "subj_user", args[0].from); - result = ima_lsm_rule_init(entry, args[0].from, - LSM_SUBJ_USER, - AUDIT_SUBJ_USER); - break; - case Opt_subj_role: - ima_log_string(ab, "subj_role", args[0].from); - result = ima_lsm_rule_init(entry, args[0].from, - LSM_SUBJ_ROLE, - AUDIT_SUBJ_ROLE); - break; - case Opt_subj_type: - ima_log_string(ab, "subj_type", args[0].from); - result = ima_lsm_rule_init(entry, args[0].from, - LSM_SUBJ_TYPE, - AUDIT_SUBJ_TYPE); - break; - case Opt_err: - ima_log_string(ab, "UNKNOWN", p); - result = -EINVAL; - break; - } - } - if (!result && (entry->action == UNKNOWN)) - result = -EINVAL; - - audit_log_format(ab, "res=%d", !result); - audit_log_end(ab); - return result; -} - -/** - * ima_parse_add_rule - add a rule to measure_policy_rules - * @rule - ima measurement policy rule - * - * Uses a mutex to protect the policy list from multiple concurrent writers. - * Returns the length of the rule parsed, an error code on failure - */ -ssize_t ima_parse_add_rule(char *rule) -{ - const char *op = "update_policy"; - char *p; - struct ima_measure_rule_entry *entry; - ssize_t result, len; - int audit_info = 0; - - /* Prevent installed policy from changing */ - if (ima_measure != &measure_default_rules) { - integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, - NULL, op, "already exists", - -EACCES, audit_info); - return -EACCES; - } - - entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) { - integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, - NULL, op, "-ENOMEM", -ENOMEM, audit_info); - return -ENOMEM; - } - - INIT_LIST_HEAD(&entry->list); - - p = strsep(&rule, "\n"); - len = strlen(p) + 1; - - if (*p == '#') { - kfree(entry); - return len; - } - - result = ima_parse_rule(p, entry); - if (result) { - kfree(entry); - integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, - NULL, op, "invalid policy", result, - audit_info); - return result; - } - - mutex_lock(&ima_measure_mutex); - list_add_tail(&entry->list, &measure_policy_rules); - mutex_unlock(&ima_measure_mutex); - - return len; -} - -/* ima_delete_rules called to cleanup invalid policy */ -void ima_delete_rules(void) -{ - struct ima_measure_rule_entry *entry, *tmp; - - mutex_lock(&ima_measure_mutex); - list_for_each_entry_safe(entry, tmp, &measure_policy_rules, list) { - list_del(&entry->list); - kfree(entry); - } - mutex_unlock(&ima_measure_mutex); -} diff --git a/ANDROID_3.4.5/security/integrity/ima/ima_queue.c b/ANDROID_3.4.5/security/integrity/ima/ima_queue.c deleted file mode 100644 index 55a6271b..00000000 --- a/ANDROID_3.4.5/security/integrity/ima/ima_queue.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2005,2006,2007,2008 IBM Corporation - * - * Authors: - * Serge Hallyn <serue@us.ibm.com> - * Reiner Sailer <sailer@watson.ibm.com> - * Mimi Zohar <zohar@us.ibm.com> - * - * 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. - * - * File: ima_queue.c - * Implements queues that store template measurements and - * maintains aggregate over the stored measurements - * in the pre-configured TPM PCR (if available). - * The measurement list is append-only. No entry is - * ever removed or changed during the boot-cycle. - */ -#include <linux/module.h> -#include <linux/rculist.h> -#include <linux/slab.h> -#include "ima.h" - -#define AUDIT_CAUSE_LEN_MAX 32 - -LIST_HEAD(ima_measurements); /* list of all measurements */ - -/* key: inode (before secure-hashing a file) */ -struct ima_h_table ima_htable = { - .len = ATOMIC_LONG_INIT(0), - .violations = ATOMIC_LONG_INIT(0), - .queue[0 ... IMA_MEASURE_HTABLE_SIZE - 1] = HLIST_HEAD_INIT -}; - -/* mutex protects atomicity of extending measurement list - * and extending the TPM PCR aggregate. Since tpm_extend can take - * long (and the tpm driver uses a mutex), we can't use the spinlock. - */ -static DEFINE_MUTEX(ima_extend_list_mutex); - -/* lookup up the digest value in the hash table, and return the entry */ -static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value) -{ - struct ima_queue_entry *qe, *ret = NULL; - unsigned int key; - struct hlist_node *pos; - int rc; - - key = ima_hash_key(digest_value); - rcu_read_lock(); - hlist_for_each_entry_rcu(qe, pos, &ima_htable.queue[key], hnext) { - rc = memcmp(qe->entry->digest, digest_value, IMA_DIGEST_SIZE); - if (rc == 0) { - ret = qe; - break; - } - } - rcu_read_unlock(); - return ret; -} - -/* ima_add_template_entry helper function: - * - Add template entry to measurement list and hash table. - * - * (Called with ima_extend_list_mutex held.) - */ -static int ima_add_digest_entry(struct ima_template_entry *entry) -{ - struct ima_queue_entry *qe; - unsigned int key; - - qe = kmalloc(sizeof(*qe), GFP_KERNEL); - if (qe == NULL) { - pr_err("IMA: OUT OF MEMORY ERROR creating queue entry.\n"); - return -ENOMEM; - } - qe->entry = entry; - - INIT_LIST_HEAD(&qe->later); - list_add_tail_rcu(&qe->later, &ima_measurements); - - atomic_long_inc(&ima_htable.len); - key = ima_hash_key(entry->digest); - hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]); - return 0; -} - -static int ima_pcr_extend(const u8 *hash) -{ - int result = 0; - - if (!ima_used_chip) - return result; - - result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash); - if (result != 0) - pr_err("IMA: Error Communicating to TPM chip, result: %d\n", - result); - return result; -} - -/* Add template entry to the measurement list and hash table, - * and extend the pcr. - */ -int ima_add_template_entry(struct ima_template_entry *entry, int violation, - const char *op, struct inode *inode) -{ - u8 digest[IMA_DIGEST_SIZE]; - const char *audit_cause = "hash_added"; - char tpm_audit_cause[AUDIT_CAUSE_LEN_MAX]; - int audit_info = 1; - int result = 0, tpmresult = 0; - - mutex_lock(&ima_extend_list_mutex); - if (!violation) { - memcpy(digest, entry->digest, sizeof digest); - if (ima_lookup_digest_entry(digest)) { - audit_cause = "hash_exists"; - result = -EEXIST; - goto out; - } - } - - result = ima_add_digest_entry(entry); - if (result < 0) { - audit_cause = "ENOMEM"; - audit_info = 0; - goto out; - } - - if (violation) /* invalidate pcr */ - memset(digest, 0xff, sizeof digest); - - tpmresult = ima_pcr_extend(digest); - if (tpmresult != 0) { - snprintf(tpm_audit_cause, AUDIT_CAUSE_LEN_MAX, "TPM_error(%d)", - tpmresult); - audit_cause = tpm_audit_cause; - audit_info = 0; - } -out: - mutex_unlock(&ima_extend_list_mutex); - integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, - entry->template.file_name, - op, audit_cause, result, audit_info); - return result; -} |