aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity
diff options
context:
space:
mode:
authorMimi Zohar <zohar@linux.vnet.ibm.com>2012-02-13 10:15:05 -0500
committerMimi Zohar <zohar@linux.vnet.ibm.com>2012-09-07 14:57:44 -0400
commit2fe5d6def1672ae6635dd71867bf36dcfaa7434b (patch)
treef83878d309605440b5bc2d2d43a16ccece64c645 /security/integrity
parent4199d35cbc90c15db447d115bd96ffa5f1d60d3a (diff)
ima: integrity appraisal extension
IMA currently maintains an integrity measurement list used to assert the integrity of the running system to a third party. The IMA-appraisal extension adds local integrity validation and enforcement of the measurement against a "good" value stored as an extended attribute 'security.ima'. The initial methods for validating 'security.ima' are hashed based, which provides file data integrity, and digital signature based, which in addition to providing file data integrity, provides authenticity. This patch creates and maintains the 'security.ima' xattr, containing the file data hash measurement. Protection of the xattr is provided by EVM, if enabled and configured. Based on policy, IMA calls evm_verifyxattr() to verify a file's metadata integrity and, assuming success, compares the file's current hash value with the one stored as an extended attribute in 'security.ima'. Changelov v4: - changed iint cache flags to hex values Changelog v3: - change appraisal default for filesystems without xattr support to fail Changelog v2: - fix audit msg 'res' value - removed unused 'ima_appraise=' values Changelog v1: - removed unused iint mutex (Dmitry Kasatkin) - setattr hook must not reset appraised (Dmitry Kasatkin) - evm_verifyxattr() now differentiates between no 'security.evm' xattr (INTEGRITY_NOLABEL) and no EVM 'protected' xattrs included in the 'security.evm' (INTEGRITY_NOXATTRS). - replace hash_status with ima_status (Dmitry Kasatkin) - re-initialize slab element ima_status on free (Dmitry Kasatkin) - include 'security.ima' in EVM if CONFIG_IMA_APPRAISE, not CONFIG_IMA - merged half "ima: ima_must_appraise_or_measure API change" (Dmitry Kasatkin) - removed unnecessary error variable in process_measurement() (Dmitry Kasatkin) - use ima_inode_post_setattr() stub function, if IMA_APPRAISE not configured (moved ima_inode_post_setattr() to ima_appraise.c) - make sure ima_collect_measurement() can read file Changelog: - add 'iint' to evm_verifyxattr() call (Dimitry Kasatkin) - fix the race condition between chmod, which takes the i_mutex and then iint->mutex, and ima_file_free() and process_measurement(), which take the locks in the reverse order, by eliminating iint->mutex. (Dmitry Kasatkin) - cleanup of ima_appraise_measurement() (Dmitry Kasatkin) - changes as a result of the iint not allocated for all regular files, but only for those measured/appraised. - don't try to appraise new/empty files - expanded ima_appraisal description in ima/Kconfig - IMA appraise definitions required even if IMA_APPRAISE not enabled - add return value to ima_must_appraise() stub - unconditionally set status = INTEGRITY_PASS *after* testing status, not before. (Found by Joe Perches) Signed-off-by: Mimi Zohar <zohar@us.ibm.com> Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
Diffstat (limited to 'security/integrity')
-rw-r--r--security/integrity/evm/evm_main.c3
-rw-r--r--security/integrity/iint.c3
-rw-r--r--security/integrity/ima/Kconfig15
-rw-r--r--security/integrity/ima/Makefile1
-rw-r--r--security/integrity/ima/ima.h37
-rw-r--r--security/integrity/ima/ima_api.c50
-rw-r--r--security/integrity/ima/ima_appraise.c168
-rw-r--r--security/integrity/ima/ima_crypto.c8
-rw-r--r--security/integrity/ima/ima_main.c79
-rw-r--r--security/integrity/ima/ima_policy.c32
-rw-r--r--security/integrity/integrity.h8
11 files changed, 351 insertions, 53 deletions
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 8901501425f4..eb5484504f50 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -34,6 +34,9 @@ char *evm_config_xattrnames[] = {
34#ifdef CONFIG_SECURITY_SMACK 34#ifdef CONFIG_SECURITY_SMACK
35 XATTR_NAME_SMACK, 35 XATTR_NAME_SMACK,
36#endif 36#endif
37#ifdef CONFIG_IMA_APPRAISE
38 XATTR_NAME_IMA,
39#endif
37 XATTR_NAME_CAPS, 40 XATTR_NAME_CAPS,
38 NULL 41 NULL
39}; 42};
diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index 399641c3e846..e600986aa49f 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -74,6 +74,7 @@ static void iint_free(struct integrity_iint_cache *iint)
74{ 74{
75 iint->version = 0; 75 iint->version = 0;
76 iint->flags = 0UL; 76 iint->flags = 0UL;
77 iint->ima_status = INTEGRITY_UNKNOWN;
77 iint->evm_status = INTEGRITY_UNKNOWN; 78 iint->evm_status = INTEGRITY_UNKNOWN;
78 kmem_cache_free(iint_cache, iint); 79 kmem_cache_free(iint_cache, iint);
79} 80}
@@ -157,7 +158,7 @@ static void init_once(void *foo)
157 memset(iint, 0, sizeof *iint); 158 memset(iint, 0, sizeof *iint);
158 iint->version = 0; 159 iint->version = 0;
159 iint->flags = 0UL; 160 iint->flags = 0UL;
160 mutex_init(&iint->mutex); 161 iint->ima_status = INTEGRITY_UNKNOWN;
161 iint->evm_status = INTEGRITY_UNKNOWN; 162 iint->evm_status = INTEGRITY_UNKNOWN;
162} 163}
163 164
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 809ccf19d09c..d232c73647ae 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -56,3 +56,18 @@ config IMA_LSM_RULES
56 default y 56 default y
57 help 57 help
58 Disabling this option will disregard LSM based policy rules. 58 Disabling this option will disregard LSM based policy rules.
59
60config IMA_APPRAISE
61 bool "Appraise integrity measurements"
62 depends on IMA
63 default n
64 help
65 This option enables local measurement integrity appraisal.
66 It requires the system to be labeled with a security extended
67 attribute containing the file hash measurement. To protect
68 the security extended attributes from offline attack, enable
69 and configure EVM.
70
71 For more information on integrity appraisal refer to:
72 <http://linux-ima.sourceforge.net>
73 If unsure, say N.
diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
index 5f740f6971e1..3f2ca6bdc384 100644
--- a/security/integrity/ima/Makefile
+++ b/security/integrity/ima/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_IMA) += ima.o
8ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ 8ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
9 ima_policy.o 9 ima_policy.o
10ima-$(CONFIG_IMA_AUDIT) += ima_audit.o 10ima-$(CONFIG_IMA_AUDIT) += ima_audit.o
11ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index e7c99fd0d223..069a4aa63e95 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -40,6 +40,7 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
40extern int ima_initialized; 40extern int ima_initialized;
41extern int ima_used_chip; 41extern int ima_used_chip;
42extern char *ima_hash; 42extern char *ima_hash;
43extern int ima_appraise;
43 44
44/* IMA inode template definition */ 45/* IMA inode template definition */
45struct ima_template_data { 46struct ima_template_data {
@@ -107,6 +108,7 @@ static inline unsigned long ima_hash_key(u8 *digest)
107} 108}
108 109
109/* LIM API function definitions */ 110/* LIM API function definitions */
111int ima_must_appraise_or_measure(struct inode *inode, int mask, int function);
110int ima_must_measure(struct inode *inode, int mask, int function); 112int ima_must_measure(struct inode *inode, int mask, int function);
111int ima_collect_measurement(struct integrity_iint_cache *iint, 113int ima_collect_measurement(struct integrity_iint_cache *iint,
112 struct file *file); 114 struct file *file);
@@ -123,14 +125,45 @@ struct integrity_iint_cache *integrity_iint_insert(struct inode *inode);
123struct integrity_iint_cache *integrity_iint_find(struct inode *inode); 125struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
124 126
125/* IMA policy related functions */ 127/* IMA policy related functions */
126enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK }; 128enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK, POST_SETATTR };
127 129
128int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); 130int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
131 int flags);
129void ima_init_policy(void); 132void ima_init_policy(void);
130void ima_update_policy(void); 133void ima_update_policy(void);
131ssize_t ima_parse_add_rule(char *); 134ssize_t ima_parse_add_rule(char *);
132void ima_delete_rules(void); 135void ima_delete_rules(void);
133 136
137/* Appraise integrity measurements */
138#define IMA_APPRAISE_ENFORCE 0x01
139#define IMA_APPRAISE_FIX 0x02
140
141#ifdef CONFIG_IMA_APPRAISE
142int ima_appraise_measurement(struct integrity_iint_cache *iint,
143 struct file *file, const unsigned char *filename);
144int ima_must_appraise(struct inode *inode, enum ima_hooks func, int mask);
145void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
146
147#else
148static inline int ima_appraise_measurement(struct integrity_iint_cache *iint,
149 struct file *file,
150 const unsigned char *filename)
151{
152 return INTEGRITY_UNKNOWN;
153}
154
155static inline int ima_must_appraise(struct inode *inode,
156 enum ima_hooks func, int mask)
157{
158 return 0;
159}
160
161static inline void ima_update_xattr(struct integrity_iint_cache *iint,
162 struct file *file)
163{
164}
165#endif
166
134/* LSM based policy rules require audit */ 167/* LSM based policy rules require audit */
135#ifdef CONFIG_IMA_LSM_RULES 168#ifdef CONFIG_IMA_LSM_RULES
136 169
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 032ff03ad907..41cce84416c5 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -9,13 +9,17 @@
9 * License. 9 * License.
10 * 10 *
11 * File: ima_api.c 11 * File: ima_api.c
12 * Implements must_measure, collect_measurement, store_measurement, 12 * Implements must_appraise_or_measure, collect_measurement,
13 * and store_template. 13 * appraise_measurement, store_measurement and store_template.
14 */ 14 */
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17 17#include <linux/file.h>
18#include <linux/fs.h>
19#include <linux/xattr.h>
20#include <linux/evm.h>
18#include "ima.h" 21#include "ima.h"
22
19static const char *IMA_TEMPLATE_NAME = "ima"; 23static const char *IMA_TEMPLATE_NAME = "ima";
20 24
21/* 25/*
@@ -93,7 +97,7 @@ err_out:
93} 97}
94 98
95/** 99/**
96 * ima_must_measure - measure decision based on policy. 100 * ima_must_appraise_or_measure - appraise & measure decision based on policy.
97 * @inode: pointer to inode to measure 101 * @inode: pointer to inode to measure
98 * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) 102 * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
99 * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP) 103 * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP)
@@ -105,15 +109,22 @@ err_out:
105 * mask: contains the permission mask 109 * mask: contains the permission mask
106 * fsmagic: hex value 110 * fsmagic: hex value
107 * 111 *
108 * Return 0 to measure. For matching a DONT_MEASURE policy, no policy, 112 * Returns IMA_MEASURE, IMA_APPRAISE mask.
109 * or other error, return an error code. 113 *
110*/ 114 */
111int ima_must_measure(struct inode *inode, int mask, int function) 115int ima_must_appraise_or_measure(struct inode *inode, int mask, int function)
112{ 116{
113 int must_measure; 117 int flags = IMA_MEASURE | IMA_APPRAISE;
118
119 if (!ima_appraise)
120 flags &= ~IMA_APPRAISE;
121
122 return ima_match_policy(inode, function, mask, flags);
123}
114 124
115 must_measure = ima_match_policy(inode, function, mask); 125int ima_must_measure(struct inode *inode, int mask, int function)
116 return must_measure ? 0 : -EACCES; 126{
127 return ima_match_policy(inode, function, mask, IMA_MEASURE);
117} 128}
118 129
119/* 130/*
@@ -129,16 +140,24 @@ int ima_must_measure(struct inode *inode, int mask, int function)
129int ima_collect_measurement(struct integrity_iint_cache *iint, 140int ima_collect_measurement(struct integrity_iint_cache *iint,
130 struct file *file) 141 struct file *file)
131{ 142{
132 int result = -EEXIST; 143 struct inode *inode = file->f_dentry->d_inode;
144 const char *filename = file->f_dentry->d_name.name;
145 int result = 0;
133 146
134 if (!(iint->flags & IMA_MEASURED)) { 147 if (!(iint->flags & IMA_COLLECTED)) {
135 u64 i_version = file->f_dentry->d_inode->i_version; 148 u64 i_version = file->f_dentry->d_inode->i_version;
136 149
137 memset(iint->digest, 0, IMA_DIGEST_SIZE); 150 memset(iint->digest, 0, IMA_DIGEST_SIZE);
138 result = ima_calc_hash(file, iint->digest); 151 result = ima_calc_hash(file, iint->digest);
139 if (!result) 152 if (!result) {
140 iint->version = i_version; 153 iint->version = i_version;
154 iint->flags |= IMA_COLLECTED;
155 }
141 } 156 }
157 if (result)
158 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
159 filename, "collect_data", "failed",
160 result, 0);
142 return result; 161 return result;
143} 162}
144 163
@@ -167,6 +186,9 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
167 struct ima_template_entry *entry; 186 struct ima_template_entry *entry;
168 int violation = 0; 187 int violation = 0;
169 188
189 if (iint->flags & IMA_MEASURED)
190 return;
191
170 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 192 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
171 if (!entry) { 193 if (!entry) {
172 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, 194 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
new file mode 100644
index 000000000000..4865f61f9044
--- /dev/null
+++ b/security/integrity/ima/ima_appraise.c
@@ -0,0 +1,168 @@
1/*
2 * Copyright (C) 2011 IBM Corporation
3 *
4 * Author:
5 * Mimi Zohar <zohar@us.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 2 of the License.
10 */
11#include <linux/module.h>
12#include <linux/file.h>
13#include <linux/fs.h>
14#include <linux/xattr.h>
15#include <linux/magic.h>
16#include <linux/ima.h>
17#include <linux/evm.h>
18
19#include "ima.h"
20
21static int __init default_appraise_setup(char *str)
22{
23 if (strncmp(str, "off", 3) == 0)
24 ima_appraise = 0;
25 else if (strncmp(str, "fix", 3) == 0)
26 ima_appraise = IMA_APPRAISE_FIX;
27 return 1;
28}
29
30__setup("ima_appraise=", default_appraise_setup);
31
32/*
33 * ima_must_appraise - set appraise flag
34 *
35 * Return 1 to appraise
36 */
37int ima_must_appraise(struct inode *inode, enum ima_hooks func, int mask)
38{
39 return 0;
40}
41
42static void ima_fix_xattr(struct dentry *dentry,
43 struct integrity_iint_cache *iint)
44{
45 iint->digest[0] = IMA_XATTR_DIGEST;
46 __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA,
47 iint->digest, IMA_DIGEST_SIZE + 1, 0);
48}
49
50/*
51 * ima_appraise_measurement - appraise file measurement
52 *
53 * Call evm_verifyxattr() to verify the integrity of 'security.ima'.
54 * Assuming success, compare the xattr hash with the collected measurement.
55 *
56 * Return 0 on success, error code otherwise
57 */
58int ima_appraise_measurement(struct integrity_iint_cache *iint,
59 struct file *file, const unsigned char *filename)
60{
61 struct dentry *dentry = file->f_dentry;
62 struct inode *inode = dentry->d_inode;
63 u8 xattr_value[IMA_DIGEST_SIZE];
64 enum integrity_status status = INTEGRITY_UNKNOWN;
65 const char *op = "appraise_data";
66 char *cause = "unknown";
67 int rc;
68
69 if (!ima_appraise)
70 return 0;
71 if (!inode->i_op->getxattr)
72 return INTEGRITY_UNKNOWN;
73
74 if (iint->flags & IMA_APPRAISED)
75 return iint->ima_status;
76
77 rc = inode->i_op->getxattr(dentry, XATTR_NAME_IMA, xattr_value,
78 IMA_DIGEST_SIZE);
79 if (rc <= 0) {
80 if (rc && rc != -ENODATA)
81 goto out;
82
83 cause = "missing-hash";
84 status =
85 (inode->i_size == 0) ? INTEGRITY_PASS : INTEGRITY_NOLABEL;
86 goto out;
87 }
88
89 status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
90 if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
91 if ((status == INTEGRITY_NOLABEL)
92 || (status == INTEGRITY_NOXATTRS))
93 cause = "missing-HMAC";
94 else if (status == INTEGRITY_FAIL)
95 cause = "invalid-HMAC";
96 goto out;
97 }
98
99 rc = memcmp(xattr_value, iint->digest, IMA_DIGEST_SIZE);
100 if (rc) {
101 status = INTEGRITY_FAIL;
102 cause = "invalid-hash";
103 print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE,
104 xattr_value, IMA_DIGEST_SIZE);
105 print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE,
106 iint->digest, IMA_DIGEST_SIZE);
107 goto out;
108 }
109 status = INTEGRITY_PASS;
110 iint->flags |= IMA_APPRAISED;
111out:
112 if (status != INTEGRITY_PASS) {
113 if (ima_appraise & IMA_APPRAISE_FIX) {
114 ima_fix_xattr(dentry, iint);
115 status = INTEGRITY_PASS;
116 }
117 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
118 op, cause, rc, 0);
119 }
120 iint->ima_status = status;
121 return status;
122}
123
124/*
125 * ima_update_xattr - update 'security.ima' hash value
126 */
127void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
128{
129 struct dentry *dentry = file->f_dentry;
130 int rc = 0;
131
132 rc = ima_collect_measurement(iint, file);
133 if (rc < 0)
134 return;
135 ima_fix_xattr(dentry, iint);
136}
137
138/**
139 * ima_inode_post_setattr - reflect file metadata changes
140 * @dentry: pointer to the affected dentry
141 *
142 * Changes to a dentry's metadata might result in needing to appraise.
143 *
144 * This function is called from notify_change(), which expects the caller
145 * to lock the inode's i_mutex.
146 */
147void ima_inode_post_setattr(struct dentry *dentry)
148{
149 struct inode *inode = dentry->d_inode;
150 struct integrity_iint_cache *iint;
151 int must_appraise, rc;
152
153 if (!ima_initialized || !ima_appraise || !S_ISREG(inode->i_mode)
154 || !inode->i_op->removexattr)
155 return;
156
157 must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR);
158 iint = integrity_iint_find(inode);
159 if (iint) {
160 if (must_appraise)
161 iint->flags |= IMA_APPRAISE;
162 else
163 iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED);
164 }
165 if (!must_appraise)
166 rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA);
167 return;
168}
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 9b3ade7468b2..b21ee5b5495a 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -48,7 +48,7 @@ int ima_calc_hash(struct file *file, char *digest)
48 struct scatterlist sg[1]; 48 struct scatterlist sg[1];
49 loff_t i_size, offset = 0; 49 loff_t i_size, offset = 0;
50 char *rbuf; 50 char *rbuf;
51 int rc; 51 int rc, read = 0;
52 52
53 rc = init_desc(&desc); 53 rc = init_desc(&desc);
54 if (rc != 0) 54 if (rc != 0)
@@ -59,6 +59,10 @@ int ima_calc_hash(struct file *file, char *digest)
59 rc = -ENOMEM; 59 rc = -ENOMEM;
60 goto out; 60 goto out;
61 } 61 }
62 if (!(file->f_mode & FMODE_READ)) {
63 file->f_mode |= FMODE_READ;
64 read = 1;
65 }
62 i_size = i_size_read(file->f_dentry->d_inode); 66 i_size = i_size_read(file->f_dentry->d_inode);
63 while (offset < i_size) { 67 while (offset < i_size) {
64 int rbuf_len; 68 int rbuf_len;
@@ -80,6 +84,8 @@ int ima_calc_hash(struct file *file, char *digest)
80 kfree(rbuf); 84 kfree(rbuf);
81 if (!rc) 85 if (!rc)
82 rc = crypto_hash_final(&desc, digest); 86 rc = crypto_hash_final(&desc, digest);
87 if (read)
88 file->f_mode &= ~FMODE_READ;
83out: 89out:
84 crypto_free_hash(desc.tfm); 90 crypto_free_hash(desc.tfm);
85 return rc; 91 return rc;
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index be8294915cf7..6eb28d47e74b 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -22,12 +22,19 @@
22#include <linux/mount.h> 22#include <linux/mount.h>
23#include <linux/mman.h> 23#include <linux/mman.h>
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/xattr.h>
25#include <linux/ima.h> 26#include <linux/ima.h>
26 27
27#include "ima.h" 28#include "ima.h"
28 29
29int ima_initialized; 30int ima_initialized;
30 31
32#ifdef CONFIG_IMA_APPRAISE
33int ima_appraise = IMA_APPRAISE_ENFORCE;
34#else
35int ima_appraise;
36#endif
37
31char *ima_hash = "sha1"; 38char *ima_hash = "sha1";
32static int __init hash_setup(char *str) 39static int __init hash_setup(char *str)
33{ 40{
@@ -52,7 +59,7 @@ static void ima_rdwr_violation_check(struct file *file)
52 struct dentry *dentry = file->f_path.dentry; 59 struct dentry *dentry = file->f_path.dentry;
53 struct inode *inode = dentry->d_inode; 60 struct inode *inode = dentry->d_inode;
54 fmode_t mode = file->f_mode; 61 fmode_t mode = file->f_mode;
55 int rc; 62 int must_measure;
56 bool send_tomtou = false, send_writers = false; 63 bool send_tomtou = false, send_writers = false;
57 unsigned char *pathname = NULL, *pathbuf = NULL; 64 unsigned char *pathname = NULL, *pathbuf = NULL;
58 65
@@ -67,8 +74,8 @@ static void ima_rdwr_violation_check(struct file *file)
67 goto out; 74 goto out;
68 } 75 }
69 76
70 rc = ima_must_measure(inode, MAY_READ, FILE_CHECK); 77 must_measure = ima_must_measure(inode, MAY_READ, FILE_CHECK);
71 if (rc < 0) 78 if (!must_measure)
72 goto out; 79 goto out;
73 80
74 if (atomic_read(&inode->i_writecount) > 0) 81 if (atomic_read(&inode->i_writecount) > 0)
@@ -100,17 +107,21 @@ out:
100} 107}
101 108
102static void ima_check_last_writer(struct integrity_iint_cache *iint, 109static void ima_check_last_writer(struct integrity_iint_cache *iint,
103 struct inode *inode, 110 struct inode *inode, struct file *file)
104 struct file *file)
105{ 111{
106 fmode_t mode = file->f_mode; 112 fmode_t mode = file->f_mode;
107 113
108 mutex_lock(&iint->mutex); 114 if (!(mode & FMODE_WRITE))
109 if (mode & FMODE_WRITE && 115 return;
110 atomic_read(&inode->i_writecount) == 1 && 116
111 iint->version != inode->i_version) 117 mutex_lock(&inode->i_mutex);
112 iint->flags &= ~IMA_MEASURED; 118 if (atomic_read(&inode->i_writecount) == 1 &&
113 mutex_unlock(&iint->mutex); 119 iint->version != inode->i_version) {
120 iint->flags &= ~(IMA_COLLECTED | IMA_APPRAISED | IMA_MEASURED);
121 if (iint->flags & IMA_APPRAISE)
122 ima_update_xattr(iint, file);
123 }
124 mutex_unlock(&inode->i_mutex);
114} 125}
115 126
116/** 127/**
@@ -140,14 +151,17 @@ static int process_measurement(struct file *file, const unsigned char *filename,
140 struct inode *inode = file->f_dentry->d_inode; 151 struct inode *inode = file->f_dentry->d_inode;
141 struct integrity_iint_cache *iint; 152 struct integrity_iint_cache *iint;
142 unsigned char *pathname = NULL, *pathbuf = NULL; 153 unsigned char *pathname = NULL, *pathbuf = NULL;
143 int rc = 0; 154 int rc = -ENOMEM, action, must_appraise;
144 155
145 if (!ima_initialized || !S_ISREG(inode->i_mode)) 156 if (!ima_initialized || !S_ISREG(inode->i_mode))
146 return 0; 157 return 0;
147 158
148 rc = ima_must_measure(inode, mask, function); 159 /* Determine if in appraise/measurement policy,
149 if (rc != 0) 160 * returns IMA_MEASURE, IMA_APPRAISE bitmask. */
150 return rc; 161 action = ima_must_appraise_or_measure(inode, mask, function);
162 if (!action)
163 return 0;
164
151retry: 165retry:
152 iint = integrity_iint_find(inode); 166 iint = integrity_iint_find(inode);
153 if (!iint) { 167 if (!iint) {
@@ -157,11 +171,21 @@ retry:
157 return rc; 171 return rc;
158 } 172 }
159 173
160 mutex_lock(&iint->mutex); 174 must_appraise = action & IMA_APPRAISE;
161 175
162 rc = iint->flags & IMA_MEASURED ? 1 : 0; 176 mutex_lock(&inode->i_mutex);
163 if (rc != 0) 177
178 /* Determine if already appraised/measured based on bitmask
179 * (IMA_MEASURE, IMA_MEASURED, IMA_APPRAISE, IMA_APPRAISED) */
180 iint->flags |= action;
181 action &= ~((iint->flags & (IMA_MEASURED | IMA_APPRAISED)) >> 1);
182
183 /* Nothing to do, just return existing appraised status */
184 if (!action) {
185 if (iint->flags & IMA_APPRAISED)
186 rc = iint->ima_status;
164 goto out; 187 goto out;
188 }
165 189
166 rc = ima_collect_measurement(iint, file); 190 rc = ima_collect_measurement(iint, file);
167 if (rc != 0) 191 if (rc != 0)
@@ -177,11 +201,16 @@ retry:
177 pathname = NULL; 201 pathname = NULL;
178 } 202 }
179 } 203 }
180 ima_store_measurement(iint, file, !pathname ? filename : pathname); 204 if (action & IMA_MEASURE)
205 ima_store_measurement(iint, file,
206 !pathname ? filename : pathname);
207 if (action & IMA_APPRAISE)
208 rc = ima_appraise_measurement(iint, file,
209 !pathname ? filename : pathname);
181 kfree(pathbuf); 210 kfree(pathbuf);
182out: 211out:
183 mutex_unlock(&iint->mutex); 212 mutex_unlock(&inode->i_mutex);
184 return rc; 213 return (rc && must_appraise) ? -EACCES : 0;
185} 214}
186 215
187/** 216/**
@@ -197,14 +226,14 @@ out:
197 */ 226 */
198int ima_file_mmap(struct file *file, unsigned long prot) 227int ima_file_mmap(struct file *file, unsigned long prot)
199{ 228{
200 int rc; 229 int rc = 0;
201 230
202 if (!file) 231 if (!file)
203 return 0; 232 return 0;
204 if (prot & PROT_EXEC) 233 if (prot & PROT_EXEC)
205 rc = process_measurement(file, file->f_dentry->d_name.name, 234 rc = process_measurement(file, file->f_dentry->d_name.name,
206 MAY_EXEC, FILE_MMAP); 235 MAY_EXEC, FILE_MMAP);
207 return 0; 236 return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0;
208} 237}
209 238
210/** 239/**
@@ -228,7 +257,7 @@ int ima_bprm_check(struct linux_binprm *bprm)
228 (strcmp(bprm->filename, bprm->interp) == 0) ? 257 (strcmp(bprm->filename, bprm->interp) == 0) ?
229 bprm->filename : bprm->interp, 258 bprm->filename : bprm->interp,
230 MAY_EXEC, BPRM_CHECK); 259 MAY_EXEC, BPRM_CHECK);
231 return 0; 260 return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0;
232} 261}
233 262
234/** 263/**
@@ -249,7 +278,7 @@ int ima_file_check(struct file *file, int mask)
249 rc = process_measurement(file, file->f_dentry->d_name.name, 278 rc = process_measurement(file, file->f_dentry->d_name.name,
250 mask & (MAY_READ | MAY_WRITE | MAY_EXEC), 279 mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
251 FILE_CHECK); 280 FILE_CHECK);
252 return 0; 281 return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0;
253} 282}
254EXPORT_SYMBOL_GPL(ima_file_check); 283EXPORT_SYMBOL_GPL(ima_file_check);
255 284
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 1a9583008aae..3e22e17da295 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -25,7 +25,13 @@
25#define IMA_FSMAGIC 0x0004 25#define IMA_FSMAGIC 0x0004
26#define IMA_UID 0x0008 26#define IMA_UID 0x0008
27 27
28enum ima_action { UNKNOWN = -1, DONT_MEASURE = 0, MEASURE }; 28#define UNKNOWN 0
29#define MEASURE 1 /* same as IMA_MEASURE */
30#define DONT_MEASURE 2
31#define MEASURE_MASK 3
32#define APPRAISE 4 /* same as IMA_APPRAISE */
33#define DONT_APPRAISE 8
34#define APPRAISE_MASK 12
29 35
30#define MAX_LSM_RULES 6 36#define MAX_LSM_RULES 6
31enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, 37enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
@@ -34,7 +40,7 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
34 40
35struct ima_measure_rule_entry { 41struct ima_measure_rule_entry {
36 struct list_head list; 42 struct list_head list;
37 enum ima_action action; 43 int action;
38 unsigned int flags; 44 unsigned int flags;
39 enum ima_hooks func; 45 enum ima_hooks func;
40 int mask; 46 int mask;
@@ -163,18 +169,28 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
163 * as elements in the list are never deleted, nor does the list 169 * as elements in the list are never deleted, nor does the list
164 * change.) 170 * change.)
165 */ 171 */
166int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask) 172int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
173 int flags)
167{ 174{
168 struct ima_measure_rule_entry *entry; 175 struct ima_measure_rule_entry *entry;
176 int action = 0, actmask = flags | (flags << 1);
169 177
170 list_for_each_entry(entry, ima_measure, list) { 178 list_for_each_entry(entry, ima_measure, list) {
171 bool rc;
172 179
173 rc = ima_match_rules(entry, inode, func, mask); 180 if (!(entry->action & actmask))
174 if (rc) 181 continue;
175 return entry->action; 182
183 if (!ima_match_rules(entry, inode, func, mask))
184 continue;
185
186 action |= (entry->action & (IMA_APPRAISE | IMA_MEASURE));
187 actmask &= (entry->action & APPRAISE_MASK) ?
188 ~APPRAISE_MASK : ~MEASURE_MASK;
189 if (!actmask)
190 break;
176 } 191 }
177 return 0; 192
193 return action;
178} 194}
179 195
180/** 196/**
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 7a25ecec5aaa..dac6b68e945a 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -16,7 +16,11 @@
16#include <crypto/sha.h> 16#include <crypto/sha.h>
17 17
18/* iint cache flags */ 18/* iint cache flags */
19#define IMA_MEASURED 0x01 19#define IMA_MEASURE 0x01
20#define IMA_MEASURED 0x02
21#define IMA_APPRAISE 0x04
22#define IMA_APPRAISED 0x08
23#define IMA_COLLECTED 0x10
20 24
21enum evm_ima_xattr_type { 25enum evm_ima_xattr_type {
22 IMA_XATTR_DIGEST = 0x01, 26 IMA_XATTR_DIGEST = 0x01,
@@ -36,7 +40,7 @@ struct integrity_iint_cache {
36 u64 version; /* track inode changes */ 40 u64 version; /* track inode changes */
37 unsigned char flags; 41 unsigned char flags;
38 u8 digest[SHA1_DIGEST_SIZE]; 42 u8 digest[SHA1_DIGEST_SIZE];
39 struct mutex mutex; /* protects: version, flags, digest */ 43 enum integrity_status ima_status;
40 enum integrity_status evm_status; 44 enum integrity_status evm_status;
41}; 45};
42 46