Skip to content

Commit f91e654

Browse files
committed
Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull integrity updates from James Morris: "This adds support for EVM signatures based on larger digests, contains a new audit record AUDIT_INTEGRITY_POLICY_RULE to differentiate the IMA policy rules from the IMA-audit messages, addresses two deadlocks due to either loading or searching for crypto algorithms, and cleans up the audit messages" * 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: EVM: fix return value check in evm_write_xattrs() integrity: prevent deadlock during digsig verification. evm: Allow non-SHA1 digital signatures evm: Don't deadlock if a crypto algorithm is unavailable integrity: silence warning when CONFIG_SECURITYFS is not enabled ima: Differentiate auditing policy rules from "audit" actions ima: Do not audit if CONFIG_INTEGRITY_AUDIT is not set ima: Use audit_log_format() rather than audit_log_string() ima: Call audit_log_string() rather than logging it untrusted
2 parents c715ebe + 3dd0f18 commit f91e654

File tree

16 files changed

+128
-47
lines changed

16 files changed

+128
-47
lines changed

crypto/api.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ static struct crypto_alg *crypto_larval_lookup(const char *name, u32 type,
229229
mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
230230

231231
alg = crypto_alg_lookup(name, type, mask);
232-
if (!alg) {
232+
if (!alg && !(mask & CRYPTO_NOLOAD)) {
233233
request_module("crypto-%s", name);
234234

235235
if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask &

include/linux/crypto.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@
112112
*/
113113
#define CRYPTO_ALG_OPTIONAL_KEY 0x00004000
114114

115+
/*
116+
* Don't trigger module loading
117+
*/
118+
#define CRYPTO_NOLOAD 0x00008000
119+
115120
/*
116121
* Transform masks and values (for crt_flags).
117122
*/

include/linux/integrity.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,17 @@ static inline void integrity_load_keys(void)
4444
}
4545
#endif /* CONFIG_INTEGRITY */
4646

47+
#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
48+
49+
extern int integrity_kernel_module_request(char *kmod_name);
50+
51+
#else
52+
53+
static inline int integrity_kernel_module_request(char *kmod_name)
54+
{
55+
return 0;
56+
}
57+
58+
#endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */
59+
4760
#endif /* _LINUX_INTEGRITY_H */

include/uapi/linux/audit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@
148148
#define AUDIT_INTEGRITY_PCR 1804 /* PCR invalidation msgs */
149149
#define AUDIT_INTEGRITY_RULE 1805 /* policy rule */
150150
#define AUDIT_INTEGRITY_EVM_XATTR 1806 /* New EVM-covered xattr */
151+
#define AUDIT_INTEGRITY_POLICY_RULE 1807 /* IMA policy rules */
151152

152153
#define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */
153154

security/integrity/digsig_asymmetric.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,26 @@ int asymmetric_verify(struct key *keyring, const char *sig,
115115
pr_debug("%s() = %d\n", __func__, ret);
116116
return ret;
117117
}
118+
119+
/**
120+
* integrity_kernel_module_request - prevent crypto-pkcs1pad(rsa,*) requests
121+
* @kmod_name: kernel module name
122+
*
123+
* We have situation, when public_key_verify_signature() in case of RSA
124+
* algorithm use alg_name to store internal information in order to
125+
* construct an algorithm on the fly, but crypto_larval_lookup() will try
126+
* to use alg_name in order to load kernel module with same name.
127+
* Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules,
128+
* we are safe to fail such module request from crypto_larval_lookup().
129+
*
130+
* In this way we prevent modprobe execution during digsig verification
131+
* and avoid possible deadlock if modprobe and/or it's dependencies
132+
* also signed with digsig.
133+
*/
134+
int integrity_kernel_module_request(char *kmod_name)
135+
{
136+
if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0)
137+
return -EINVAL;
138+
139+
return 0;
140+
}

security/integrity/evm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ config EVM
44
select ENCRYPTED_KEYS
55
select CRYPTO_HMAC
66
select CRYPTO_SHA1
7+
select CRYPTO_HASH_INFO
78
default n
89
help
910
EVM protects a file's security extended attributes against

security/integrity/evm/evm.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,23 @@ extern struct crypto_shash *hash_tfm;
4747
/* List of EVM protected security xattrs */
4848
extern struct list_head evm_config_xattrnames;
4949

50+
struct evm_digest {
51+
struct ima_digest_data hdr;
52+
char digest[IMA_MAX_DIGEST_SIZE];
53+
} __packed;
54+
5055
int evm_init_key(void);
5156
int evm_update_evmxattr(struct dentry *dentry,
5257
const char *req_xattr_name,
5358
const char *req_xattr_value,
5459
size_t req_xattr_value_len);
5560
int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
5661
const char *req_xattr_value,
57-
size_t req_xattr_value_len, char *digest);
62+
size_t req_xattr_value_len, struct evm_digest *data);
5863
int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
5964
const char *req_xattr_value,
60-
size_t req_xattr_value_len, char type, char *digest);
65+
size_t req_xattr_value_len, char type,
66+
struct evm_digest *data);
6167
int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
6268
char *hmac_val);
6369
int evm_init_secfs(void);

