Skip to content

Commit 9238311

Browse files
robertosassupcmoore
authored andcommitted
evm: Move to LSM infrastructure
As for IMA, move hardcoded EVM function calls from various places in the kernel to the LSM infrastructure, by introducing a new LSM named 'evm' (last and always enabled like 'ima'). The order in the Makefile ensures that 'evm' hooks are executed after 'ima' ones. Make EVM functions as static (except for evm_inode_init_security(), which is exported), and register them as hook implementations in init_evm_lsm(). Also move the inline functions evm_inode_remove_acl(), evm_inode_post_remove_acl(), and evm_inode_post_set_acl() from the public evm.h header to evm_main.c. Unlike before (see commit to move IMA to the LSM infrastructure), evm_inode_post_setattr(), evm_inode_post_set_acl(), evm_inode_post_remove_acl(), and evm_inode_post_removexattr() are not executed for private inodes. Finally, add the LSM_ID_EVM case in lsm_list_modules_test.c Signed-off-by: Roberto Sassu <[email protected]> Reviewed-by: Casey Schaufler <[email protected]> Acked-by: Christian Brauner <[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 84594c9 commit 9238311

File tree

8 files changed

+116
-169
lines changed

8 files changed

+116
-169
lines changed

fs/attr.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#include <linux/fcntl.h>
1717
#include <linux/filelock.h>
1818
#include <linux/security.h>
19-
#include <linux/evm.h>
2019

2120
#include "internal.h"
2221

@@ -502,7 +501,6 @@ int notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
502501
if (!error) {
503502
fsnotify_change(dentry, ia_valid);
504503
security_inode_post_setattr(idmap, dentry, ia_valid);
505-
evm_inode_post_setattr(idmap, dentry, ia_valid);
506504
}
507505

508506
return error;

fs/posix_acl.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#include <linux/mnt_idmapping.h>
2727
#include <linux/iversion.h>
2828
#include <linux/security.h>
29-
#include <linux/evm.h>
3029
#include <linux/fsnotify.h>
3130
#include <linux/filelock.h>
3231

@@ -1138,7 +1137,6 @@ int vfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
11381137
if (!error) {
11391138
fsnotify_xattr(dentry);
11401139
security_inode_post_set_acl(dentry, acl_name, kacl);
1141-
evm_inode_post_set_acl(dentry, acl_name, kacl);
11421140
}
11431141

11441142
out_inode_unlock:
@@ -1247,7 +1245,6 @@ int vfs_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry,
12471245
if (!error) {
12481246
fsnotify_xattr(dentry);
12491247
security_inode_post_remove_acl(idmap, dentry, acl_name);
1250-
evm_inode_post_remove_acl(idmap, dentry, acl_name);
12511248
}
12521249

12531250
out_inode_unlock:

fs/xattr.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#include <linux/mount.h>
1717
#include <linux/namei.h>
1818
#include <linux/security.h>
19-
#include <linux/evm.h>
2019
#include <linux/syscalls.h>
2120
#include <linux/export.h>
2221
#include <linux/fsnotify.h>
@@ -557,7 +556,6 @@ __vfs_removexattr_locked(struct mnt_idmap *idmap,
557556

558557
fsnotify_xattr(dentry);
559558
security_inode_post_removexattr(dentry, name);
560-
evm_inode_post_removexattr(dentry, name);
561559

562560
out:
563561
return error;

include/linux/evm.h

Lines changed: 0 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -21,45 +21,6 @@ extern enum integrity_status evm_verifyxattr(struct dentry *dentry,
2121
void *xattr_value,
2222
size_t xattr_value_len,
2323
struct integrity_iint_cache *iint);
24-
extern int evm_inode_setattr(struct mnt_idmap *idmap,
25-
struct dentry *dentry, struct iattr *attr);
26-
extern void evm_inode_post_setattr(struct mnt_idmap *idmap,
27-
struct dentry *dentry, int ia_valid);
28-
extern int evm_inode_setxattr(struct mnt_idmap *idmap,
29-
struct dentry *dentry, const char *name,
30-
const void *value, size_t size, int flags);
31-
extern void evm_inode_post_setxattr(struct dentry *dentry,
32-
const char *xattr_name,
33-
const void *xattr_value,
34-
size_t xattr_value_len,
35-
int flags);
36-
extern int evm_inode_copy_up_xattr(const char *name);
37-
extern int evm_inode_removexattr(struct mnt_idmap *idmap,
38-
struct dentry *dentry, const char *xattr_name);
39-
extern void evm_inode_post_removexattr(struct dentry *dentry,
40-
const char *xattr_name);
41-
static inline void evm_inode_post_remove_acl(struct mnt_idmap *idmap,
42-
struct dentry *dentry,
43-
const char *acl_name)
44-
{
45-
evm_inode_post_removexattr(dentry, acl_name);
46-
}
47-
extern int evm_inode_set_acl(struct mnt_idmap *idmap,
48-
struct dentry *dentry, const char *acl_name,
49-
struct posix_acl *kacl);
50-
static inline int evm_inode_remove_acl(struct mnt_idmap *idmap,
51-
struct dentry *dentry,
52-
const char *acl_name)
53-
{
54-
return evm_inode_set_acl(idmap, dentry, acl_name, NULL);
55-
}
56-
static inline void evm_inode_post_set_acl(struct dentry *dentry,
57-
const char *acl_name,
58-
struct posix_acl *kacl)
59-
{
60-
return evm_inode_post_setxattr(dentry, acl_name, NULL, 0, 0);
61-
}
62-
6324
int evm_inode_init_security(struct inode *inode, struct inode *dir,
6425
const struct qstr *qstr, struct xattr *xattrs,
6526
int *xattr_count);
@@ -94,80 +55,6 @@ static inline enum integrity_status evm_verifyxattr(struct dentry *dentry,
9455
}
9556
#endif
9657

97-
static inline int evm_inode_setattr(struct mnt_idmap *idmap,
98-
struct dentry *dentry, struct iattr *attr)
99-
{
100-
return 0;
101-
}
102-
103-
static inline void evm_inode_post_setattr(struct mnt_idmap *idmap,
104-
struct dentry *dentry, int ia_valid)
105-
{
106-
return;
107-
}
108-
109-
static inline int evm_inode_setxattr(struct mnt_idmap *idmap,
110-
struct dentry *dentry, const char *name,
111-
const void *value, size_t size, int flags)
112-
{
113-
return 0;
114-
}
115-
116-
static inline void evm_inode_post_setxattr(struct dentry *dentry,
117-
const char *xattr_name,
118-
const void *xattr_value,
119-
size_t xattr_value_len,
120-
int flags)
121-
{
122-
return;
123-
}
124-
125-
static inline int evm_inode_copy_up_xattr(const char *name)
126-
{
127-
return 0;
128-
}
129-
130-
static inline int evm_inode_removexattr(struct mnt_idmap *idmap,
131-
struct dentry *dentry,
132-
const char *xattr_name)
133-
{
134-
return 0;
135-
}
136-
137-
static inline void evm_inode_post_removexattr(struct dentry *dentry,
138-
const char *xattr_name)
139-
{
140-
return;
141-
}
142-
143-
static inline void evm_inode_post_remove_acl(struct mnt_idmap *idmap,
144-
struct dentry *dentry,
145-
const char *acl_name)
146-
{
147-
return;
148-
}
149-
150-
static inline int evm_inode_set_acl(struct mnt_idmap *idmap,
151-
struct dentry *dentry, const char *acl_name,
152-
struct posix_acl *kacl)
153-
{
154-
return 0;
155-
}
156-
157-
static inline int evm_inode_remove_acl(struct mnt_idmap *idmap,
158-
struct dentry *dentry,
159-
const char *acl_name)
160-
{
161-
return 0;
162-
}
163-
164-
static inline void evm_inode_post_set_acl(struct dentry *dentry,
165-
const char *acl_name,
166-
struct posix_acl *kacl)
167-
{
168-
return;
169-
}
170-
17158
static inline int evm_inode_init_security(struct inode *inode, struct inode *dir,
17259
const struct qstr *qstr,
17360
struct xattr *xattrs,

include/uapi/linux/lsm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ struct lsm_ctx {
6363
#define LSM_ID_BPF 109
6464
#define LSM_ID_LANDLOCK 110
6565
#define LSM_ID_IMA 111
66+
#define LSM_ID_EVM 112
6667

6768
/*
6869
* LSM_ATTR_XXX definitions identify different LSM attributes

security/integrity/evm/evm_main.c

Lines changed: 102 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -589,9 +589,9 @@ static int evm_protect_xattr(struct mnt_idmap *idmap,
589589
* userspace from writing HMAC value. Writing 'security.evm' requires
590590
* requires CAP_SYS_ADMIN privileges.
591591
*/
592-
int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
593-
const char *xattr_name, const void *xattr_value,
594-
size_t xattr_value_len, int flags)
592+
static int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
593+
const char *xattr_name, const void *xattr_value,
594+
size_t xattr_value_len, int flags)
595595
{
596596
const struct evm_ima_xattr_data *xattr_data = xattr_value;
597597

@@ -621,8 +621,8 @@ int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
621621
* Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that
622622
* the current value is valid.
623623
*/
624-
int evm_inode_removexattr(struct mnt_idmap *idmap,
625-
struct dentry *dentry, const char *xattr_name)
624+
static int evm_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry,
625+
const char *xattr_name)
626626
{
627627
/* Policy permits modification of the protected xattrs even though
628628
* there's no HMAC key loaded
@@ -672,9 +672,11 @@ static inline int evm_inode_set_acl_change(struct mnt_idmap *idmap,
672672
* Prevent modifying posix acls causing the EVM HMAC to be re-calculated
673673
* and 'security.evm' xattr updated, unless the existing 'security.evm' is
674674
* valid.
675+
*
676+
* Return: zero on success, -EPERM on failure.
675677
*/
676-
int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
677-
const char *acl_name, struct posix_acl *kacl)
678+
static int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
679+
const char *acl_name, struct posix_acl *kacl)
678680
{
679681
enum integrity_status evm_status;
680682

@@ -713,6 +715,24 @@ int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
713715
return -EPERM;
714716
}
715717

718+
/**
719+
* evm_inode_remove_acl - Protect the EVM extended attribute from posix acls
720+
* @idmap: idmap of the mount
721+
* @dentry: pointer to the affected dentry
722+
* @acl_name: name of the posix acl
723+
*
724+
* Prevent removing posix acls causing the EVM HMAC to be re-calculated
725+
* and 'security.evm' xattr updated, unless the existing 'security.evm' is
726+
* valid.
727+
*
728+
* Return: zero on success, -EPERM on failure.
729+
*/
730+
static int evm_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry,
731+
const char *acl_name)
732+
{
733+
return evm_inode_set_acl(idmap, dentry, acl_name, NULL);
734+
}
735+
716736
static void evm_reset_status(struct inode *inode)
717737
{
718738
struct integrity_iint_cache *iint;
@@ -761,9 +781,11 @@ bool evm_revalidate_status(const char *xattr_name)
761781
* __vfs_setxattr_noperm(). The caller of which has taken the inode's
762782
* i_mutex lock.
763783
*/
764-
void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
765-
const void *xattr_value, size_t xattr_value_len,
766-
int flags)
784+
static void evm_inode_post_setxattr(struct dentry *dentry,
785+
const char *xattr_name,
786+
const void *xattr_value,
787+
size_t xattr_value_len,
788+
int flags)
767789
{
768790
if (!evm_revalidate_status(xattr_name))
769791
return;
@@ -782,6 +804,21 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
782804
evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
783805
}
784806

