Skip to content

Commit a60c538

Browse files
committed
Merge tag 'integrity-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity
Pull integrity subsystem updates from Mimi Zohar: "The large majority of the changes are EVM portable & immutable signature related: removing a dependency on loading an HMAC key, safely allowing file metadata included in the EVM portable & immutable signatures to be modified, allowing EVM signatures to fulfill IMA file signature policy requirements, including the EVM file metadata signature in lieu of an IMA file data signature in the measurement list, and adding dynamic debugging of EVM file metadata. In addition, in order to detect critical data or file change reversions, duplicate measurement records are permitted in the IMA measurement list. The remaining patches address compiler, sparse, and doc warnings" * tag 'integrity-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity: (31 commits) evm: Check xattr size discrepancy between kernel and user evm: output EVM digest calculation info IMA: support for duplicate measurement records ima: Fix warning: no previous prototype for function 'ima_add_kexec_buffer' ima: differentiate between EVM failures in the audit log ima: Fix fall-through warning for Clang ima: Pass NULL instead of 0 to ima_get_action() in ima_file_mprotect() ima: Include header defining ima_post_key_create_or_update() ima/evm: Fix type mismatch ima: Set correct casting types doc: Fix warning in Documentation/security/IMA-templates.rst evm: Don't return an error in evm_write_xattrs() if audit is not enabled ima: Define new template evm-sig ima: Define new template fields xattrnames, xattrlengths and xattrvalues evm: Verify portable signatures against all protected xattrs ima: Define new template field imode ima: Define new template fields iuid and igid ima: Add ima_show_template_uint() template library function ima: Don't remove security.ima if file must not be appraised ima: Introduce template field evmsig and write to field sig as fallback ...
2 parents 9cd19f0 + 907a399 commit a60c538

22 files changed

+804
-84
lines changed

Documentation/ABI/testing/evm

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Description:
2424
1 Enable digital signature validation
2525
2 Permit modification of EVM-protected metadata at
2626
runtime. Not supported if HMAC validation and
27-
creation is enabled.
27+
creation is enabled (deprecated).
2828
31 Disable further runtime modification of EVM policy
2929
=== ==================================================
3030

@@ -47,10 +47,38 @@ Description:
4747

4848
will enable digital signature validation, permit
4949
modification of EVM-protected metadata and
50-
disable all further modification of policy
50+
disable all further modification of policy. This option is now
51+
deprecated in favor of::
5152

52-
Note that once a key has been loaded, it will no longer be
53-
possible to enable metadata modification.
53+
echo 0x80000002 ><securityfs>/evm
54+
55+
as the outstanding issues that prevent the usage of EVM portable
56+
signatures have been solved.
57+
58+
Echoing a value is additive, the new value is added to the
59+
existing initialization flags.
60+
61+
For example, after::
62+
63+
echo 2 ><securityfs>/evm
64+
65+
another echo can be performed::
66+
67+
echo 1 ><securityfs>/evm
68+
69+
and the resulting value will be 3.
70+
71+
Note that once an HMAC key has been loaded, it will no longer
72+
be possible to enable metadata modification. Signaling that an
73+
HMAC key has been loaded will clear the corresponding flag.
74+
For example, if the current value is 6 (2 and 4 set)::
75+
76+
echo 1 ><securityfs>/evm
77+
78+
will set the new value to 3 (4 cleared).
79+
80+
Loading an HMAC key is the only way to disable metadata
81+
modification.
5482

5583
Until key loading has been signaled EVM can not create
5684
or validate the 'security.evm' xattr, but returns

Documentation/security/IMA-templates.rst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,18 @@ descriptors by adding their identifier to the format string
7070
prefix is shown only if the hash algorithm is not SHA1 or MD5);
7171
- 'd-modsig': the digest of the event without the appended modsig;
7272
- 'n-ng': the name of the event, without size limitations;
73-
- 'sig': the file signature;
73+
- 'sig': the file signature, or the EVM portable signature if the file
74+
signature is not found;
7475
- 'modsig' the appended file signature;
7576
- 'buf': the buffer data that was used to generate the hash without size limitations;
77+
- 'evmsig': the EVM portable signature;
78+
- 'iuid': the inode UID;
79+
- 'igid': the inode GID;
80+
- 'imode': the inode mode;
81+
- 'xattrnames': a list of xattr names (separated by ``|``), only if the xattr is
82+
present;
83+
- 'xattrlengths': a list of xattr lengths (u32), only if the xattr is present;
84+
- 'xattrvalues': a list of xattr values;
7685