security/integrity/evm/evm_crypto.c

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/evm.h>
2222
#include <keys/encrypted-type.h>
2323
#include <crypto/hash.h>
24+
#include <crypto/hash_info.h>
2425
#include "evm.h"
2526

2627
#define EVMKEY "evm-key"
@@ -29,7 +30,7 @@ static unsigned char evmkey[MAX_KEY_SIZE];
2930
static int evmkey_len = MAX_KEY_SIZE;
3031

3132
struct crypto_shash *hmac_tfm;
32-
struct crypto_shash *hash_tfm;
33+
static struct crypto_shash *evm_tfm[HASH_ALGO__LAST];
3334

3435
static DEFINE_MUTEX(mutex);
3536

@@ -38,7 +39,6 @@ static DEFINE_MUTEX(mutex);
3839
static unsigned long evm_set_key_flags;
3940

4041
static char * const evm_hmac = "hmac(sha1)";
41-
static char * const evm_hash = "sha1";
4242

4343
/**
4444
* evm_set_key() - set EVM HMAC key from the kernel
@@ -74,10 +74,10 @@ int evm_set_key(void *key, size_t keylen)
7474
}
7575
EXPORT_SYMBOL_GPL(evm_set_key);
7676

77-
static struct shash_desc *init_desc(char type)
77+
static struct shash_desc *init_desc(char type, uint8_t hash_algo)
7878
{
7979
long rc;
80-
char *algo;
80+
const char *algo;
8181
struct crypto_shash **tfm;
8282
struct shash_desc *desc;
8383

@@ -89,15 +89,16 @@ static struct shash_desc *init_desc(char type)
8989
tfm = &hmac_tfm;
9090
algo = evm_hmac;
9191
} else {
92-
tfm = &hash_tfm;
93-
algo = evm_hash;
92+
tfm = &evm_tfm[hash_algo];
93+
algo = hash_algo_name[hash_algo];
9494
}
9595

9696
if (*tfm == NULL) {
9797
mutex_lock(&mutex);
9898
if (*tfm)
9999
goto out;
100-
*tfm = crypto_alloc_shash(algo, 0, CRYPTO_ALG_ASYNC);
100+
*tfm = crypto_alloc_shash(algo, 0,
101+
CRYPTO_ALG_ASYNC | CRYPTO_NOLOAD);
101102
if (IS_ERR(*tfm)) {
102103
rc = PTR_ERR(*tfm);
103104
pr_err("Can not allocate %s (reason: %ld)\n", algo, rc);
@@ -186,10 +187,10 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
186187
* each xattr, but attempt to re-use the previously allocated memory.
187188
*/
188189
static int evm_calc_hmac_or_hash(struct dentry *dentry,
189-
const char *req_xattr_name,
190-
const char *req_xattr_value,
191-
size_t req_xattr_value_len,
192-
char type, char *digest)
190+
const char *req_xattr_name,
191+
const char *req_xattr_value,
192+
size_t req_xattr_value_len,
193+
uint8_t type, struct evm_digest *data)
193194
{
194195
struct inode *inode = d_backing_inode(dentry);
195196
struct xattr_list *xattr;
@@ -204,10 +205,12 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
204205
inode->i_sb->s_user_ns != &init_user_ns)
205206
return -EOPNOTSUPP;
206207