807+
/**
808+
* evm_inode_post_set_acl - Update the EVM extended attribute from posix acls
809+
* @dentry: pointer to the affected dentry
810+
* @acl_name: name of the posix acl
811+
* @kacl: pointer to the posix acls
812+
*
813+
* Update the 'security.evm' xattr with the EVM HMAC re-calculated after setting
814+
* posix acls.
815+
*/
816+
static void evm_inode_post_set_acl(struct dentry *dentry, const char *acl_name,
817+
struct posix_acl *kacl)
818+
{
819+
return evm_inode_post_setxattr(dentry, acl_name, NULL, 0, 0);
820+
}
821+
785822
/**
786823
* evm_inode_post_removexattr - update 'security.evm' after removing the xattr
787824
* @dentry: pointer to the affected dentry
@@ -792,7 +829,8 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
792829
* No need to take the i_mutex lock here, as this function is called from
793830
* vfs_removexattr() which takes the i_mutex.
794831
*/
795-
void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
832+
static void evm_inode_post_removexattr(struct dentry *dentry,
833+
const char *xattr_name)
796834
{
797835
if (!evm_revalidate_status(xattr_name))
798836
return;
@@ -808,6 +846,22 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
808846
evm_update_evmxattr(dentry, xattr_name, NULL, 0);
809847
}
810848

