Skip to content

Commit aef4892

Browse files
committed
Merge tag 'integrity-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity
Pull integrity subsystem updates from Mimi Zohar: - Limit the allowed hash algorithms when writing security.ima xattrs or verifying them, based on the IMA policy and the configured hash algorithms. - Return the calculated "critical data" measurement hash and size to avoid code duplication. (Preparatory change for a proposed LSM.) - and a single patch to address a compiler warning. * tag 'integrity-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity: IMA: reject unknown hash algorithms in ima_get_hash_algo IMA: prevent SETXATTR_CHECK policy rules with unavailable algorithms IMA: introduce a new policy option func=SETXATTR_CHECK IMA: add a policy option to restrict xattr hash algorithms on appraisal IMA: add support to restrict the hash algorithms used for file appraisal IMA: block writes of the security.ima xattr with unsupported algorithms IMA: remove the dependency on CRYPTO_MD5 ima: Add digest and digest_len params to the functions to measure a buffer ima: Return int in the functions to measure a buffer ima: Introduce ima_get_current_hash_algo() IMA: remove -Wmissing-prototypes warning
2 parents b55060d + cb181da commit aef4892

14 files changed

Lines changed: 352 additions & 76 deletions

File tree

Documentation/ABI/testing/ima_policy

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@ Description:
2727
lsm: [[subj_user=] [subj_role=] [subj_type=]
2828
[obj_user=] [obj_role=] [obj_type=]]
2929
option: [[appraise_type=]] [template=] [permit_directio]
30-
[appraise_flag=] [keyrings=]
30+
[appraise_flag=] [appraise_algos=] [keyrings=]
3131
base:
3232
func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
33-
[FIRMWARE_CHECK]
33+
[FIRMWARE_CHECK]
3434
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
3535
[KEXEC_CMDLINE] [KEY_CHECK] [CRITICAL_DATA]
36+
[SETXATTR_CHECK]
3637
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
3738
[[^]MAY_EXEC]
3839
fsmagic:= hex value
@@ -55,6 +56,10 @@ Description:
5556
label:= [selinux]|[kernel_info]|[data_label]
5657
data_label:= a unique string used for grouping and limiting critical data.
5758
For example, "selinux" to measure critical data for SELinux.
59+
appraise_algos:= comma-separated list of hash algorithms
60+
For example, "sha256,sha512" to only accept to appraise
61+
files where the security.ima xattr was hashed with one
62+
of these two algorithms.
5863

5964
default policy:
6065
# PROC_SUPER_MAGIC
@@ -134,3 +139,9 @@ Description:
134139
keys added to .builtin_trusted_keys or .ima keyring:
135140

136141
measure func=KEY_CHECK keyrings=.builtin_trusted_keys|.ima
142+
143+
Example of the special SETXATTR_CHECK appraise rule, that
144+
restricts the hash algorithms allowed when writing to the
145+
security.ima xattr of a file:
146+
147+
appraise func=SETXATTR_CHECK appraise_algos=sha256,sha384,sha512