207-
desc = init_desc(type);
208+
desc = init_desc(type, data->hdr.algo);
208209
if (IS_ERR(desc))
209210
return PTR_ERR(desc);
210211

212+
data->hdr.length = crypto_shash_digestsize(desc->tfm);
213+
211214
error = -ENODATA;
212215
list_for_each_entry_rcu(xattr, &evm_config_xattrnames, list) {
213216
bool is_ima = false;
@@ -239,7 +242,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
239242
if (is_ima)
240243
ima_present = true;
241244
}
242-
hmac_add_misc(desc, inode, type, digest);
245+
hmac_add_misc(desc, inode, type, data->digest);
243246

244247
/* Portable EVM signatures must include an IMA hash */
245248
if (type == EVM_XATTR_PORTABLE_DIGSIG && !ima_present)
@@ -252,18 +255,18 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
252255

253256
int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
254257
const char *req_xattr_value, size_t req_xattr_value_len,
255-
char *digest)
258+
struct evm_digest *data)
256259
{
257260
return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
258-
req_xattr_value_len, EVM_XATTR_HMAC, digest);
261+
req_xattr_value_len, EVM_XATTR_HMAC, data);
259262
}
260263

261264
int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
262265
const char *req_xattr_value, size_t req_xattr_value_len,
263-
char type, char *digest)
266+
char type, struct evm_digest *data)
264267
{
265268
return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
266-
req_xattr_value_len, type, digest);
269+
req_xattr_value_len, type, data);
267270
}
268271