7786

7887
Below, there is the list of defined template descriptors:
@@ -82,6 +91,7 @@ Below, there is the list of defined template descriptors:
8291
- "ima-sig": its format is ``d-ng|n-ng|sig``;
8392
- "ima-buf": its format is ``d-ng|n-ng|buf``;
8493
- "ima-modsig": its format is ``d-ng|n-ng|sig|d-modsig|modsig``;
94+
- "evm-sig": its format is ``d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode``;
8595

8696

8797
Use

include/linux/evm.h

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,25 @@ extern enum integrity_status evm_verifyxattr(struct dentry *dentry,
2323
struct integrity_iint_cache *iint);
2424
extern int evm_inode_setattr(struct dentry *dentry, struct iattr *attr);
2525
extern void evm_inode_post_setattr(struct dentry *dentry, int ia_valid);
26-
extern int evm_inode_setxattr(struct dentry *dentry, const char *name,
26+
extern int evm_inode_setxattr(struct user_namespace *mnt_userns,
27+
struct dentry *dentry, const char *name,
2728
const void *value, size_t size);
2829
extern void evm_inode_post_setxattr(struct dentry *dentry,
2930
const char *xattr_name,
3031
const void *xattr_value,
3132
size_t xattr_value_len);
32-
extern int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name);
33+
extern int evm_inode_removexattr(struct user_namespace *mnt_userns,
34+
struct dentry *dentry, const char *xattr_name);
3335
extern void evm_inode_post_removexattr(struct dentry *dentry,
3436
const char *xattr_name);
3537
extern int evm_inode_init_security(struct inode *inode,
3638
const struct xattr *xattr_array,
3739
struct xattr *evm);
40+
extern bool evm_revalidate_status(const char *xattr_name);
41+
extern int evm_protected_xattr_if_enabled(const char *req_xattr_name);
42+
extern int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
43+
int buffer_size, char type,
44+
bool canonical_fmt);
3845
#ifdef CONFIG_FS_POSIX_ACL
3946
extern int posix_xattr_acl(const char *xattrname);
4047
#else
@@ -71,7 +78,8 @@ static inline void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
7178
return;
7279
}
7380

