integrity-v6.3
-----BEGIN PGP SIGNATURE----- iIoEABYIADIWIQQdXVVFGN5XqKr1Hj7LwZzRsCrn5QUCY/OUGBQcem9oYXJAbGlu dXguaWJtLmNvbQAKCRDLwZzRsCrn5baCAP0a4N8OiH5Sv9EQ5xAI8jbDwOeE/Aen izx6RXiBncaY9QEA7WrXUS3y/8zO3dWSL9feviGDuajTn0bJpmWXkCeh8wM= =pwAo -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
67e2dcff8b
@ -35,7 +35,7 @@ Description:
|
||||
[FIRMWARE_CHECK]
|
||||
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
|
||||
[KEXEC_CMDLINE] [KEY_CHECK] [CRITICAL_DATA]
|
||||
[SETXATTR_CHECK]
|
||||
[SETXATTR_CHECK][MMAP_CHECK_REQPROT]
|
||||
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
|
||||
[[^]MAY_EXEC]
|
||||
fsmagic:= hex value
|
||||
|
@ -21,7 +21,8 @@ extern int ima_file_check(struct file *file, int mask);
|
||||
extern void ima_post_create_tmpfile(struct mnt_idmap *idmap,
|
||||
struct inode *inode);
|
||||
extern void ima_file_free(struct file *file);
|
||||
extern int ima_file_mmap(struct file *file, unsigned long prot);
|
||||
extern int ima_file_mmap(struct file *file, unsigned long reqprot,
|
||||
unsigned long prot, unsigned long flags);
|
||||
extern int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot);
|
||||
extern int ima_load_data(enum kernel_load_data_id id, bool contents);
|
||||
extern int ima_post_load_data(char *buf, loff_t size,
|
||||
@ -76,7 +77,8 @@ static inline void ima_file_free(struct file *file)
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int ima_file_mmap(struct file *file, unsigned long prot)
|
||||
static inline int ima_file_mmap(struct file *file, unsigned long reqprot,
|
||||
unsigned long prot, unsigned long flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -183,8 +183,8 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
|
||||
* Dump large security xattr values as a continuous ascii hexademical string.
|
||||
* (pr_debug is limited to 64 bytes.)
|
||||
*/
|
||||
static void dump_security_xattr(const char *prefix, const void *src,
|
||||
size_t count)
|
||||
static void dump_security_xattr_l(const char *prefix, const void *src,
|
||||
size_t count)
|
||||
{
|
||||
#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
|
||||
char *asciihex, *p;
|
||||
@ -200,6 +200,16 @@ static void dump_security_xattr(const char *prefix, const void *src,
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dump_security_xattr(const char *name, const char *value,
|
||||
size_t value_len)
|
||||
{
|
||||
if (value_len < 64)
|
||||
pr_debug("%s: (%zu) [%*phN]\n", name, value_len,
|
||||
(int)value_len, value);
|
||||
else
|
||||
dump_security_xattr_l(name, value, value_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the HMAC value across the set of protected security xattrs.
|
||||
*
|
||||
@ -254,15 +264,9 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
|
||||
if (is_ima)
|
||||
ima_present = true;
|
||||
|
||||
if (req_xattr_value_len < 64)
|
||||
pr_debug("%s: (%zu) [%*phN]\n", req_xattr_name,
|
||||
req_xattr_value_len,
|
||||
(int)req_xattr_value_len,
|
||||
req_xattr_value);
|
||||
else
|
||||
dump_security_xattr(req_xattr_name,
|
||||
req_xattr_value,
|
||||
req_xattr_value_len);
|
||||
dump_security_xattr(req_xattr_name,
|
||||
req_xattr_value,
|
||||
req_xattr_value_len);
|
||||
continue;
|
||||
}
|
||||
size = vfs_getxattr_alloc(&nop_mnt_idmap, dentry, xattr->name,
|
||||
@ -286,12 +290,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
|
||||
if (is_ima)
|
||||
ima_present = true;
|
||||
|
||||
if (xattr_size < 64)
|
||||
pr_debug("%s: (%zu) [%*phN]", xattr->name, xattr_size,
|
||||
(int)xattr_size, xattr_value);
|
||||
else
|
||||
dump_security_xattr(xattr->name, xattr_value,
|
||||
xattr_size);
|
||||
dump_security_xattr(xattr->name, xattr_value, xattr_size);
|
||||
}
|
||||
hmac_add_misc(desc, inode, type, data->digest);
|
||||
|
||||
|
@ -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) \
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -1661,12 +1661,13 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
|
||||
int security_mmap_file(struct file *file, unsigned long prot,
|
||||
unsigned long flags)
|
||||
{
|
||||
unsigned long prot_adj = mmap_prot(file, prot);
|
||||
int ret;
|
||||
ret = call_int_hook(mmap_file, 0, file, prot,
|
||||
mmap_prot(file, prot), flags);
|
||||
|
||||
ret = call_int_hook(mmap_file, 0, file, prot, prot_adj, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
return ima_file_mmap(file, prot);
|
||||
return ima_file_mmap(file, prot, prot_adj, flags);
|
||||
}
|
||||
|
||||
int security_mmap_addr(unsigned long addr)
|
||||
|
Loading…
Reference in New Issue
Block a user