History

ima: verify mprotect change is consistent with mmap policy

Files can be mmap'ed read/write and later changed to execute to circumvent IMA's mmap appraise policy rules. Due to locking issues (mmap semaphore would be taken prior to i_mutex), files can not be measured or appraised at this point. Eliminate this integrity gap, by denying the mprotect PROT_EXECUTE change, if an mmap appraise policy rule exists. On mprotect change success, return 0. On failure, return -EACESS.

Mimi Zohar committed 6 years ago

Commit 8eb613c1 parent 0c4395f3 files · +64 −1Browse files

Unified · Split

3 files
  1. include/linux/ima.h +7 −0
  2. security/integrity/ima/ima_main.c +51 −0
  3. security/security.c +6 −1
include/linux/ima.h+7−0
@@ -18,6 +18,7 @@ extern int ima_file_check(struct file *file, int mask); · 17 unmodified lines
18extern void ima_post_create_tmpfile(struct inode *inode);18extern void ima_post_create_tmpfile(struct inode *inode);
19extern void ima_file_free(struct file *file);19extern void ima_file_free(struct file *file);
20extern int ima_file_mmap(struct file *file, unsigned long prot);20extern int ima_file_mmap(struct file *file, unsigned long prot);
21extern int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot);
21extern int ima_load_data(enum kernel_load_data_id id);22extern int ima_load_data(enum kernel_load_data_id id);
22extern int ima_read_file(struct file *file, enum kernel_read_file_id id);23extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
23extern int ima_post_read_file(struct file *file, void *buf, loff_t size,24extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
@@ -70,6 +71,12 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot) · 46 unmodified lines
70 return 0;71 return 0;
71}72}
72 73
74static inline int ima_file_mprotect(struct vm_area_struct *vma,
75 unsigned long prot)
76{
77 return 0;
78}
79
73static inline int ima_load_data(enum kernel_load_data_id id)80static inline int ima_load_data(enum kernel_load_data_id id)
74{81{
75 return 0;82 return 0;
security/integrity/ima/ima_main.c+51−0
@@ -393,6 +393,57 @@ int ima_file_mmap(struct file *file, unsigned long prot) · 392 unmodified lines
393 return 0;393 return 0;
394}394}
395 395
396/**
397 * ima_file_mprotect - based on policy, limit mprotect change
398 * @prot: contains the protection that will be applied by the kernel.
399 *
400 * Files can be mmap'ed read/write and later changed to execute to circumvent
401 * IMA's mmap appraisal policy rules. Due to locking issues (mmap semaphore
402 * would be taken before i_mutex), files can not be measured or appraised at
403 * this point. Eliminate this integrity gap by denying the mprotect
404 * PROT_EXECUTE change, if an mmap appraise policy rule exists.
405 *
406 * On mprotect change success, return 0. On failure, return -EACESS.
407 */
408int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
409{
410 struct ima_template_desc *template;
411 struct file *file = vma->vm_file;
412 char filename[NAME_MAX];
413 char *pathbuf = NULL;
414 const char *pathname = NULL;
415 struct inode *inode;
416 int result = 0;
417 int action;
418 u32 secid;
419 int pcr;
420
421 /* Is mprotect making an mmap'ed file executable? */
422 if (!vma->vm_file || !(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC))
423 return 0;
424
425 security_task_getsecid(current, &secid);
426 inode = file_inode(vma->vm_file);
427 action = ima_get_action(inode, current_cred(), secid, MAY_EXEC,
428 MMAP_CHECK, &pcr, &template, 0);
429
430 /* Is the mmap'ed file in policy? */
431 if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK)))
432 return 0;
433
434 if (action & IMA_APPRAISE_SUBMASK)
435 result = -EPERM;
436
437 file = vma->vm_file;
438 pathname = ima_d_path(&file->f_path, &pathbuf, filename);
439 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, pathname,
440 "collect_data", "failed-mprotect", result, 0);
441 if (pathbuf)
442 __putname(pathbuf);
443
444 return result;
445}
446
396/**447/**
397 * ima_bprm_check - based on policy, collect/store measurement.448 * ima_bprm_check - based on policy, collect/store measurement.
398 * @bprm: contains the linux_binprm structure449 * @bprm: contains the linux_binprm structure
security/security.c+6−1
@@ -1512,7 +1512,12 @@ int security_mmap_addr(unsigned long addr) · 1511 unmodified lines
1512int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,1512int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
1513 unsigned long prot)1513 unsigned long prot)
1514{1514{
1515 return call_int_hook(file_mprotect, 0, vma, reqprot, prot);1515 int ret;
1516
1517 ret = call_int_hook(file_mprotect, 0, vma, reqprot, prot);
1518 if (ret)
1519 return ret;
1520 return ima_file_mprotect(vma, prot);
1516}1521}
1517 1522
1518int security_file_lock(struct file *file, unsigned int cmd)1523int security_file_lock(struct file *file, unsigned int cmd)