Skip to content

Commit 75a323e

Browse files
robertosassupcmoore
authored andcommitted
evm: Make it independent from 'integrity' LSM
Define a new structure for EVM-specific metadata, called evm_iint_cache, and embed it in the inode security blob. Introduce evm_iint_inode() to retrieve metadata, and register evm_inode_alloc_security() for the inode_alloc_security LSM hook, to initialize the structure (before splitting metadata, this task was done by iint_init_always()). Keep the non-NULL checks after calling evm_iint_inode() except in evm_inode_alloc_security(), to take into account inodes for which security_inode_alloc() was not called. When using shared metadata, obtaining a NULL pointer from integrity_iint_find() meant that the file wasn't in the IMA policy. Now, because IMA and EVM use disjoint metadata, the EVM status has to be stored for every inode regardless of the IMA policy. Given that from now on EVM relies on its own metadata, remove the iint parameter from evm_verifyxattr(). Also, directly retrieve the iint in evm_verify_hmac(), called by both evm_verifyxattr() and evm_verify_current_integrity(), since now there is no performance penalty in retrieving EVM metadata (constant time). Replicate the management of the IMA_NEW_FILE flag, by introducing evm_post_path_mknod() and evm_file_release() to respectively set and clear the newly introduced flag EVM_NEW_FILE, at the same time IMA does. Like for IMA, select CONFIG_SECURITY_PATH when EVM is enabled, to ensure that files are marked as new. Unlike ima_post_path_mknod(), evm_post_path_mknod() cannot check if a file must be appraised. Thus, it marks all affected files. Also, it does not clear EVM_NEW_FILE depending on i_version, but that is not a problem because IMA_NEW_FILE is always cleared when set in ima_check_last_writer(). Move the EVM-specific flag EVM_IMMUTABLE_DIGSIG to security/integrity/evm/evm.h, since that definition is now unnecessary in the common integrity layer. Finally, switch to the LSM reservation mechanism for the EVM xattr, and consequently decrement by one the number of xattrs to allocate in security_inode_init_security(). Signed-off-by: Roberto Sassu <[email protected]> Reviewed-by: Casey Schaufler <[email protected]> Reviewed-by: Stefan Berger <[email protected]> Reviewed-by: Mimi Zohar <[email protected]> Acked-by: Mimi Zohar <[email protected]> Signed-off-by: Paul Moore <[email protected]>
1 parent 9238311 commit 75a323e

File tree

8 files changed

+83
-32
lines changed

8 files changed

+83
-32
lines changed

include/linux/evm.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,12 @@
1212
#include <linux/integrity.h>
1313
#include <linux/xattr.h>
1414

15-
struct integrity_iint_cache;
16-
1715
#ifdef CONFIG_EVM
1816
extern int evm_set_key(void *key, size_t keylen);
1917
extern enum integrity_status evm_verifyxattr(struct dentry *dentry,
2018
const char *xattr_name,
2119
void *xattr_value,
22-
size_t xattr_value_len,
23-
struct integrity_iint_cache *iint);
20+
size_t xattr_value_len);
2421
int evm_inode_init_security(struct inode *inode, struct inode *dir,
2522
const struct qstr *qstr, struct xattr *xattrs,
2623
int *xattr_count);
@@ -48,8 +45,7 @@ static inline int evm_set_key(void *key, size_t keylen)
4845
static inline enum integrity_status evm_verifyxattr(struct dentry *dentry,
4946
const char *xattr_name,
5047
void *xattr_value,
51-
size_t xattr_value_len,
52-
struct integrity_iint_cache *iint)
48+
size_t xattr_value_len)
5349
{
5450
return INTEGRITY_UNKNOWN;
5551
}

security/integrity/evm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ config EVM
66
select CRYPTO_HMAC
77
select CRYPTO_SHA1
88
select CRYPTO_HASH_INFO
9+
select SECURITY_PATH
910
default n
1011
help
1112
EVM protects a file's security extended attributes against

security/integrity/evm/evm.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,25 @@ struct xattr_list {
3232
bool enabled;
3333
};
3434

35+
#define EVM_NEW_FILE 0x00000001
36+
#define EVM_IMMUTABLE_DIGSIG 0x00000002
37+
38+
/* EVM integrity metadata associated with an inode */
39+
struct evm_iint_cache {
40+
unsigned long flags;
41+
enum integrity_status evm_status:4;
42+
};
43+
44+
extern struct lsm_blob_sizes evm_blob_sizes;
45+
46+
static inline struct evm_iint_cache *evm_iint_inode(const struct inode *inode)
47+
{
48+
if (unlikely(!inode->i_security))
49+
return NULL;
50+
51+
return inode->i_security + evm_blob_sizes.lbs_inode;
52+
}
53+
3554
extern int evm_initialized;
3655

