Skip to content

Commit ca3c9bd

Browse files
robertosassumimizohar
authored andcommitted
ima: Add digest and digest_len params to the functions to measure a buffer
This patch performs the final modification necessary to pass the buffer measurement to callers, so that they provide a functionality similar to ima_file_hash(). It adds the 'digest' and 'digest_len' parameters to ima_measure_critical_data() and process_buffer_measurement(). These functions calculate the digest even if there is no suitable rule in the IMA policy and, in this case, they simply return 1 before generating a new measurement entry. Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com> Reviewed-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
1 parent ce5bb5a commit ca3c9bd

8 files changed

Lines changed: 39 additions & 19 deletions

File tree

include/linux/ima.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ extern void ima_kexec_cmdline(int kernel_fd, const void *buf, int size);
3838
extern int ima_measure_critical_data(const char *event_label,
3939
const char *event_name,
4040
const void *buf, size_t buf_len,
41-
bool hash);
41+
bool hash, u8 *digest, size_t digest_len);
4242

4343
#ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
4444
extern void ima_appraise_parse_cmdline(void);
@@ -147,7 +147,8 @@ static inline void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) {
147147
static inline int ima_measure_critical_data(const char *event_label,
148148
const char *event_name,
149149
const void *buf, size_t buf_len,
150-
bool hash)
150+
bool hash, u8 *digest,
151+
size_t digest_len)
151152
{
152153
return -ENOENT;
153154
}

security/integrity/ima/ima.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ int process_buffer_measurement(struct user_namespace *mnt_userns,
268268
struct inode *inode, const void *buf, int size,
269269
const char *eventname, enum ima_hooks func,
270270
int pcr, const char *func_data,
271-
bool buf_hash);
271+
bool buf_hash, u8 *digest, size_t digest_len);
272272
void ima_audit_measurement(struct integrity_iint_cache *iint,
273273
const unsigned char *filename);
274274
int ima_alloc_init_template(struct ima_event_data *event_data,

security/integrity/ima/ima_appraise.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint,
357357
if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
358358
process_buffer_measurement(&init_user_ns, NULL, digest, digestsize,
359359
"blacklisted-hash", NONE,
360-
pcr, NULL, false);
360+
pcr, NULL, false, NULL, 0);
361361
}
362362

363363
return rc;

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
}

security/integrity/ima/ima_main.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -838,17 +838,20 @@ int ima_post_load_data(char *buf, loff_t size,
838838
* @pcr: pcr to extend the measurement
839839
* @func_data: func specific data, may be NULL
840840
* @buf_hash: measure buffer data hash
841+
* @digest: buffer digest will be written to
842+
* @digest_len: buffer length
841843
*
842844
* Based on policy, either the buffer data or buffer data hash is measured
843845
*
844-
* Return: 0 if the buffer has been successfully measured, a negative value
845-
* otherwise.
846+
* Return: 0 if the buffer has been successfully measured, 1 if the digest
847+
* has been written to the passed location but not added to a measurement entry,
848+
* a negative value otherwise.
846849
*/
847850
int process_buffer_measurement(struct user_namespace *mnt_userns,
848851
struct inode *inode, const void *buf, int size,
849852
const char *eventname, enum ima_hooks func,
850853
int pcr, const char *func_data,
851-
bool buf_hash)
854+
bool buf_hash, u8 *digest, size_t digest_len)
852855
{
853856
int ret = 0;
854857
const char *audit_cause = "ENOMEM";
@@ -869,7 +872,10 @@ int process_buffer_measurement(struct user_namespace *mnt_userns,
869872
int action = 0;
870873
u32 secid;
871874

872-
if (!ima_policy_flag)
875+
if (digest && digest_len < digest_hash_len)
876+
return -EINVAL;
877+
878+
if (!ima_policy_flag && !digest)
873879
return -ENOENT;
874880

875881
template = ima_template_desc_buf();
@@ -891,7 +897,7 @@ int process_buffer_measurement(struct user_namespace *mnt_userns,
891897
action = ima_get_action(mnt_userns, inode, current_cred(),
892898
secid, 0, func, &pcr, &template,
893899
func_data);
894-
if (!(action & IMA_MEASURE))
900+
if (!(action & IMA_MEASURE) && !digest)
895901
return -ENOENT;
896902
}
897903

@@ -922,6 +928,12 @@ int process_buffer_measurement(struct user_namespace *mnt_userns,
922928
event_data.buf_len = digest_hash_len;
923929
}
924930

931+
if (digest)
932+
memcpy(digest, iint.ima_hash->digest, digest_hash_len);
933+
934+
if (!ima_policy_flag || (func && !(action & IMA_MEASURE)))
935+
return 1;
936+
925937
ret = ima_alloc_init_template(&event_data, &entry, template);
926938
if (ret < 0) {
927939
audit_cause = "alloc_entry";
@@ -964,7 +976,7 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
964976

965977
process_buffer_measurement(file_mnt_user_ns(f.file), file_inode(f.file),
966978
buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0,
967-
NULL, false);
979+
NULL, false, NULL, 0);
968980
fdput(f);
969981
}
970982

@@ -975,26 +987,30 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
975987
* @buf: pointer to buffer data
976988
* @buf_len: length of buffer data (in bytes)
977989
* @hash: measure buffer data hash
990+
* @digest: buffer digest will be written to
991+
* @digest_len: buffer length
978992
*
979993
* Measure data critical to the integrity of the kernel into the IMA log
980994
* and extend the pcr. Examples of critical data could be various data
981995
* structures, policies, and states stored in kernel memory that can
982996
* impact the integrity of the system.
983997
*
984-
* Return: 0 if the buffer has been successfully measured, a negative value
985-
* otherwise.
998+
* Return: 0 if the buffer has been successfully measured, 1 if the digest
999+
* has been written to the passed location but not added to a measurement entry,
1000+
* a negative value otherwise.
9861001
*/
9871002
int ima_measure_critical_data(const char *event_label,
9881003
const char *event_name,
9891004
const void *buf, size_t buf_len,
990-
bool hash)
1005+
bool hash, u8 *digest, size_t digest_len)
9911006
{
9921007
if (!event_name || !event_label || !buf || !buf_len)
9931008
return -ENOPARAM;
9941009

9951010
return process_buffer_measurement(&init_user_ns, NULL, buf, buf_len,
9961011
event_name, CRITICAL_DATA, 0,
997-
event_label, hash);
1012+
event_label, hash, digest,
1013+
digest_len);
9981014
}
9991015

10001016
static int __init init_ima(void)

security/integrity/ima/ima_queue_keys.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ void ima_process_queued_keys(void)
165165
entry->keyring_name,
166166
KEY_CHECK, 0,
167167
entry->keyring_name,
168-
false);
168+
false, NULL, 0);
169169
list_del(&entry->list);
170170
ima_free_key_entry(entry);
171171
}

security/selinux/ima.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ void selinux_ima_measure_state_locked(struct selinux_state *state)
8686
}
8787

8888
ima_measure_critical_data("selinux", "selinux-state",
89-
state_str, strlen(state_str), false);
89+
state_str, strlen(state_str), false,
90+
NULL, 0);
9091

9192
kfree(state_str);
9293

@@ -103,7 +104,8 @@ void selinux_ima_measure_state_locked(struct selinux_state *state)
103104
}
104105

105106
ima_measure_critical_data("selinux", "selinux-policy-hash",
106-
policy, policy_len, true);
107+
policy, policy_len, true,
108+
NULL, 0);
107109

108110
vfree(policy);
109111
}

0 commit comments

Comments
 (0)