summaryrefslogtreecommitdiff
path: root/security/integrity/ima
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-02-22 23:36:25 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2023-02-22 23:36:25 +0300
commit67e2dcff8b21923d48f5ca835773b2f005389e69 (patch)
treed82794c38da99b40ed452fb658a4e772e65c3e16 /security/integrity/ima
parent70756b49be4ea8bf36a664322df6e7e89895fa60 (diff)
parent4958db3245fa655bf18251bd2a83bcc164071c39 (diff)
downloadlinux-67e2dcff8b21923d48f5ca835773b2f005389e69.tar.xz
Merge tag 'integrity-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity
Pull integrity update from Mimi Zohar: "One doc and one code cleanup, and two bug fixes" * tag 'integrity-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity: ima: Introduce MMAP_CHECK_REQPROT hook ima: Align ima_file_mmap() parameters with mmap_file LSM hook evm: call dump_security_xattr() in all cases to remove code duplication ima: fix ima_delete_rules() kernel-doc warning ima: return IMA digest value only when IMA_COLLECTED flag is set ima: fix error handling logic when file measurement failed
Diffstat (limited to 'security/integrity/ima')
-rw-r--r--security/integrity/ima/ima.h1
-rw-r--r--security/integrity/ima/ima_api.c5
-rw-r--r--security/integrity/ima/ima_appraise.c3
-rw-r--r--security/integrity/ima/ima_main.c38
-rw-r--r--security/integrity/ima/ima_policy.c7
5 files changed, 42 insertions, 12 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index d8530e722515..c29db699c996 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -190,6 +190,7 @@ static inline unsigned int ima_hash_key(u8 *digest)
hook(NONE, none) \
hook(FILE_CHECK, file) \
hook(MMAP_CHECK, mmap) \
+ hook(MMAP_CHECK_REQPROT, mmap_reqprot) \
hook(BPRM_CHECK, bprm) \
hook(CREDS_CHECK, creds) \
hook(POST_SETATTR, post_setattr) \
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 9345fd66f5b8..d3662f4acadc 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -179,7 +179,8 @@ err_out:
* subj=, obj=, type=, func=, mask=, fsmagic=
* subj,obj, and type: are LSM specific.
* func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK
- * | KEXEC_CMDLINE | KEY_CHECK | CRITICAL_DATA
+ * | KEXEC_CMDLINE | KEY_CHECK | CRITICAL_DATA | SETXATTR_CHECK
+ * | MMAP_CHECK_REQPROT
* mask: contains the permission mask
* fsmagic: hex value
*
@@ -292,7 +293,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
result = ima_calc_file_hash(file, &hash.hdr);
}
- if (result == -ENOMEM)
+ if (result && result != -EBADF && result != -EINVAL)
goto out;
length = sizeof(hash.hdr) + hash.hdr.length;
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 555342d337f9..491c1aca0b1c 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -111,6 +111,7 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
{
switch (func) {
case MMAP_CHECK:
+ case MMAP_CHECK_REQPROT:
return iint->ima_mmap_status;
case BPRM_CHECK:
return iint->ima_bprm_status;
@@ -131,6 +132,7 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint,
{
switch (func) {
case MMAP_CHECK:
+ case MMAP_CHECK_REQPROT:
iint->ima_mmap_status = status;
break;
case BPRM_CHECK:
@@ -155,6 +157,7 @@ static void ima_cache_flags(struct integrity_iint_cache *iint,
{
switch (func) {
case MMAP_CHECK:
+ case MMAP_CHECK_REQPROT:
iint->flags |= (IMA_MMAP_APPRAISED | IMA_APPRAISED);
break;
case BPRM_CHECK:
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 358578267fea..d66a0a36415e 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -89,7 +89,8 @@ static int mmap_violation_check(enum ima_hooks func, struct file *file,
struct inode *inode;
int rc = 0;
- if ((func == MMAP_CHECK) && mapping_writably_mapped(file->f_mapping)) {
+ if ((func == MMAP_CHECK || func == MMAP_CHECK_REQPROT) &&
+ mapping_writably_mapped(file->f_mapping)) {
rc = -ETXTBSY;
inode = file_inode(file);
@@ -227,7 +228,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
action = ima_get_action(file_mnt_idmap(file), inode, cred, secid,
mask, func, &pcr, &template_desc, NULL,
&allowed_algos);
- violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
+ violation_check = ((func == FILE_CHECK || func == MMAP_CHECK ||
+ func == MMAP_CHECK_REQPROT) &&
(ima_policy_flag & IMA_MEASURE));
if (!action && !violation_check)
return 0;
@@ -337,7 +339,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
hash_algo = ima_get_hash_algo(xattr_value, xattr_len);
rc = ima_collect_measurement(iint, file, buf, size, hash_algo, modsig);
- if (rc == -ENOMEM)
+ if (rc != 0 && rc != -EBADF && rc != -EINVAL)
goto out_locked;
if (!pathbuf) /* ima_rdwr_violation possibly pre-fetched */
@@ -397,7 +399,9 @@ out:
/**
* ima_file_mmap - based on policy, collect/store measurement.
* @file: pointer to the file to be measured (May be NULL)
- * @prot: contains the protection that will be applied by the kernel.
+ * @reqprot: protection requested by the application
+ * @prot: protection that will be applied by the kernel
+ * @flags: operational flags
*
* Measure files being mmapped executable based on the ima_must_measure()
* policy decision.
@@ -405,15 +409,27 @@ out:
* On success return 0. On integrity appraisal error, assuming the file
* is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
*/
-int ima_file_mmap(struct file *file, unsigned long prot)
+int ima_file_mmap(struct file *file, unsigned long reqprot,
+ unsigned long prot, unsigned long flags)
{
u32 secid;
+ int ret;
- if (file && (prot & PROT_EXEC)) {
- security_current_getsecid_subj(&secid);
+ if (!file)
+ return 0;
+
+ security_current_getsecid_subj(&secid);
+
+ if (reqprot & PROT_EXEC) {
+ ret = process_measurement(file, current_cred(), secid, NULL,
+ 0, MAY_EXEC, MMAP_CHECK_REQPROT);
+ if (ret)
+ return ret;
+ }
+
+ if (prot & PROT_EXEC)
return process_measurement(file, current_cred(), secid, NULL,
0, MAY_EXEC, MMAP_CHECK);
- }
return 0;
}
@@ -454,6 +470,10 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
action = ima_get_action(file_mnt_idmap(vma->vm_file), inode,
current_cred(), secid, MAY_EXEC, MMAP_CHECK,
&pcr, &template, NULL, NULL);
+ action |= ima_get_action(file_mnt_idmap(vma->vm_file), inode,
+ current_cred(), secid, MAY_EXEC,
+ MMAP_CHECK_REQPROT, &pcr, &template, NULL,
+ NULL);
/* Is the mmap'ed file in policy? */
if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK)))
@@ -563,7 +583,7 @@ static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
* ima_file_hash can be called when ima_collect_measurement has still
* not been called, we might not always have a hash.
*/
- if (!iint->ima_hash) {
+ if (!iint->ima_hash || !(iint->flags & IMA_COLLECTED)) {
mutex_unlock(&iint->mutex);
return -EOPNOTSUPP;
}
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index fc128a6b4abe..3ca8b7348c2e 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -697,6 +697,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
switch (func) {
case MMAP_CHECK:
+ case MMAP_CHECK_REQPROT:
return IMA_MMAP_APPRAISE;
case BPRM_CHECK:
return IMA_BPRM_APPRAISE;
@@ -1266,6 +1267,7 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
case NONE:
case FILE_CHECK:
case MMAP_CHECK:
+ case MMAP_CHECK_REQPROT:
case BPRM_CHECK:
case CREDS_CHECK:
case POST_SETATTR:
@@ -1504,6 +1506,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
else if ((strcmp(args[0].from, "FILE_MMAP") == 0)
|| (strcmp(args[0].from, "MMAP_CHECK") == 0))
entry->func = MMAP_CHECK;
+ else if ((strcmp(args[0].from, "MMAP_CHECK_REQPROT") == 0))
+ entry->func = MMAP_CHECK_REQPROT;
else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
entry->func = BPRM_CHECK;
else if (strcmp(args[0].from, "CREDS_CHECK") == 0)
@@ -1955,7 +1959,8 @@ ssize_t ima_parse_add_rule(char *rule)
}
/**
- * ima_delete_rules() called to cleanup invalid in-flight policy.
+ * ima_delete_rules() - called to cleanup invalid in-flight policy.
+ *
* We don't need locking as we operate on the temp list, which is
* different from the active one. There is also only one user of
* ima_delete_rules() at a time.