Skip to content

Commit 8c7a703

Browse files
robertosassumimizohar
authored andcommitted
evm: Verify portable signatures against all protected xattrs
Currently, the evm_config_default_xattrnames array contains xattr names only related to LSMs which are enabled in the kernel configuration. However, EVM portable signatures do not depend on local information and a vendor might include in the signature calculation xattrs that are not enabled in the target platform. Just including all xattrs names in evm_config_default_xattrnames is not a safe approach, because a target system might have already calculated signatures or HMACs based only on the enabled xattrs. After applying this patch, EVM would verify those signatures and HMACs with all xattrs instead. The non-enabled ones, which could possibly exist, would cause a verification error. Thus, this patch adds a new field named enabled to the xattr_list structure, which is set to true if the LSM associated to a given xattr name is enabled in the kernel configuration. The non-enabled xattrs are taken into account only in evm_calc_hmac_or_hash(), if the passed security.evm type is EVM_XATTR_PORTABLE_DIGSIG. The new function evm_protected_xattr_if_enabled() has been defined so that IMA can include all protected xattrs and not only the enabled ones in the measurement list, if the new template fields xattrnames, xattrlengths or xattrvalues have been included in the template format. Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
1 parent f8216f6 commit 8c7a703

5 files changed

Lines changed: 74 additions & 12 deletions

File tree

include/linux/evm.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ extern int evm_inode_init_security(struct inode *inode,
3838
const struct xattr *xattr_array,
3939
struct xattr *evm);
4040
extern bool evm_revalidate_status(const char *xattr_name);
41+
extern int evm_protected_xattr_if_enabled(const char *req_xattr_name);
4142
#ifdef CONFIG_FS_POSIX_ACL
4243
extern int posix_xattr_acl(const char *xattrname);
4344
#else
@@ -114,5 +115,10 @@ static inline bool evm_revalidate_status(const char *xattr_name)
114115
return false;
115116
}
116117

118+
static inline int evm_protected_xattr_if_enabled(const char *req_xattr_name)
119+
{
120+
return false;
121+
}
122+
117123
#endif /* CONFIG_EVM */
118124
#endif /* LINUX_EVM_H */

security/integrity/evm/evm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
struct xattr_list {
3030
struct list_head list;
3131
char *name;
32+
bool enabled;
3233
};
3334

3435
extern int evm_initialized;

security/integrity/evm/evm_crypto.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,13 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
216216
if (strcmp(xattr->name, XATTR_NAME_IMA) == 0)
217217
is_ima = true;
218218