drivers/md/dm-ima.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ static void dm_ima_measure_data(const char *event_name, const void *buf, size_t
136136
if (noio)
137137
noio_flag = memalloc_noio_save();
138138

139-
ima_measure_critical_data(DM_NAME, event_name, buf, buf_len, false);
139+
ima_measure_critical_data(DM_NAME, event_name, buf, buf_len,
140+
false, NULL, 0);
140141

141142
if (noio)
142143
memalloc_noio_restore(noio_flag);

include/linux/ima.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
#include <linux/fs.h>
1212
#include <linux/security.h>
1313
#include <linux/kexec.h>
14+
#include <crypto/hash_info.h>
1415
struct linux_binprm;
1516

1617
#ifdef CONFIG_IMA
18+
extern enum hash_algo ima_get_current_hash_algo(void);
1719
extern int ima_bprm_check(struct linux_binprm *bprm);
1820
extern int ima_file_check(struct file *file, int mask);
1921
extern void ima_post_create_tmpfile(struct user_namespace *mnt_userns,
@@ -33,10 +35,10 @@ extern void ima_post_path_mknod(struct user_namespace *mnt_userns,
3335
extern int ima_file_hash(struct file *file, char *buf, size_t buf_size);
3436
extern int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size);
3537
extern void ima_kexec_cmdline(int kernel_fd, const void *buf, int size);
36-
extern void ima_measure_critical_data(const char *event_label,
37-
const char *event_name,
38-
const void *buf, size_t buf_len,
39-
bool hash);
38+
extern int ima_measure_critical_data(const char *event_label,
39+
const char *event_name,
40+
const void *buf, size_t buf_len,
41+
bool hash, u8 *digest, size_t digest_len);
4042

4143
#ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
4244
extern void ima_appraise_parse_cmdline(void);
@@ -64,6 +66,11 @@ static inline const char * const *arch_get_ima_policy(void)
6466
#endif
6567

6668
#else
69+
static inline enum hash_algo ima_get_current_hash_algo(void)
70+
{
71+
return HASH_ALGO__LAST;
72+
}
73+
6774
static inline int ima_bprm_check(struct linux_binprm *bprm)
6875
{
6976
return 0;
@@ -137,10 +144,14 @@ static inline int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size
137144

138145
static inline void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) {}
139146

140-
static inline void ima_measure_critical_data(const char *event_label,
147+
static inline int ima_measure_critical_data(const char *event_label,
141148
const char *event_name,
142149
const void *buf, size_t buf_len,
143-
bool hash) {}
150+
bool hash, u8 *digest,
151+
size_t digest_len)
152+
{
153+
return -ENOENT;
154+
}
144155

145156
#endif /* CONFIG_IMA */
146157

security/integrity/ima/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ config IMA
66
select SECURITYFS
77
select CRYPTO
88
select CRYPTO_HMAC
9-
select CRYPTO_MD5
109
select CRYPTO_SHA1
1110
select CRYPTO_HASH_INFO
1211
select TCG_TPM if HAS_IOMEM && !UML

security/integrity/ima/ima.h

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,11 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };
4646
/* current content of the policy */
4747
extern int ima_policy_flag;
4848

49+
/* bitset of digests algorithms allowed in the setxattr hook */
50+
extern atomic_t ima_setxattr_allowed_hash_algorithms;
51+
4952
/* set during initialization */
50-
extern int ima_hash_algo;
53+
extern int ima_hash_algo __ro_after_init;
5154
extern int ima_sha1_idx __ro_after_init;
5255
extern int ima_hash_algo_idx __ro_after_init;
5356
extern int ima_extra_slots __ro_after_init;
@@ -198,6 +201,7 @@ static inline unsigned int ima_hash_key(u8 *digest)
198201
hook(KEXEC_CMDLINE, kexec_cmdline) \
199202
hook(KEY_CHECK, key) \
200203
hook(CRITICAL_DATA, critical_data) \
204+
hook(SETXATTR_CHECK, setxattr_check) \
201205
hook(MAX_CHECK, none)
202206

203207
#define __ima_hook_enumify(ENUM, str) ENUM,
@@ -254,7 +258,7 @@ int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
254258
const struct cred *cred, u32 secid, int mask,
255259
enum ima_hooks func, int *pcr,
256260
struct ima_template_desc **template_desc,
257-
const char *func_data);
261+
const char *func_data, unsigned int *allowed_algos);
258262
int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
259263
int ima_collect_measurement(struct integrity_iint_cache *iint,
260264
struct file *file, void *buf, loff_t size,
@@ -264,11 +268,11 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
264268
struct evm_ima_xattr_data *xattr_value,
265269
int xattr_len, const struct modsig *modsig, int pcr,
266270
struct ima_template_desc *template_desc);
267-
void process_buffer_measurement(struct user_namespace *mnt_userns,
268-
struct inode *inode, const void *buf, int size,
269-
const char *eventname, enum ima_hooks func,
270-
int pcr, const char *func_data,
271-
bool buf_hash);
271+
int process_buffer_measurement(struct user_namespace *mnt_userns,
272+
struct inode *inode, const void *buf, int size,
273+
const char *eventname, enum ima_hooks func,
274+
int pcr, const char *func_data,
275+
bool buf_hash, u8 *digest, size_t digest_len);
272276
void ima_audit_measurement(struct integrity_iint_cache *iint,
273277
const unsigned char *filename);
274278
int ima_alloc_init_template(struct ima_event_data *event_data,
@@ -285,10 +289,10 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
285289
const struct cred *cred, u32 secid, enum ima_hooks func,
286290
int mask, int flags, int *pcr,
287291
struct ima_template_desc **template_desc,
288-
const char *func_data);
292+
const char *func_data, unsigned int *allowed_algos);
289293
void ima_init_policy(void);
290294
void ima_update_policy(void);
291-
void ima_update_policy_flag(void);
295+
void ima_update_policy_flags(void);
292296
ssize_t ima_parse_add_rule(char *);
293297
void ima_delete_rules(void);
294298
int ima_check_policy(void);
@@ -319,7 +323,7 @@ int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
319323
void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
320324
enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
321325
enum ima_hooks func);
322-
enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
326+
enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value,
323327
int xattr_len);
324328
int ima_read_xattr(struct dentry *dentry,
325329
struct evm_ima_xattr_data **xattr_value);

