Skip to content

Commit 4834177

Browse files
tyhicksmimizohar
authored andcommitted
ima: Support additional conditionals in the KEXEC_CMDLINE hook function
Take the properties of the kexec kernel's inode and the current task ownership into consideration when matching a KEXEC_CMDLINE operation to the rules in the IMA policy. This allows for some uniformity when writing IMA policy rules for KEXEC_KERNEL_CHECK, KEXEC_INITRAMFS_CHECK, and KEXEC_CMDLINE operations. Prior to this patch, it was not possible to write a set of rules like this: dont_measure func=KEXEC_KERNEL_CHECK obj_type=foo_t dont_measure func=KEXEC_INITRAMFS_CHECK obj_type=foo_t dont_measure func=KEXEC_CMDLINE obj_type=foo_t measure func=KEXEC_KERNEL_CHECK measure func=KEXEC_INITRAMFS_CHECK measure func=KEXEC_CMDLINE The inode information associated with the kernel being loaded by a kexec_kernel_load(2) syscall can now be included in the decision to measure or not Additonally, the uid, euid, and subj_* conditionals can also now be used in KEXEC_CMDLINE rules. There was no technical reason as to why those conditionals weren't being considered previously other than ima_match_rules() didn't have a valid inode to use so it immediately bailed out for KEXEC_CMDLINE operations rather than going through the full list of conditional comparisons. Signed-off-by: Tyler Hicks <[email protected]> Cc: Eric Biederman <[email protected]> Cc: [email protected] Reviewed-by: Lakshmi Ramasubramanian <[email protected]> Signed-off-by: Mimi Zohar <[email protected]>
1 parent 592b24c commit 4834177

File tree

9 files changed

+31
-25
lines changed

9 files changed

+31
-25
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
@@ -287,7 +287,7 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
287287
goto out;
288288
}
289289

290-
ima_kexec_cmdline(image->cmdline_buf,
290+
ima_kexec_cmdline(kernel_fd, image->cmdline_buf,
291291
image->cmdline_buf_len - 1);
292292
}
293293

security/integrity/ima/ima.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
265265
struct evm_ima_xattr_data *xattr_value,
266266
int xattr_len, const struct modsig *modsig, int pcr,
267267
struct ima_template_desc *template_desc);
268-
void process_buffer_measurement(const void *buf, int size,
268+
void process_buffer_measurement(struct inode *inode, const void *buf, int size,
269269
const char *eventname, enum ima_hooks func,
270270
int pcr, const char *keyring);
271271
void ima_audit_measurement(struct integrity_iint_cache *iint,

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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint,
328328

329329
rc = is_binary_blacklisted(digest, digestsize);
330330
if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
331-
process_buffer_measurement(digest, digestsize,
331+
process_buffer_measurement(NULL, digest, digestsize,
332332
"blacklisted-hash", NONE,
333333
pcr, NULL);
334334
}

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: 17 additions & 6 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,7 +736,7 @@ 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
{
@@ -768,7 +769,7 @@ void process_buffer_measurement(const void *buf, int size,
768769
*/
769770
if (func) {
770771
security_task_getsecid(current, &secid);
771-
action = ima_get_action(NULL, current_cred(), secid, 0, func,
772+
action = ima_get_action(inode, current_cred(), secid, 0, func,
772773
&pcr, &template, keyring);
773774
if (!(action & IMA_MEASURE))
774775
return;
@@ -823,16 +824,26 @@ void process_buffer_measurement(const void *buf, int size,
823824

824825
/**
825826
* ima_kexec_cmdline - measure kexec cmdline boot args
827+
* @kernel_fd: file descriptor of the kexec kernel being loaded
826828
* @buf: pointer to buffer
827829
* @size: size of buffer
828830
*
829831
* Buffers can only be measured, not appraised.
830832
*/
831-
void ima_kexec_cmdline(const void *buf, int size)
833+
void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
832834
{
833-
if (buf && size != 0)
834-
process_buffer_measurement(buf, size, "kexec-cmdline",
835-
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);
836847
}
837848

838849
static int __init init_ima(void)

security/integrity/ima/ima_policy.c

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -443,13 +443,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
443443
{
444444
int i;
445445

446-
if ((func == KEXEC_CMDLINE) || (func == KEY_CHECK)) {
447-
if ((rule->flags & IMA_FUNC) && (rule->func == func)) {
448-
if (func == KEY_CHECK)
449-
return ima_match_keyring(rule, keyring, cred);
450-
return true;
451-
}
452-
return false;
446+
if (func == KEY_CHECK) {
447+
return (rule->flags & IMA_FUNC) && (rule->func == func) &&
448+
ima_match_keyring(rule, keyring, cred);
453449
}
454450
if ((rule->flags & IMA_FUNC) &&
455451
(rule->func != func && func != POST_SETATTR))
@@ -1035,10 +1031,9 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
10351031
if (entry->action & ~(MEASURE | DONT_MEASURE))
10361032
return false;
10371033

1038-
if (entry->flags & ~(IMA_FUNC | IMA_PCR))
1039-
return false;
1040-
1041-
if (ima_rule_contains_lsm_cond(entry))
1034+
if (entry->flags & ~(IMA_FUNC | IMA_FSMAGIC | IMA_UID |
1035+
IMA_FOWNER | IMA_FSUUID | IMA_EUID |
1036+
IMA_PCR | IMA_FSNAME))
10421037
return false;
10431038

10441039
break;

security/integrity/ima/ima_queue_keys.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ void ima_process_queued_keys(void)
158158

159159
list_for_each_entry_safe(entry, tmp, &ima_keys, list) {
160160
if (!timer_expired)
161-
process_buffer_measurement(entry->payload,
161+
process_buffer_measurement(NULL, entry->payload,
162162
entry->payload_len,
163163
entry->keyring_name,
164164
KEY_CHECK, 0,

0 commit comments

Comments
 (0)