219+
/*
220+
* Skip non-enabled xattrs for locally calculated
221+
* signatures/HMACs.
222+
*/
223+
if (type != EVM_XATTR_PORTABLE_DIGSIG && !xattr->enabled)
224+
continue;
225+
219226
if ((req_xattr_name && req_xattr_value)
220227
&& !strcmp(xattr->name, req_xattr_name)) {
221228
error = 0;

security/integrity/evm/evm_main.c

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,44 @@ static const char * const integrity_status_msg[] = {
3434
int evm_hmac_attrs;
3535

3636
static struct xattr_list evm_config_default_xattrnames[] = {
37+
{.name = XATTR_NAME_SELINUX,
3738
#ifdef CONFIG_SECURITY_SELINUX
38-
{.name = XATTR_NAME_SELINUX},
39+
.enabled = true
3940
#endif
41+
},
42+
{.name = XATTR_NAME_SMACK,
4043
#ifdef CONFIG_SECURITY_SMACK
41-
{.name = XATTR_NAME_SMACK},
44+
.enabled = true
45+
#endif
46+
},
47+
{.name = XATTR_NAME_SMACKEXEC,
48+
#ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
49+
.enabled = true
50+
#endif
51+
},
52+
{.name = XATTR_NAME_SMACKTRANSMUTE,
4253
#ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
43-
{.name = XATTR_NAME_SMACKEXEC},
44-
{.name = XATTR_NAME_SMACKTRANSMUTE},
45-
{.name = XATTR_NAME_SMACKMMAP},
54+
.enabled = true
4655
#endif
56+
},
57+
{.name = XATTR_NAME_SMACKMMAP,
58+
#ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
59+
.enabled = true
4760
#endif
61+
},
62+
{.name = XATTR_NAME_APPARMOR,
4863
#ifdef CONFIG_SECURITY_APPARMOR
49-
{.name = XATTR_NAME_APPARMOR},
64+
.enabled = true
5065
#endif
66+
},
67+
{.name = XATTR_NAME_IMA,
5168
#ifdef CONFIG_IMA_APPRAISE
52-
{.name = XATTR_NAME_IMA},
69+
.enabled = true
5370
#endif
54-
{.name = XATTR_NAME_CAPS},
71+
},
72+
{.name = XATTR_NAME_CAPS,
73+
.enabled = true
74+
},
5575
};
5676

5777
LIST_HEAD(evm_config_xattrnames);
@@ -76,7 +96,9 @@ static void __init evm_init_config(void)
7696

7797
pr_info("Initialising EVM extended attributes:\n");
7898
for (i = 0; i < xattrs; i++) {
79-
pr_info("%s\n", evm_config_default_xattrnames[i].name);
99+
pr_info("%s%s\n", evm_config_default_xattrnames[i].name,
100+
!evm_config_default_xattrnames[i].enabled ?
101+
" (disabled)" : "");
80102
list_add_tail(&evm_config_default_xattrnames[i].list,
81103
&evm_config_xattrnames);
82104
}
@@ -257,14 +279,18 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
257279
return evm_status;
258280
}
259281

260-
static int evm_protected_xattr(const char *req_xattr_name)
282+
static int evm_protected_xattr_common(const char *req_xattr_name,
283+
bool all_xattrs)
261284
{
262285
int namelen;
263286
int found = 0;
264287
struct xattr_list *xattr;
265288

266289
namelen = strlen(req_xattr_name);
267290
list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) {
291+
if (!all_xattrs && !xattr->enabled)
292+
continue;
293+
268294
if ((strlen(xattr->name) == namelen)
269295
&& (strncmp(req_xattr_name, xattr->name, namelen) == 0)) {
270296
found = 1;
@@ -281,6 +307,16 @@ static int evm_protected_xattr(const char *req_xattr_name)
281307
return found;
282308
}
283309

310+
static int evm_protected_xattr(const char *req_xattr_name)
311+
{
312+
return evm_protected_xattr_common(req_xattr_name, false);
313+
}
314+
315+
int evm_protected_xattr_if_enabled(const char *req_xattr_name)
316+
{
317+
return evm_protected_xattr_common(req_xattr_name, true);
318+
}
319+
284320
/**
285321
* evm_verifyxattr - verify the integrity of the requested xattr
286322
* @dentry: object of the verify xattr

security/integrity/evm/evm_secfs.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,12 @@ static ssize_t evm_read_xattrs(struct file *filp, char __user *buf,
139139
if (rc)
140140
return -ERESTARTSYS;
141141

142-
list_for_each_entry(xattr, &evm_config_xattrnames, list)
142+
list_for_each_entry(xattr, &evm_config_xattrnames, list) {
143+
if (!xattr->enabled)
144+
continue;
145+
143146
size += strlen(xattr->name) + 1;
147+
}
144148

145149
temp = kmalloc(size + 1, GFP_KERNEL);
146150
if (!temp) {
@@ -149,6 +153,9 @@ static ssize_t evm_read_xattrs(struct file *filp, char __user *buf,
149153
}
150154

151155
list_for_each_entry(xattr, &evm_config_xattrnames, list) {
156+
if (!xattr->enabled)
157+
continue;
158+
152159
sprintf(temp + offset, "%s\n", xattr->name);
153160
offset += strlen(xattr->name) + 1;
154161
}
@@ -199,6 +206,7 @@ static ssize_t evm_write_xattrs(struct file *file, const char __user *buf,
199206
goto out;
200207
}
201208

209+
xattr->enabled = true;
202210
xattr->name = memdup_user_nul(buf, count);
203211
if (IS_ERR(xattr->name)) {
204212
err = PTR_ERR(xattr->name);
@@ -245,6 +253,10 @@ static ssize_t evm_write_xattrs(struct file *file, const char __user *buf,
245253
list_for_each_entry(tmp, &evm_config_xattrnames, list) {
246254
if (strcmp(xattr->name, tmp->name) == 0) {
247255
err = -EEXIST;
256+
if (!tmp->enabled) {
257+
tmp->enabled = true;
258+
err = count;
259+
}
248260
mutex_unlock(&xattr_list_mutex);
249261
goto out;
250262
}
@@ -256,7 +268,7 @@ static ssize_t evm_write_xattrs(struct file *file, const char __user *buf,
256268
audit_log_end(ab);
257269
return count;
258270
out:
259-
audit_log_format(ab, " res=%d", err);
271+
audit_log_format(ab, " res=%d", (err < 0) ? err : 0);
260272
audit_log_end(ab);
261273
if (xattr) {
262274
kfree(xattr->name);

0 commit comments

Comments
 (0)