security/integrity/ima/ima_api.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
172172
* @pcr: pointer filled in if matched measure policy sets pcr=
173173
* @template_desc: pointer filled in if matched measure policy sets template=
174174
* @func_data: func specific data, may be NULL
175+
* @allowed_algos: allowlist of hash algorithms for the IMA xattr
175176
*
176177
* The policy is defined in terms of keypairs:
177178
* subj=, obj=, type=, func=, mask=, fsmagic=
@@ -188,14 +189,15 @@ int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
188189
const struct cred *cred, u32 secid, int mask,
189190
enum ima_hooks func, int *pcr,
190191
struct ima_template_desc **template_desc,
191-
const char *func_data)
192+
const char *func_data, unsigned int *allowed_algos)
192193
{
193194
int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
194195

195196
flags &= ima_policy_flag;
196197

197198
return ima_match_policy(mnt_userns, inode, cred, secid, func, mask,
198-
flags, pcr, template_desc, func_data);
199+
flags, pcr, template_desc, func_data,
200+
allowed_algos);
199201
}
200202

201203
/*

security/integrity/ima/ima_appraise.c

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,9 @@ int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
7777
return 0;
7878

7979
security_task_getsecid_subj(current, &secid);
80-
return ima_match_policy(mnt_userns, inode, current_cred(), secid, func,
81-
mask, IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL);
80+
return ima_match_policy(mnt_userns, inode, current_cred(), secid,
81+
func, mask, IMA_APPRAISE | IMA_HASH, NULL,
82+
NULL, NULL, NULL);
8283
}
8384

8485
static int ima_fix_xattr(struct dentry *dentry,
@@ -171,7 +172,7 @@ static void ima_cache_flags(struct integrity_iint_cache *iint,
171172
}
172173
}
173174

174-
enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
175+
enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value,
175176
int xattr_len)
176177
{
177178
struct signature_v2_hdr *sig;
@@ -184,7 +185,8 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
184185
switch (xattr_value->type) {
185186
case EVM_IMA_XATTR_DIGSIG:
186187
sig = (typeof(sig))xattr_value;
187-
if (sig->version != 2 || xattr_len <= sizeof(*sig))
188+
if (sig->version != 2 || xattr_len <= sizeof(*sig)
189+
|| sig->hash_algo >= HASH_ALGO__LAST)
188190
return ima_hash_algo;
189191
return sig->hash_algo;
190192
break;
@@ -357,7 +359,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint,
357359
if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
358360
process_buffer_measurement(&init_user_ns, NULL, digest, digestsize,
359361
"blacklisted-hash", NONE,
360-
pcr, NULL, false);
362+
pcr, NULL, false, NULL, 0);
361363
}
362364

363365
return rc;
@@ -575,6 +577,66 @@ static void ima_reset_appraise_flags(struct inode *inode, int digsig)
575577
clear_bit(IMA_DIGSIG, &iint->atomic_flags);
576578
}
577579

580+
/**
581+
* validate_hash_algo() - Block setxattr with unsupported hash algorithms
582+
* @dentry: object of the setxattr()
583+
* @xattr_value: userland supplied xattr value
584+
* @xattr_value_len: length of xattr_value
585+
*
586+
* The xattr value is mapped to its hash algorithm, and this algorithm
587+
* must be built in the kernel for the setxattr to be allowed.
588+
*
589+
* Emit an audit message when the algorithm is invalid.
590+
*
591+
* Return: 0 on success, else an error.
592+
*/
593+
static int validate_hash_algo(struct dentry *dentry,
594+
const struct evm_ima_xattr_data *xattr_value,
595+
size_t xattr_value_len)
596+
{
597+
char *path = NULL, *pathbuf = NULL;
598+
enum hash_algo xattr_hash_algo;
599+
const char *errmsg = "unavailable-hash-algorithm";
600+
unsigned int allowed_hashes;
601+
602+
xattr_hash_algo = ima_get_hash_algo(xattr_value, xattr_value_len);
603+
604+
allowed_hashes = atomic_read(&ima_setxattr_allowed_hash_algorithms);
605+
606+
if (allowed_hashes) {
607+
/* success if the algorithm is allowed in the ima policy */
608+
if (allowed_hashes & (1U << xattr_hash_algo))
609+
return 0;
610+
611+
/*
612+
* We use a different audit message when the hash algorithm
613+
* is denied by a policy rule, instead of not being built
614+
* in the kernel image
615+
*/
616+
errmsg = "denied-hash-algorithm";
617+
} else {
618+
if (likely(xattr_hash_algo == ima_hash_algo))
619+
return 0;
620+
621+
/* allow any xattr using an algorithm built in the kernel */
622+
if (crypto_has_alg(hash_algo_name[xattr_hash_algo], 0, 0))
623+
return 0;
624+
}
625+
626+
pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
627+
if (!pathbuf)
628+
return -EACCES;
629+
630+
path = dentry_path(dentry, pathbuf, PATH_MAX);
631+
632+
integrity_audit_msg(AUDIT_INTEGRITY_DATA, d_inode(dentry), path,
633+
"set_data", errmsg, -EACCES, 0);
634+
635+
kfree(pathbuf);
636+
637+
return -EACCES;
638+
}
639+
578640
int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
579641
const void *xattr_value, size_t xattr_value_len)
580642
{
@@ -592,9 +654,11 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
592654
digsig = (xvalue->type == EVM_XATTR_PORTABLE_DIGSIG);
593655
}
594656
if (result == 1 || evm_revalidate_status(xattr_name)) {
657+
result = validate_hash_algo(dentry, xvalue, xattr_value_len);
658+
if (result)
659+
return result;
660+
595661
ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
596-
if (result == 1)
597-
result = 0;
598662
}
599663
return result;
600664
}

security/integrity/ima/ima_asymmetric_keys.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,5 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
6262
*/
6363
process_buffer_measurement(&init_user_ns, NULL, payload, payload_len,
6464
keyring->description, KEY_CHECK, 0,
65-
keyring->description, false);
65+
keyring->description, false, NULL, 0);
6666
}

security/integrity/ima/ima_init.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ int __init ima_init(void)
154154
ima_init_key_queue();
155155

156156
ima_measure_critical_data("kernel_info", "kernel_version",
157-
UTS_RELEASE, strlen(UTS_RELEASE), false);
157+
UTS_RELEASE, strlen(UTS_RELEASE), false,
158+
NULL, 0);
158159

159160
return rc;
160161
}

0 commit comments

Comments
 (0)