269272
static int evm_is_immutable(struct dentry *dentry, struct inode *inode)
@@ -303,7 +306,7 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
303306
const char *xattr_value, size_t xattr_value_len)
304307
{
305308
struct inode *inode = d_backing_inode(dentry);
306-
struct evm_ima_xattr_data xattr_data;
309+
struct evm_digest data;
307310
int rc = 0;
308311

309312
/*
@@ -316,13 +319,14 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
316319
if (rc)
317320
return -EPERM;
318321

322+
data.hdr.algo = HASH_ALGO_SHA1;
319323
rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
320-
xattr_value_len, xattr_data.digest);
324+
xattr_value_len, &data);
321325
if (rc == 0) {
322-
xattr_data.type = EVM_XATTR_HMAC;
326+
data.hdr.xattr.sha1.type = EVM_XATTR_HMAC;
323327
rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
324-
&xattr_data,
325-
sizeof(xattr_data), 0);
328+
&data.hdr.xattr.data[1],
329+
SHA1_DIGEST_SIZE + 1, 0);
326330
} else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) {
327331
rc = __vfs_removexattr(dentry, XATTR_NAME_EVM);
328332
}
@@ -334,7 +338,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
334338
{
335339
struct shash_desc *desc;
336340

337-
desc = init_desc(EVM_XATTR_HMAC);
341+
desc = init_desc(EVM_XATTR_HMAC, HASH_ALGO_SHA1);
338342
if (IS_ERR(desc)) {
339343
pr_info("init_desc failed\n");
340344
return PTR_ERR(desc);

security/integrity/evm/evm_main.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/magic.h>
2626

2727
#include <crypto/hash.h>
28+
#include <crypto/hash_info.h>
2829
#include <crypto/algapi.h>
2930
#include "evm.h"
3031

@@ -134,8 +135,9 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
134135
struct integrity_iint_cache *iint)
135136
{
136137
struct evm_ima_xattr_data *xattr_data = NULL;
137-
struct evm_ima_xattr_data calc;
138+
struct signature_v2_hdr *hdr;
138139
enum integrity_status evm_status = INTEGRITY_PASS;
140+
struct evm_digest digest;
139141
struct inode *inode;
140142
int rc, xattr_len;
141143

@@ -171,25 +173,28 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
171173
evm_status = INTEGRITY_FAIL;
172174
goto out;
173175
}
176+
177+
digest.hdr.algo = HASH_ALGO_SHA1;
174178
rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
175-
xattr_value_len, calc.digest);
179+
xattr_value_len, &digest);
176180
if (rc)
177181
break;
178-
rc = crypto_memneq(xattr_data->digest, calc.digest,
179-
sizeof(calc.digest));
182+
rc = crypto_memneq(xattr_data->digest, digest.digest,
183+
SHA1_DIGEST_SIZE);
180184
if (rc)
181185
rc = -EINVAL;
182186
break;
183187
case EVM_IMA_XATTR_DIGSIG:
184188
case EVM_XATTR_PORTABLE_DIGSIG:
189+
hdr = (struct signature_v2_hdr *)xattr_data;
190+
digest.hdr.algo = hdr->hash_algo;
185191
rc = evm_calc_hash(dentry, xattr_name, xattr_value,
186-
xattr_value_len, xattr_data->type,
187-
calc.digest);
192+
xattr_value_len, xattr_data->type, &digest);
188193
if (rc)
189194
break;
190195
rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
191196
(const char *)xattr_data, xattr_len,
192-
calc.digest, sizeof(calc.digest));
197+
digest.digest, digest.hdr.length);
193198
if (!rc) {
194199
inode = d_backing_inode(dentry);
195200

security/integrity/evm/evm_secfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ static ssize_t evm_write_xattrs(struct file *file, const char __user *buf,
193193
return -E2BIG;
194194

195195
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_EVM_XATTR);
196-
if (IS_ERR(ab))
197-
return PTR_ERR(ab);
196+
if (!ab)
197+
return -ENOMEM;
198198

199199
xattr = kmalloc(sizeof(struct xattr_list), GFP_KERNEL);
200200
if (!xattr) {

security/integrity/iint.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,13 @@ static int __init integrity_fs_init(void)
219219
{
220220
integrity_dir = securityfs_create_dir("integrity", NULL);
221221
if (IS_ERR(integrity_dir)) {
222-
pr_err("Unable to create integrity sysfs dir: %ld\n",
223-
PTR_ERR(integrity_dir));
222+
int ret = PTR_ERR(integrity_dir);
223+
224+
if (ret != -ENODEV)
225+
pr_err("Unable to create integrity sysfs dir: %d\n",
226+
ret);
224227
integrity_dir = NULL;
225-
return PTR_ERR(integrity_dir);
228+
return ret;
226229
}
227230

228231
return 0;

security/integrity/ima/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ config IMA
1212
select TCG_TIS if TCG_TPM && X86
1313
select TCG_CRB if TCG_TPM && ACPI
1414
select TCG_IBMVTPM if TCG_TPM && PPC_PSERIES
15+
select INTEGRITY_AUDIT if AUDIT
1516
help
1617
The Trusted Computing Group(TCG) runtime Integrity
1718
Measurement Architecture(IMA) maintains a list of hash

security/integrity/ima/ima_policy.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -657,14 +657,16 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry,
657657
static void ima_log_string_op(struct audit_buffer *ab, char *key, char *value,
658658
bool (*rule_operator)(kuid_t, kuid_t))
659659
{
660+
if (!ab)
661+
return;
662+
660663
if (rule_operator == &uid_gt)
661664
audit_log_format(ab, "%s>", key);
662665
else if (rule_operator == &uid_lt)
663666
audit_log_format(ab, "%s<", key);
664667
else
665668
audit_log_format(ab, "%s=", key);
666-
audit_log_untrustedstring(ab, value);
667-
audit_log_format(ab, " ");
669+
audit_log_format(ab, "%s ", value);
668670
}
669671
static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
670672
{
@@ -679,7 +681,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
679681
bool uid_token;
680682
int result = 0;
681683

682-
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE);
684+
ab = integrity_audit_log_start(audit_context(), GFP_KERNEL,
685+
AUDIT_INTEGRITY_POLICY_RULE);
683686

684687
entry->uid = INVALID_UID;
685688
entry->fowner = INVALID_UID;

0 commit comments

Comments
 (0)