diff options
| -rw-r--r-- | security/selinux/selinuxfs.c | 44 | ||||
| -rw-r--r-- | security/selinux/ss/services.c | 2 |
2 files changed, 45 insertions, 1 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 8eb102c72606..87e0556bae70 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
| @@ -439,9 +439,53 @@ out: | |||
| 439 | return ret; | 439 | return ret; |
| 440 | } | 440 | } |
| 441 | 441 | ||
| 442 | static int sel_mmap_policy_fault(struct vm_area_struct *vma, | ||
| 443 | struct vm_fault *vmf) | ||
| 444 | { | ||
| 445 | struct policy_load_memory *plm = vma->vm_file->private_data; | ||
| 446 | unsigned long offset; | ||
| 447 | struct page *page; | ||
| 448 | |||
| 449 | if (vmf->flags & (FAULT_FLAG_MKWRITE | FAULT_FLAG_WRITE)) | ||
| 450 | return VM_FAULT_SIGBUS; | ||
| 451 | |||
| 452 | offset = vmf->pgoff << PAGE_SHIFT; | ||
| 453 | if (offset >= roundup(plm->len, PAGE_SIZE)) | ||
| 454 | return VM_FAULT_SIGBUS; | ||
| 455 | |||
| 456 | page = vmalloc_to_page(plm->data + offset); | ||
| 457 | get_page(page); | ||
| 458 | |||
| 459 | vmf->page = page; | ||
| 460 | |||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | |||
| 464 | static struct vm_operations_struct sel_mmap_policy_ops = { | ||
| 465 | .fault = sel_mmap_policy_fault, | ||
| 466 | .page_mkwrite = sel_mmap_policy_fault, | ||
| 467 | }; | ||
| 468 | |||
| 469 | int sel_mmap_policy(struct file *filp, struct vm_area_struct *vma) | ||
| 470 | { | ||
| 471 | if (vma->vm_flags & VM_SHARED) { | ||
| 472 | /* do not allow mprotect to make mapping writable */ | ||
| 473 | vma->vm_flags &= ~VM_MAYWRITE; | ||
| 474 | |||
| 475 | if (vma->vm_flags & VM_WRITE) | ||
| 476 | return -EACCES; | ||
| 477 | } | ||
| 478 | |||
| 479 | vma->vm_flags |= VM_RESERVED; | ||
| 480 | vma->vm_ops = &sel_mmap_policy_ops; | ||
| 481 | |||
| 482 | return 0; | ||
| 483 | } | ||
| 484 | |||
| 442 | static const struct file_operations sel_policy_ops = { | 485 | static const struct file_operations sel_policy_ops = { |
| 443 | .open = sel_open_policy, | 486 | .open = sel_open_policy, |
| 444 | .read = sel_read_policy, | 487 | .read = sel_read_policy, |
| 488 | .mmap = sel_mmap_policy, | ||
| 445 | .release = sel_release_policy, | 489 | .release = sel_release_policy, |
| 446 | }; | 490 | }; |
| 447 | 491 | ||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 7565d16aac31..3a1739b33b78 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -3169,7 +3169,7 @@ int security_read_policy(void **data, ssize_t *len) | |||
| 3169 | 3169 | ||
| 3170 | *len = security_policydb_len(); | 3170 | *len = security_policydb_len(); |
| 3171 | 3171 | ||
| 3172 | *data = vmalloc(*len); | 3172 | *data = vmalloc_user(*len); |
| 3173 | if (!*data) | 3173 | if (!*data) |
| 3174 | return -ENOMEM; | 3174 | return -ENOMEM; |
| 3175 | 3175 | ||