74-
static inline int evm_inode_setxattr(struct dentry *dentry, const char *name,
81+
static inline int evm_inode_setxattr(struct user_namespace *mnt_userns,
82+
struct dentry *dentry, const char *name,
7583
const void *value, size_t size)
7684
{
7785
return 0;
@@ -85,7 +93,8 @@ static inline void evm_inode_post_setxattr(struct dentry *dentry,
8593
return;
8694
}
8795

88-
static inline int evm_inode_removexattr(struct dentry *dentry,
96+
static inline int evm_inode_removexattr(struct user_namespace *mnt_userns,
97+
struct dentry *dentry,
8998
const char *xattr_name)
9099
{
91100
return 0;
@@ -104,5 +113,22 @@ static inline int evm_inode_init_security(struct inode *inode,
104113
return 0;
105114
}
106115

116+
static inline bool evm_revalidate_status(const char *xattr_name)
117+
{
118+
return false;
119+
}
120+
121+
static inline int evm_protected_xattr_if_enabled(const char *req_xattr_name)
122+
{
123+
return false;
124+
}
125+
126+
static inline int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
127+
int buffer_size, char type,
128+
bool canonical_fmt)
129+
{
130+
return -EOPNOTSUPP;
131+
}
132+
107133
#endif /* CONFIG_EVM */
108134
#endif /* LINUX_EVM_H */

include/linux/integrity.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ enum integrity_status {
1313
INTEGRITY_PASS = 0,
1414
INTEGRITY_PASS_IMMUTABLE,
1515
INTEGRITY_FAIL,
16+
INTEGRITY_FAIL_IMMUTABLE,
1617
INTEGRITY_NOLABEL,
1718
INTEGRITY_NOXATTRS,
1819
INTEGRITY_UNKNOWN,

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: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
* Using root's kernel master key (kmk), calculate the HMAC
1111
*/
1212

13+
#define pr_fmt(fmt) "EVM: "fmt
14+
1315
#include <linux/export.h>
1416
#include <linux/crypto.h>
1517
#include <linux/xattr.h>
@@ -175,6 +177,30 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
175177
type != EVM_XATTR_PORTABLE_DIGSIG)
176178
crypto_shash_update(desc, (u8 *)&inode->i_sb->s_uuid, UUID_SIZE);
177179
crypto_shash_final(desc, digest);
180+
181+
pr_debug("hmac_misc: (%zu) [%*phN]\n", sizeof(struct h_misc),
182+
(int)sizeof(struct h_misc), &hmac_misc);
183+
}
184+
185+
/*
186+
* Dump large security xattr values as a continuous ascii hexademical string.
187+
* (pr_debug is limited to 64 bytes.)
188+
*/
189+
static void dump_security_xattr(const char *prefix, const void *src,
190+
size_t count)
191+
{
192+
#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
193+
char *asciihex, *p;
194+
195+
p = asciihex = kmalloc(count * 2 + 1, GFP_KERNEL);
196+
if (!asciihex)
197+
return;
198+
199+
p = bin2hex(p, src, count);
200+
*p = 0;
201+
pr_debug("%s: (%zu) %.*s\n", prefix, count, (int)count * 2, asciihex);
202+
kfree(asciihex);
203+
#endif
178204
}
179205

180206
/*
@@ -196,7 +222,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
196222
size_t xattr_size = 0;
197223
char *xattr_value = NULL;
198224
int error;
199-
int size;
225+
int size, user_space_size;
200226
bool ima_present = false;
201227

202228
if (!(inode->i_opflags & IOP_XATTR) ||
@@ -216,13 +242,30 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
216242
if (strcmp(xattr->name, XATTR_NAME_IMA) == 0)
217243
is_ima = true;
218244

245+
/*
246+
* Skip non-enabled xattrs for locally calculated
247+
* signatures/HMACs.
248+
*/
249+
if (type != EVM_XATTR_PORTABLE_DIGSIG && !xattr->enabled)
250+
continue;
251+
219252
if ((req_xattr_name && req_xattr_value)
220253
&& !strcmp(xattr->name, req_xattr_name)) {
221254
error = 0;
222255
crypto_shash_update(desc, (const u8 *)req_xattr_value,
223256
req_xattr_value_len);
224257
if (is_ima)
225258
ima_present = true;
259+
260+
if (req_xattr_value_len < 64)
261+
pr_debug("%s: (%zu) [%*phN]\n", req_xattr_name,
262+
req_xattr_value_len,
263+
(int)req_xattr_value_len,
264+
req_xattr_value);
265+
else
266+
dump_security_xattr(req_xattr_name,
267+
req_xattr_value,
268+
req_xattr_value_len);
226269
continue;
227270
}
228271
size = vfs_getxattr_alloc(&init_user_ns, dentry, xattr->name,
@@ -234,11 +277,24 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
234277
if (size < 0)
235278
continue;
236279

280+
user_space_size = vfs_getxattr(&init_user_ns, dentry,
281+
xattr->name, NULL, 0);
282+
if (user_space_size != size)
283+
pr_debug("file %s: xattr %s size mismatch (kernel: %d, user: %d)\n",
284+
dentry->d_name.name, xattr->name, size,
285+
user_space_size);
237286
error = 0;
238287
xattr_size = size;
239288
crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size);
240289
if (is_ima)
241290
ima_present = true;
291+
292+
if (xattr_size < 64)
293+
pr_debug("%s: (%zu) [%*phN]", xattr->name, xattr_size,
294+
(int)xattr_size, xattr_value);
295+
else
296+
dump_security_xattr(xattr->name, xattr_value,
297+
xattr_size);
242298
}
243299
hmac_add_misc(desc, inode, type, data->digest);
244300

0 commit comments

Comments
 (0)