849+
/**
850+
* evm_inode_post_remove_acl - Update the EVM extended attribute from posix acls
851+
* @idmap: idmap of the mount
852+
* @dentry: pointer to the affected dentry
853+
* @acl_name: name of the posix acl
854+
*
855+
* Update the 'security.evm' xattr with the EVM HMAC re-calculated after
856+
* removing posix acls.
857+
*/
858+
static inline void evm_inode_post_remove_acl(struct mnt_idmap *idmap,
859+
struct dentry *dentry,
860+
const char *acl_name)
861+
{
862+
evm_inode_post_removexattr(dentry, acl_name);
863+
}
864+
811865
static int evm_attr_change(struct mnt_idmap *idmap,
812866
struct dentry *dentry, struct iattr *attr)
813867
{
@@ -831,8 +885,8 @@ static int evm_attr_change(struct mnt_idmap *idmap,
831885
* Permit update of file attributes when files have a valid EVM signature,
832886
* except in the case of them having an immutable portable signature.
833887
*/
834-
int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
835-
struct iattr *attr)
888+
static int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
889+
struct iattr *attr)
836890
{
837891
unsigned int ia_valid = attr->ia_valid;
838892
enum integrity_status evm_status;
@@ -883,8 +937,8 @@ int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
883937
* This function is called from notify_change(), which expects the caller
884938
* to lock the inode's i_mutex.
885939
*/
886-
void evm_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
887-
int ia_valid)
940+
static void evm_inode_post_setattr(struct mnt_idmap *idmap,
941+
struct dentry *dentry, int ia_valid)
888942
{
889943
if (!evm_revalidate_status(NULL))
890944
return;
@@ -901,7 +955,7 @@ void evm_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
901955
evm_update_evmxattr(dentry, NULL, NULL, 0);
902956
}
903957

