diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-10-17 09:32:49 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-10-17 09:32:49 -0300 |
commit | 214e2ca2b82d335935a861c253fe94c61ad77aad (patch) | |
tree | eee42ff74d10470789d919b8499737ad0e919360 /security/integrity/ima/ima_api.c | |
parent | 1fdead8ad31d3aa833bc37739273fcde89ace93c (diff) | |
parent | ddffeb8c4d0331609ef2581d84de4d763607bd37 (diff) |
Merge tag 'v3.7-rc1' into staging/for_v3.8
Linux 3.7-rc1
* tag 'v3.7-rc1': (9579 commits)
Linux 3.7-rc1
x86, boot: Explicitly include autoconf.h for hostprogs
perf: Fix UAPI fallout
ARM: config: make sure that platforms are ordered by option string
ARM: config: sort select statements alphanumerically
UAPI: (Scripted) Disintegrate include/linux/byteorder
UAPI: (Scripted) Disintegrate include/linux
UAPI: Unexport linux/blk_types.h
UAPI: Unexport part of linux/ppp-comp.h
perf: Handle new rbtree implementation
procfs: don't need a PATH_MAX allocation to hold a string representation of an int
vfs: embed struct filename inside of names_cache allocation if possible
audit: make audit_inode take struct filename
vfs: make path_openat take a struct filename pointer
vfs: turn do_path_lookup into wrapper around struct filename variant
audit: allow audit code to satisfy getname requests from its names_list
vfs: define struct filename and have getname() return it
btrfs: Fix compilation with user namespace support enabled
userns: Fix posix_acl_file_xattr_userns gid conversion
userns: Properly print bluetooth socket uids
...
Diffstat (limited to 'security/integrity/ima/ima_api.c')
-rw-r--r-- | security/integrity/ima/ima_api.c | 86 |
1 files changed, 69 insertions, 17 deletions
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 032ff03ad90..b356884fb3e 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -9,13 +9,17 @@ * License. * * File: ima_api.c - * Implements must_measure, collect_measurement, store_measurement, - * and store_template. + * Implements must_appraise_or_measure, collect_measurement, + * appraise_measurement, store_measurement and store_template. */ #include <linux/module.h> #include <linux/slab.h> - +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/xattr.h> +#include <linux/evm.h> #include "ima.h" + static const char *IMA_TEMPLATE_NAME = "ima"; /* @@ -93,7 +97,7 @@ err_out: } /** - * ima_must_measure - measure decision based on policy. + * ima_get_action - appraise & 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) @@ -105,15 +109,22 @@ err_out: * 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) + * Returns IMA_MEASURE, IMA_APPRAISE mask. + * + */ +int ima_get_action(struct inode *inode, int mask, int function) { - int must_measure; + int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE; + + if (!ima_appraise) + flags &= ~IMA_APPRAISE; - must_measure = ima_match_policy(inode, function, mask); - return must_measure ? 0 : -EACCES; + return ima_match_policy(inode, function, mask, flags); +} + +int ima_must_measure(struct inode *inode, int mask, int function) +{ + return ima_match_policy(inode, function, mask, IMA_MEASURE); } /* @@ -129,16 +140,24 @@ int ima_must_measure(struct inode *inode, int mask, int function) int ima_collect_measurement(struct integrity_iint_cache *iint, struct file *file) { - int result = -EEXIST; + struct inode *inode = file->f_dentry->d_inode; + const char *filename = file->f_dentry->d_name.name; + int result = 0; - if (!(iint->flags & IMA_MEASURED)) { + if (!(iint->flags & IMA_COLLECTED)) { 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->ima_xattr.type = IMA_XATTR_DIGEST; + result = ima_calc_hash(file, iint->ima_xattr.digest); + if (!result) { iint->version = i_version; + iint->flags |= IMA_COLLECTED; + } } + if (result) + integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, + filename, "collect_data", "failed", + result, 0); return result; } @@ -167,6 +186,9 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct ima_template_entry *entry; int violation = 0; + if (iint->flags & IMA_MEASURED) + return; + entry = kmalloc(sizeof(*entry), GFP_KERNEL); if (!entry) { integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, @@ -174,7 +196,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, return; } memset(&entry->template, 0, sizeof(entry->template)); - memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE); + memcpy(entry->template.digest, iint->ima_xattr.digest, IMA_DIGEST_SIZE); strcpy(entry->template.file_name, (strlen(filename) > IMA_EVENT_NAME_LEN_MAX) ? file->f_dentry->d_name.name : filename); @@ -185,3 +207,33 @@ void ima_store_measurement(struct integrity_iint_cache *iint, if (result < 0) kfree(entry); } + +void ima_audit_measurement(struct integrity_iint_cache *iint, + const unsigned char *filename) +{ + struct audit_buffer *ab; + char hash[(IMA_DIGEST_SIZE * 2) + 1]; + int i; + + if (iint->flags & IMA_AUDITED) + return; + + for (i = 0; i < IMA_DIGEST_SIZE; i++) + hex_byte_pack(hash + (i * 2), iint->ima_xattr.digest[i]); + hash[i * 2] = '\0'; + + ab = audit_log_start(current->audit_context, GFP_KERNEL, + AUDIT_INTEGRITY_RULE); + if (!ab) + return; + + audit_log_format(ab, "file="); + audit_log_untrustedstring(ab, filename); + audit_log_format(ab, " hash="); + audit_log_untrustedstring(ab, hash); + + audit_log_task_info(ab, current); + audit_log_end(ab); + + iint->flags |= IMA_AUDITED; +} |