3756
#define EVM_ATTR_FSUUID 0x0001

security/integrity/evm/evm_crypto.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,10 @@ int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
322322
static int evm_is_immutable(struct dentry *dentry, struct inode *inode)
323323
{
324324
const struct evm_ima_xattr_data *xattr_data = NULL;
325-
struct integrity_iint_cache *iint;
325+
struct evm_iint_cache *iint;
326326
int rc = 0;
327327

328-
iint = integrity_iint_find(inode);
328+
iint = evm_iint_inode(inode);
329329
if (iint && (iint->flags & EVM_IMMUTABLE_DIGSIG))
330330
return 1;
331331

security/integrity/evm/evm_main.c

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -178,14 +178,14 @@ static int is_unsupported_fs(struct dentry *dentry)
178178
static enum integrity_status evm_verify_hmac(struct dentry *dentry,
179179
const char *xattr_name,
180180
char *xattr_value,
181-
size_t xattr_value_len,
182-
struct integrity_iint_cache *iint)
181+
size_t xattr_value_len)
183182
{
184183
struct evm_ima_xattr_data *xattr_data = NULL;
185184
struct signature_v2_hdr *hdr;
186185
enum integrity_status evm_status = INTEGRITY_PASS;
187186
struct evm_digest digest;
188-
struct inode *inode;
187+
struct inode *inode = d_backing_inode(dentry);
188+
struct evm_iint_cache *iint = evm_iint_inode(inode);
189189
int rc, xattr_len, evm_immutable = 0;
190190

191191
if (iint && (iint->evm_status == INTEGRITY_PASS ||
@@ -254,8 +254,6 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
254254
(const char *)xattr_data, xattr_len,
255255
digest.digest, digest.hdr.length);
256256
if (!rc) {
257-
inode = d_backing_inode(dentry);
258-
259257
if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) {
260258
if (iint)
261259
iint->flags |= EVM_IMMUTABLE_DIGSIG;
@@ -403,7 +401,6 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
403401
* @xattr_name: requested xattr
404402
* @xattr_value: requested xattr value
405403
* @xattr_value_len: requested xattr value length
406-
* @iint: inode integrity metadata
407404
*
408405
* Calculate the HMAC for the given dentry and verify it against the stored
409406
* security.evm xattr. For performance, use the xattr value and length
@@ -416,22 +413,16 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
416413
*/
417414
enum integrity_status evm_verifyxattr(struct dentry *dentry,
418415
const char *xattr_name,
419-
void *xattr_value, size_t xattr_value_len,
420-
struct integrity_iint_cache *iint)
416+
void *xattr_value, size_t xattr_value_len)
421417
{
422418
if (!evm_key_loaded() || !evm_protected_xattr(xattr_name))
423419
return INTEGRITY_UNKNOWN;
424420

425421
if (is_unsupported_fs(dentry))
426422
return INTEGRITY_UNKNOWN;
427423

428-
if (!iint) {
429-
iint = integrity_iint_find(d_backing_inode(dentry));
430-
if (!iint)
431-
return INTEGRITY_UNKNOWN;
432-
}
433424
return evm_verify_hmac(dentry, xattr_name, xattr_value,
434-
xattr_value_len, iint);
425+
xattr_value_len);
435426
}
436427
EXPORT_SYMBOL_GPL(evm_verifyxattr);
437428

@@ -448,7 +439,7 @@ static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
448439

449440
if (!evm_key_loaded() || !S_ISREG(inode->i_mode) || evm_fixmode)
450441
return INTEGRITY_PASS;
451-
return evm_verify_hmac(dentry, NULL, NULL, 0, NULL);
442+
return evm_verify_hmac(dentry, NULL, NULL, 0);
452443
}
453444

454445
/*
@@ -526,14 +517,14 @@ static int evm_protect_xattr(struct mnt_idmap *idmap,
526517

527518
evm_status = evm_verify_current_integrity(dentry);
528519
if (evm_status == INTEGRITY_NOXATTRS) {
529-
struct integrity_iint_cache *iint;
520+
struct evm_iint_cache *iint;
530521

531522
/* Exception if the HMAC is not going to be calculated. */
532523
if (evm_hmac_disabled())
533524
return 0;
534525

535-
iint = integrity_iint_find(d_backing_inode(dentry));
536-
if (iint && (iint->flags & IMA_NEW_FILE))
526+
iint = evm_iint_inode(d_backing_inode(dentry));
527+
if (iint && (iint->flags & EVM_NEW_FILE))
537528
return 0;
538529

539530
/* exception for pseudo filesystems */
@@ -735,9 +726,9 @@ static int evm_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry,
735726

