aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt6
-rw-r--r--security/integrity/evm/evm_main.c77
2 files changed, 69 insertions, 14 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index fd248a318211..db97ff1da8c0 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -48,6 +48,7 @@ parameter is applicable:
48 EDD BIOS Enhanced Disk Drive Services (EDD) is enabled 48 EDD BIOS Enhanced Disk Drive Services (EDD) is enabled
49 EFI EFI Partitioning (GPT) is enabled 49 EFI EFI Partitioning (GPT) is enabled
50 EIDE EIDE/ATAPI support is enabled. 50 EIDE EIDE/ATAPI support is enabled.
51 EVM Extended Verification Module
51 FB The frame buffer device is enabled. 52 FB The frame buffer device is enabled.
52 GCOV GCOV profiling is enabled. 53 GCOV GCOV profiling is enabled.
53 HW Appropriate hardware is enabled. 54 HW Appropriate hardware is enabled.
@@ -750,6 +751,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
750 This option is obsoleted by the "netdev=" option, which 751 This option is obsoleted by the "netdev=" option, which
751 has equivalent usage. See its documentation for details. 752 has equivalent usage. See its documentation for details.
752 753
754 evm= [EVM]
755 Format: { "fix" }
756 Permit 'security.evm' to be updated regardless of
757 current integrity status.
758
753 failslab= 759 failslab=
754 fail_page_alloc= 760 fail_page_alloc=
755 fail_make_request=[KNL] 761 fail_make_request=[KNL]
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index eb07f9d13c24..94d66af07aa4 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -37,13 +37,25 @@ char *evm_config_xattrnames[] = {
37 NULL 37 NULL
38}; 38};
39 39
40static int evm_fixmode;
41static int __init evm_set_fixmode(char *str)
42{
43 if (strncmp(str, "fix", 3) == 0)
44 evm_fixmode = 1;
45 return 0;
46}
47__setup("evm=", evm_set_fixmode);
48
40/* 49/*
41 * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr 50 * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr
42 * 51 *
43 * Compute the HMAC on the dentry's protected set of extended attributes 52 * Compute the HMAC on the dentry's protected set of extended attributes
44 * and compare it against the stored security.evm xattr. (For performance, 53 * and compare it against the stored security.evm xattr.
45 * use the previoulsy retrieved xattr value and length to calculate the 54 *
46 * HMAC.) 55 * For performance:
56 * - use the previoulsy retrieved xattr value and length to calculate the
57 * HMAC.)
58 * - cache the verification result in the iint, when available.
47 * 59 *
48 * Returns integrity status 60 * Returns integrity status
49 */ 61 */
@@ -54,9 +66,10 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
54 struct integrity_iint_cache *iint) 66 struct integrity_iint_cache *iint)
55{ 67{
56 struct evm_ima_xattr_data xattr_data; 68 struct evm_ima_xattr_data xattr_data;
69 enum integrity_status evm_status;
57 int rc; 70 int rc;
58 71
59 if (iint->evm_status == INTEGRITY_PASS) 72 if (iint && iint->evm_status == INTEGRITY_PASS)
60 return iint->evm_status; 73 return iint->evm_status;
61 74
62 /* if status is not PASS, try to check again - against -ENOMEM */ 75 /* if status is not PASS, try to check again - against -ENOMEM */
@@ -71,18 +84,21 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
71 sizeof xattr_data, GFP_NOFS); 84 sizeof xattr_data, GFP_NOFS);
72 if (rc < 0) 85 if (rc < 0)
73 goto err_out; 86 goto err_out;
74 iint->evm_status = INTEGRITY_PASS; 87 evm_status = INTEGRITY_PASS;
75 return iint->evm_status; 88 goto out;
76 89
77err_out: 90err_out:
78 switch (rc) { 91 switch (rc) {
79 case -ENODATA: /* file not labelled */ 92 case -ENODATA: /* file not labelled */
80 iint->evm_status = INTEGRITY_NOLABEL; 93 evm_status = INTEGRITY_NOLABEL;
81 break; 94 break;
82 default: 95 default:
83 iint->evm_status = INTEGRITY_FAIL; 96 evm_status = INTEGRITY_FAIL;
84 } 97 }
85 return iint->evm_status; 98out:
99 if (iint)
100 iint->evm_status = evm_status;
101 return evm_status;
86} 102}
87 103
88static int evm_protected_xattr(const char *req_xattr_name) 104static int evm_protected_xattr(const char *req_xattr_name)
@@ -157,6 +173,22 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
157 return 0; 173 return 0;
158} 174}
159 175
176/*
177 * evm_verify_current_integrity - verify the dentry's metadata integrity
178 * @dentry: pointer to the affected dentry
179 *
180 * Verify and return the dentry's metadata integrity. The exceptions are
181 * before EVM is initialized or in 'fix' mode.
182 */
183static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
184{
185 struct inode *inode = dentry->d_inode;
186
187 if (!evm_initialized || !S_ISREG(inode->i_mode) || evm_fixmode)
188 return 0;
189 return evm_verify_hmac(dentry, NULL, NULL, 0, NULL);
190}
191
160/** 192/**
161 * evm_inode_setxattr - protect the EVM extended attribute 193 * evm_inode_setxattr - protect the EVM extended attribute
162 * @dentry: pointer to the affected dentry 194 * @dentry: pointer to the affected dentry
@@ -164,13 +196,22 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
164 * @xattr_value: pointer to the new extended attribute value 196 * @xattr_value: pointer to the new extended attribute value
165 * @xattr_value_len: pointer to the new extended attribute value length 197 * @xattr_value_len: pointer to the new extended attribute value length
166 * 198 *
167 * Prevent 'security.evm' from being modified 199 * Updating 'security.evm' requires CAP_SYS_ADMIN privileges and that
200 * the current value is valid.
168 */ 201 */
169int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name, 202int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,
170 const void *xattr_value, size_t xattr_value_len) 203 const void *xattr_value, size_t xattr_value_len)
171{ 204{
172 return evm_protect_xattr(dentry, xattr_name, xattr_value, 205
173 xattr_value_len); 206 enum integrity_status evm_status;
207 int ret;
208
209 ret = evm_protect_xattr(dentry, xattr_name, xattr_value,
210 xattr_value_len);
211 if (ret)
212 return ret;
213 evm_status = evm_verify_current_integrity(dentry);
214 return evm_status == INTEGRITY_PASS ? 0 : -EPERM;
174} 215}
175 216
176/** 217/**
@@ -178,11 +219,19 @@ int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,
178 * @dentry: pointer to the affected dentry 219 * @dentry: pointer to the affected dentry
179 * @xattr_name: pointer to the affected extended attribute name 220 * @xattr_name: pointer to the affected extended attribute name
180 * 221 *
181 * Prevent 'security.evm' from being removed. 222 * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that
223 * the current value is valid.
182 */ 224 */
183int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name) 225int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name)
184{ 226{
185 return evm_protect_xattr(dentry, xattr_name, NULL, 0); 227 enum integrity_status evm_status;
228 int ret;
229
230 ret = evm_protect_xattr(dentry, xattr_name, NULL, 0);
231 if (ret)
232 return ret;
233 evm_status = evm_verify_current_integrity(dentry);
234 return evm_status == INTEGRITY_PASS ? 0 : -EPERM;
186} 235}
187 236
188/** 237/**