Skip to content

Commit 4cec929

Browse files
committed
Merge tag 'integrity-v5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity
Pull integrity updates from Mimi Zohar: "The nicest change is the IMA policy rule checking. The other changes include allowing the kexec boot cmdline line measure policy rules to be defined in terms of the inode associated with the kexec kernel image, making the IMA_APPRAISE_BOOTPARAM, which governs the IMA appraise mode (log, fix, enforce), a runtime decision based on the secure boot mode of the system, and including errno in the audit log" * tag 'integrity-v5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity: integrity: remove redundant initialization of variable ret ima: move APPRAISE_BOOTPARAM dependency on ARCH_POLICY to runtime ima: AppArmor satisfies the audit rule requirements ima: Rename internal filter rule functions ima: Support additional conditionals in the KEXEC_CMDLINE hook function ima: Use the common function to detect LSM conditionals in a rule ima: Move comprehensive rule validation checks out of the token parser ima: Use correct type for the args_p member of ima_rule_entry.lsm elements ima: Shallow copy the args_p member of ima_rule_entry.lsm elements ima: Fail rule parsing when appraise_flag=blacklist is unsupportable ima: Fail rule parsing when the KEY_CHECK hook is combined with an invalid cond ima: Fail rule parsing when the KEXEC_CMDLINE hook is combined with an invalid cond ima: Fail rule parsing when buffer hook functions have an invalid action ima: Free the entire rule if it fails to parse ima: Free the entire rule when deleting a list of rules ima: Have the LSM free its audit rule IMA: Add audit log for failure conditions integrity: Add errno field in audit message
2 parents e3243e2 + 3db0d0c commit 4cec929

File tree

14 files changed

+286
-143
lines changed

14 files changed

+286
-143
lines changed

include/linux/ima.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
2525
enum kernel_read_file_id id);
2626
extern void ima_post_path_mknod(struct dentry *dentry);
2727
extern int ima_file_hash(struct file *file, char *buf, size_t buf_size);
28-
extern void ima_kexec_cmdline(const void *buf, int size);
28+
extern void ima_kexec_cmdline(int kernel_fd, const void *buf, int size);
2929

3030
#ifdef CONFIG_IMA_KEXEC
3131
extern void ima_add_kexec_buffer(struct kimage *image);
@@ -103,7 +103,7 @@ static inline int ima_file_hash(struct file *file, char *buf, size_t buf_size)
103103
return -EOPNOTSUPP;
104104
}
105105

106-
static inline void ima_kexec_cmdline(const void *buf, int size) {}
106+
static inline void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) {}
107107
#endif /* CONFIG_IMA */
108108

109109
#ifndef CONFIG_IMA_KEXEC

kernel/kexec_file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
265265
goto out;
266266
}
267267

268-
ima_kexec_cmdline(image->cmdline_buf,
268+
ima_kexec_cmdline(kernel_fd, image->cmdline_buf,
269269
image->cmdline_buf_len - 1);
270270
}
271271

security/integrity/digsig_asymmetric.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ int asymmetric_verify(struct key *keyring, const char *sig,
7979
struct public_key_signature pks;
8080
struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
8181
struct key *key;
82-
int ret = -ENOMEM;
82+
int ret;
8383

8484
if (siglen <= sizeof(*hdr))
8585
return -EBADMSG;

security/integrity/ima/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ config IMA_MEASURE_PCR_IDX
5454

5555
config IMA_LSM_RULES
5656
bool
57-
depends on IMA && AUDIT && (SECURITY_SELINUX || SECURITY_SMACK)
57+
depends on IMA && AUDIT && (SECURITY_SELINUX || SECURITY_SMACK || SECURITY_APPARMOR)
5858
default y
5959
help
6060
Disabling this option will disregard LSM based policy rules.
@@ -232,7 +232,7 @@ config IMA_APPRAISE_REQUIRE_POLICY_SIGS
232232

233233
config IMA_APPRAISE_BOOTPARAM
234234
bool "ima_appraise boot parameter"
235-
depends on IMA_APPRAISE && !IMA_ARCH_POLICY
235+
depends on IMA_APPRAISE
236236
default y
237237
help
238238
This option enables the different "ima_appraise=" modes

security/integrity/ima/ima.h

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -186,27 +186,43 @@ static inline unsigned int ima_hash_key(u8 *digest)
186186
return (digest[0] | digest[1] << 8) % IMA_MEASURE_HTABLE_SIZE;
187187
}
188188