736727
static void evm_reset_status(struct inode *inode)
737728
{
738-
struct integrity_iint_cache *iint;
729+
struct evm_iint_cache *iint;
739730

740-
iint = integrity_iint_find(inode);
731+
iint = evm_iint_inode(inode);
741732
if (iint)
742733
iint->evm_status = INTEGRITY_UNKNOWN;
743734
}
@@ -1019,6 +1010,42 @@ int evm_inode_init_security(struct inode *inode, struct inode *dir,
10191010
}
10201011
EXPORT_SYMBOL_GPL(evm_inode_init_security);
10211012

1013+
static int evm_inode_alloc_security(struct inode *inode)
1014+
{
1015+
struct evm_iint_cache *iint = evm_iint_inode(inode);
1016+
1017+
/* Called by security_inode_alloc(), it cannot be NULL. */
1018+
iint->flags = 0UL;
1019+
iint->evm_status = INTEGRITY_UNKNOWN;
1020+
1021+
return 0;
1022+
}
1023+
1024+
static void evm_file_release(struct file *file)
1025+
{
1026+
struct inode *inode = file_inode(file);
1027+
struct evm_iint_cache *iint = evm_iint_inode(inode);
1028+
fmode_t mode = file->f_mode;
1029+
1030+
if (!S_ISREG(inode->i_mode) || !(mode & FMODE_WRITE))
1031+
return;
1032+
1033+
if (iint && atomic_read(&inode->i_writecount) == 1)
1034+
iint->flags &= ~EVM_NEW_FILE;
1035+
}
1036+
1037+
static void evm_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
1038+
{
1039+
struct inode *inode = d_backing_inode(dentry);
1040+
struct evm_iint_cache *iint = evm_iint_inode(inode);
1041+
1042+
if (!S_ISREG(inode->i_mode))
1043+
return;
1044+
1045+
if (iint)
1046+
iint->flags |= EVM_NEW_FILE;
1047+
}
1048+
10221049
#ifdef CONFIG_EVM_LOAD_X509
10231050
void __init evm_load_x509(void)
10241051
{
@@ -1071,6 +1098,9 @@ static struct security_hook_list evm_hooks[] __ro_after_init = {
10711098
LSM_HOOK_INIT(inode_removexattr, evm_inode_removexattr),
10721099
LSM_HOOK_INIT(inode_post_removexattr, evm_inode_post_removexattr),
10731100
LSM_HOOK_INIT(inode_init_security, evm_inode_init_security),
1101+
LSM_HOOK_INIT(inode_alloc_security, evm_inode_alloc_security),
1102+
LSM_HOOK_INIT(file_release, evm_file_release),
1103+
LSM_HOOK_INIT(path_post_mknod, evm_post_path_mknod),
10741104
};
10751105

10761106
static const struct lsm_id evm_lsmid = {
@@ -1084,10 +1114,16 @@ static int __init init_evm_lsm(void)
10841114
return 0;
10851115
}
10861116

1117+
struct lsm_blob_sizes evm_blob_sizes __ro_after_init = {
1118+
.lbs_inode = sizeof(struct evm_iint_cache),
1119+
.lbs_xattr_count = 1,
1120+
};
1121+
10871122
DEFINE_LSM(evm) = {
10881123
.name = "evm",
10891124
.init = init_evm_lsm,
10901125
.order = LSM_ORDER_LAST,
1126+
.blobs = &evm_blob_sizes,
10911127
};
10921128

10931129
late_initcall(init_evm);

security/integrity/ima/ima_appraise.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ int ima_appraise_measurement(enum ima_hooks func,
520520
}
521521

522522
status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value,
523-
rc < 0 ? 0 : rc, iint);
523+
rc < 0 ? 0 : rc);
524524
switch (status) {
525525
case INTEGRITY_PASS:
526526
case INTEGRITY_PASS_IMMUTABLE:

security/integrity/integrity.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
#define IMA_DIGSIG_REQUIRED 0x01000000
3838
#define IMA_PERMIT_DIRECTIO 0x02000000
3939
#define IMA_NEW_FILE 0x04000000
40-
#define EVM_IMMUTABLE_DIGSIG 0x08000000
4140
#define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000
4241
#define IMA_MODSIG_ALLOWED 0x20000000
4342
#define IMA_CHECK_BLACKLIST 0x40000000

security/security.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,8 +1716,8 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
17161716
return 0;
17171717

17181718
if (initxattrs) {
1719-
/* Allocate +1 for EVM and +1 as terminator. */
1720-
new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 2,
1719+
/* Allocate +1 as terminator. */
1720+
new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 1,
17211721
sizeof(*new_xattrs), GFP_NOFS);
17221722
if (!new_xattrs)
17231723
return -ENOMEM;

0 commit comments

Comments
 (0)