]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - security/integrity/ima/ima_appraise.c
ima: add support for different security.ima data types
[mirror_ubuntu-zesty-kernel.git] / security / integrity / ima / ima_appraise.c
CommitLineData
2fe5d6de
MZ
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{
07f6a794
MZ
39 if (!ima_appraise)
40 return 0;
41
42 return ima_match_policy(inode, func, mask, IMA_APPRAISE);
2fe5d6de
MZ
43}
44
45static void ima_fix_xattr(struct dentry *dentry,
46 struct integrity_iint_cache *iint)
47{
5a44b412
MZ
48 iint->ima_xattr.type = IMA_XATTR_DIGEST;
49 __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA, (u8 *)&iint->ima_xattr,
50 sizeof iint->ima_xattr, 0);
2fe5d6de
MZ
51}
52
53/*
54 * ima_appraise_measurement - appraise file measurement
55 *
56 * Call evm_verifyxattr() to verify the integrity of 'security.ima'.
57 * Assuming success, compare the xattr hash with the collected measurement.
58 *
59 * Return 0 on success, error code otherwise
60 */
61int ima_appraise_measurement(struct integrity_iint_cache *iint,
62 struct file *file, const unsigned char *filename)
63{
64 struct dentry *dentry = file->f_dentry;
65 struct inode *inode = dentry->d_inode;
5a44b412 66 struct evm_ima_xattr_data xattr_value;
2fe5d6de
MZ
67 enum integrity_status status = INTEGRITY_UNKNOWN;
68 const char *op = "appraise_data";
69 char *cause = "unknown";
70 int rc;
71
72 if (!ima_appraise)
73 return 0;
74 if (!inode->i_op->getxattr)
75 return INTEGRITY_UNKNOWN;
76
77 if (iint->flags & IMA_APPRAISED)
78 return iint->ima_status;
79
5a44b412
MZ
80 rc = inode->i_op->getxattr(dentry, XATTR_NAME_IMA, (u8 *)&xattr_value,
81 sizeof xattr_value);
2fe5d6de
MZ
82 if (rc <= 0) {
83 if (rc && rc != -ENODATA)
84 goto out;
85
86 cause = "missing-hash";
87 status =
88 (inode->i_size == 0) ? INTEGRITY_PASS : INTEGRITY_NOLABEL;
89 goto out;
90 }
91
5a44b412
MZ
92 status = evm_verifyxattr(dentry, XATTR_NAME_IMA, (u8 *)&xattr_value,
93 rc, iint);
2fe5d6de
MZ
94 if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
95 if ((status == INTEGRITY_NOLABEL)
96 || (status == INTEGRITY_NOXATTRS))
97 cause = "missing-HMAC";
98 else if (status == INTEGRITY_FAIL)
99 cause = "invalid-HMAC";
100 goto out;
101 }
102
5a44b412
MZ
103 rc = memcmp(xattr_value.digest, iint->ima_xattr.digest,
104 IMA_DIGEST_SIZE);
2fe5d6de
MZ
105 if (rc) {
106 status = INTEGRITY_FAIL;
107 cause = "invalid-hash";
108 print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE,
5a44b412 109 &xattr_value, sizeof xattr_value);
2fe5d6de 110 print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE,
5a44b412
MZ
111 (u8 *)&iint->ima_xattr,
112 sizeof iint->ima_xattr);
2fe5d6de
MZ
113 goto out;
114 }
115 status = INTEGRITY_PASS;
116 iint->flags |= IMA_APPRAISED;
117out:
118 if (status != INTEGRITY_PASS) {
119 if (ima_appraise & IMA_APPRAISE_FIX) {
120 ima_fix_xattr(dentry, iint);
121 status = INTEGRITY_PASS;
122 }
123 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
124 op, cause, rc, 0);
125 }
126 iint->ima_status = status;
127 return status;
128}
129
130/*
131 * ima_update_xattr - update 'security.ima' hash value
132 */
133void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
134{
135 struct dentry *dentry = file->f_dentry;
136 int rc = 0;
137
138 rc = ima_collect_measurement(iint, file);
139 if (rc < 0)
140 return;
141 ima_fix_xattr(dentry, iint);
142}
143
144/**
145 * ima_inode_post_setattr - reflect file metadata changes
146 * @dentry: pointer to the affected dentry
147 *
148 * Changes to a dentry's metadata might result in needing to appraise.
149 *
150 * This function is called from notify_change(), which expects the caller
151 * to lock the inode's i_mutex.
152 */
153void ima_inode_post_setattr(struct dentry *dentry)
154{
155 struct inode *inode = dentry->d_inode;
156 struct integrity_iint_cache *iint;
157 int must_appraise, rc;
158
159 if (!ima_initialized || !ima_appraise || !S_ISREG(inode->i_mode)
160 || !inode->i_op->removexattr)
161 return;
162
163 must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR);
164 iint = integrity_iint_find(inode);
165 if (iint) {
166 if (must_appraise)
167 iint->flags |= IMA_APPRAISE;
168 else
169 iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED);
170 }
171 if (!must_appraise)
172 rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA);
173 return;
174}
42c63330
MZ
175
176/*
177 * ima_protect_xattr - protect 'security.ima'
178 *
179 * Ensure that not just anyone can modify or remove 'security.ima'.
180 */
181static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name,
182 const void *xattr_value, size_t xattr_value_len)
183{
184 if (strcmp(xattr_name, XATTR_NAME_IMA) == 0) {
185 if (!capable(CAP_SYS_ADMIN))
186 return -EPERM;
187 return 1;
188 }
189 return 0;
190}
191
192static void ima_reset_appraise_flags(struct inode *inode)
193{
194 struct integrity_iint_cache *iint;
195
196 if (!ima_initialized || !ima_appraise || !S_ISREG(inode->i_mode))
197 return;
198
199 iint = integrity_iint_find(inode);
200 if (!iint)
201 return;
202
203 iint->flags &= ~(IMA_COLLECTED | IMA_APPRAISED | IMA_MEASURED);
204 return;
205}
206
207int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
208 const void *xattr_value, size_t xattr_value_len)
209{
210 int result;
211
212 result = ima_protect_xattr(dentry, xattr_name, xattr_value,
213 xattr_value_len);
214 if (result == 1) {
215 ima_reset_appraise_flags(dentry->d_inode);
216 result = 0;
217 }
218 return result;
219}
220
221int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)
222{
223 int result;
224
225 result = ima_protect_xattr(dentry, xattr_name, NULL, 0);
226 if (result == 1) {
227 ima_reset_appraise_flags(dentry->d_inode);
228 result = 0;
229 }
230 return result;
231}