904-
int evm_inode_copy_up_xattr(const char *name)
958+
static int evm_inode_copy_up_xattr(const char *name)
905959
{
906960
if (strcmp(name, XATTR_NAME_EVM) == 0)
907961
return 1; /* Discard */
@@ -1004,4 +1058,36 @@ static int __init init_evm(void)
10041058
return error;
10051059
}
10061060

1061+
static struct security_hook_list evm_hooks[] __ro_after_init = {
1062+
LSM_HOOK_INIT(inode_setattr, evm_inode_setattr),
1063+
LSM_HOOK_INIT(inode_post_setattr, evm_inode_post_setattr),
1064+
LSM_HOOK_INIT(inode_copy_up_xattr, evm_inode_copy_up_xattr),
1065+
LSM_HOOK_INIT(inode_setxattr, evm_inode_setxattr),
1066+
LSM_HOOK_INIT(inode_post_setxattr, evm_inode_post_setxattr),
1067+
LSM_HOOK_INIT(inode_set_acl, evm_inode_set_acl),
1068+
LSM_HOOK_INIT(inode_post_set_acl, evm_inode_post_set_acl),
1069+
LSM_HOOK_INIT(inode_remove_acl, evm_inode_remove_acl),
1070+
LSM_HOOK_INIT(inode_post_remove_acl, evm_inode_post_remove_acl),
1071+
LSM_HOOK_INIT(inode_removexattr, evm_inode_removexattr),
1072+
LSM_HOOK_INIT(inode_post_removexattr, evm_inode_post_removexattr),
1073+
LSM_HOOK_INIT(inode_init_security, evm_inode_init_security),
1074+
};
1075+
1076+
static const struct lsm_id evm_lsmid = {
1077+
.name = "evm",
1078+
.id = LSM_ID_EVM,
1079+
};
1080+
1081+
static int __init init_evm_lsm(void)
1082+
{
1083+
security_add_hooks(evm_hooks, ARRAY_SIZE(evm_hooks), &evm_lsmid);
1084+
return 0;
1085+
}
1086+
1087+
DEFINE_LSM(evm) = {
1088+
.name = "evm",
1089+
.init = init_evm_lsm,
1090+
.order = LSM_ORDER_LAST,
1091+
};
1092+
10071093
late_initcall(init_evm);

0 commit comments

Comments
 (0)