189-
#define __ima_hooks(hook) \
190-
hook(NONE) \
191-
hook(FILE_CHECK) \
192-
hook(MMAP_CHECK) \
193-
hook(BPRM_CHECK) \
194-
hook(CREDS_CHECK) \
195-
hook(POST_SETATTR) \
196-
hook(MODULE_CHECK) \
197-
hook(FIRMWARE_CHECK) \
198-
hook(KEXEC_KERNEL_CHECK) \
199-
hook(KEXEC_INITRAMFS_CHECK) \
200-
hook(POLICY_CHECK) \
201-
hook(KEXEC_CMDLINE) \
202-
hook(KEY_CHECK) \
203-
hook(MAX_CHECK)
204-
#define __ima_hook_enumify(ENUM) ENUM,
189+
#define __ima_hooks(hook) \
190+
hook(NONE, none) \
191+
hook(FILE_CHECK, file) \
192+
hook(MMAP_CHECK, mmap) \
193+
hook(BPRM_CHECK, bprm) \
194+
hook(CREDS_CHECK, creds) \
195+
hook(POST_SETATTR, post_setattr) \
196+
hook(MODULE_CHECK, module) \
197+
hook(FIRMWARE_CHECK, firmware) \
198+
hook(KEXEC_KERNEL_CHECK, kexec_kernel) \
199+
hook(KEXEC_INITRAMFS_CHECK, kexec_initramfs) \
200+
hook(POLICY_CHECK, policy) \
201+
hook(KEXEC_CMDLINE, kexec_cmdline) \
202+
hook(KEY_CHECK, key) \
203+
hook(MAX_CHECK, none)
204+
205+
#define __ima_hook_enumify(ENUM, str) ENUM,
206+
#define __ima_stringify(arg) (#arg)
207+
#define __ima_hook_measuring_stringify(ENUM, str) \
208+
(__ima_stringify(measuring_ ##str)),
205209

206210
enum ima_hooks {
207211
__ima_hooks(__ima_hook_enumify)
208212
};
209213

214+
static const char * const ima_hooks_measure_str[] = {
215+
__ima_hooks(__ima_hook_measuring_stringify)
216+
};
217+
218+
static inline const char *func_measure_str(enum ima_hooks func)
219+
{
220+
if (func >= MAX_CHECK)
221+
return ima_hooks_measure_str[NONE];
222+
223+
return ima_hooks_measure_str[func];
224+
}
225+
210226
extern const char *const func_tokens[];
211227

212228
struct modsig;
@@ -249,7 +265,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
249265
struct evm_ima_xattr_data *xattr_value,
250266
int xattr_len, const struct modsig *modsig, int pcr,
251267
struct ima_template_desc *template_desc);
252-
void process_buffer_measurement(const void *buf, int size,
268+
void process_buffer_measurement(struct inode *inode, const void *buf, int size,
253269
const char *eventname, enum ima_hooks func,
254270
int pcr, const char *keyring);
255271
void ima_audit_measurement(struct integrity_iint_cache *iint,
@@ -356,7 +372,6 @@ static inline int ima_read_xattr(struct dentry *dentry,
356372
#endif /* CONFIG_IMA_APPRAISE */
357373

358374
#ifdef CONFIG_IMA_APPRAISE_MODSIG
359-
bool ima_hook_supports_modsig(enum ima_hooks func);
360375
int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
361376
struct modsig **modsig);
362377
void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size);
@@ -366,11 +381,6 @@ int ima_get_raw_modsig(const struct modsig *modsig, const void **data,
366381
u32 *data_len);
367382
void ima_free_modsig(struct modsig *modsig);
368383
#else
369-
static inline bool ima_hook_supports_modsig(enum ima_hooks func)
370-
{
371-
return false;
372-
}
373-
374384
static inline int ima_read_modsig(enum ima_hooks func, const void *buf,
375385
loff_t buf_len, struct modsig **modsig)
376386
{
@@ -403,19 +413,24 @@ static inline void ima_free_modsig(struct modsig *modsig)
403413
/* LSM based policy rules require audit */
404414
#ifdef CONFIG_IMA_LSM_RULES
405415

406-
#define security_filter_rule_init security_audit_rule_init
407-
#define security_filter_rule_match security_audit_rule_match
416+
#define ima_filter_rule_init security_audit_rule_init
417+
#define ima_filter_rule_free security_audit_rule_free
418+
#define ima_filter_rule_match security_audit_rule_match
408419

409420
#else
410421

411-
static inline int security_filter_rule_init(u32 field, u32 op, char *rulestr,
412-
void **lsmrule)
422+
static inline int ima_filter_rule_init(u32 field, u32 op, char *rulestr,
423+
void **lsmrule)
413424
{
414425
return -EINVAL;
415426
}
416427

417-
static inline int security_filter_rule_match(u32 secid, u32 field, u32 op,
418-
void *lsmrule)
428+
static inline void ima_filter_rule_free(void *lsmrule)
429+
{
430+
}
431+
432+
static inline int ima_filter_rule_match(u32 secid, u32 field, u32 op,
433+
void *lsmrule)
419434
{
420435
return -EINVAL;
421436
}

security/integrity/ima/ima_api.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
162162

163163
/**
164164
* ima_get_action - appraise & measure decision based on policy.
165-
* @inode: pointer to inode to measure
165+
* @inode: pointer to the inode associated with the object being validated
166166
* @cred: pointer to credentials structure to validate
167167
* @secid: secid of the task being validated
168168
* @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXEC,

security/integrity/ima/ima_appraise.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
static int __init default_appraise_setup(char *str)
2020
{
2121
#ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
22+
if (arch_ima_get_secureboot()) {
23+
pr_info("Secure boot enabled: ignoring ima_appraise=%s boot parameter option",
24+
str);
25+
return 1;
26+
}
27+
2228
if (strncmp(str, "off", 3) == 0)
2329
ima_appraise = 0;
2430
else if (strncmp(str, "log", 3) == 0)
@@ -328,7 +334,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint,
328334

329335
rc = is_binary_blacklisted(digest, digestsize);
330336
if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
331-
process_buffer_measurement(digest, digestsize,
337+
process_buffer_measurement(NULL, digest, digestsize,
332338
"blacklisted-hash", NONE,
333339
pcr, NULL);
334340
}

security/integrity/ima/ima_asymmetric_keys.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
5858
* if the IMA policy is configured to measure a key linked
5959
* to the given keyring.
6060
*/
61-
process_buffer_measurement(payload, payload_len,
61+
process_buffer_measurement(NULL, payload, payload_len,
6262
keyring->description, KEY_CHECK, 0,
6363
keyring->description);
6464
}

security/integrity/ima/ima_main.c

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,7 @@ int ima_load_data(enum kernel_load_data_id id)
726726

727727
/*
728728
* process_buffer_measurement - Measure the buffer to ima log.
729+
* @inode: inode associated with the object being measured (NULL for KEY_CHECK)
729730
* @buf: pointer to the buffer that needs to be added to the log.
730731
* @size: size of buffer(in bytes).
731732
* @eventname: event name to be used for the buffer entry.
@@ -735,11 +736,12 @@ int ima_load_data(enum kernel_load_data_id id)
735736
*
736737
* Based on policy, the buffer is measured into the ima log.
737738
*/
738-
void process_buffer_measurement(const void *buf, int size,
739+
void process_buffer_measurement(struct inode *inode, const void *buf, int size,
739740
const char *eventname, enum ima_hooks func,
740741
int pcr, const char *keyring)
741742
{
742743
int ret = 0;
744+
const char *audit_cause = "ENOMEM";
743745
struct ima_template_entry *entry = NULL;
744746
struct integrity_iint_cache iint = {};
745747
struct ima_event_data event_data = {.iint = &iint,
@@ -767,7 +769,7 @@ void process_buffer_measurement(const void *buf, int size,
767769
*/
768770
if (func) {
769771
security_task_getsecid(current, &secid);
770-
action = ima_get_action(NULL, current_cred(), secid, 0, func,
772+
action = ima_get_action(inode, current_cred(), secid, 0, func,
771773
&pcr, &template, keyring);
772774
if (!(action & IMA_MEASURE))
773775
return;
@@ -794,37 +796,54 @@ void process_buffer_measurement(const void *buf, int size,
794796
iint.ima_hash->length = hash_digest_size[ima_hash_algo];
795797

796798
ret = ima_calc_buffer_hash(buf, size, iint.ima_hash);
797-
if (ret < 0)
799+
if (ret < 0) {
800+
audit_cause = "hashing_error";
798801
goto out;
802+
}
799803

800804
ret = ima_alloc_init_template(&event_data, &entry, template);
801-
if (ret < 0)
805+
if (ret < 0) {
806+
audit_cause = "alloc_entry";
802807
goto out;
808+
}
803809

804810
ret = ima_store_template(entry, violation, NULL, buf, pcr);
805-
806-
if (ret < 0)
811+
if (ret < 0) {
812+
audit_cause = "store_entry";
807813
ima_free_template_entry(entry);
814+
}
808815

809816
out:
810817
if (ret < 0)
811-
pr_devel("%s: failed, result: %d\n", __func__, ret);
818+
integrity_audit_message(AUDIT_INTEGRITY_PCR, NULL, eventname,
819+
func_measure_str(func),
820+
audit_cause, ret, 0, ret);
812821

813822
return;
814823
}
815824

816825
/**
817826
* ima_kexec_cmdline - measure kexec cmdline boot args
827+
* @kernel_fd: file descriptor of the kexec kernel being loaded
818828
* @buf: pointer to buffer
819829
* @size: size of buffer
820830
*
821831
* Buffers can only be measured, not appraised.
822832
*/
823-
void ima_kexec_cmdline(const void *buf, int size)
833+
void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
824834
{
825-
if (buf && size != 0)
826-
process_buffer_measurement(buf, size, "kexec-cmdline",
827-
KEXEC_CMDLINE, 0, NULL);
835+
struct fd f;
836+
837+
if (!buf || !size)
838+
return;
839+
840+
f = fdget(kernel_fd);
841+
if (!f.file)
842+
return;
843+
844+
process_buffer_measurement(file_inode(f.file), buf, size,
845+
"kexec-cmdline", KEXEC_CMDLINE, 0, NULL);
846+
fdput(f);
828847
}
829848

830849
static int __init init_ima(void)

security/integrity/ima/ima_modsig.c

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,6 @@ struct modsig {
3232
u8 raw_pkcs7[];
3333
};
3434

35-
/**
36-
* ima_hook_supports_modsig - can the policy allow modsig for this hook?
37-
*
38-
* modsig is only supported by hooks using ima_post_read_file(), because only
39-
* they preload the contents of the file in a buffer. FILE_CHECK does that in
40-
* some cases, but not when reached from vfs_open(). POLICY_CHECK can support
41-
* it, but it's not useful in practice because it's a text file so deny.
42-
*/
43-
bool ima_hook_supports_modsig(enum ima_hooks func)
44-
{
45-
switch (func) {
46-
case KEXEC_KERNEL_CHECK:
47-
case KEXEC_INITRAMFS_CHECK:
48-
case MODULE_CHECK:
49-
return true;
50-
default:
51-
return false;
52-
}
53-
}
54-
5535
/*
5636
* ima_read_modsig - Read modsig from buf.
5737
*

0 commit comments

Comments
 (0)