diff options
author | Eric Paris <eparis@redhat.com> | 2010-10-13 17:50:31 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-10-20 19:12:59 -0400 |
commit | 845ca30fe9691f1bab7cfbf30b6d11c944eb4abd (patch) | |
tree | eabf2b17957c2214375f870387eaab6c43d9e931 /security/selinux | |
parent | cee74f47a6baba0ac457e87687fdcf0abd599f0a (diff) |
selinux: implement mmap on /selinux/policy
/selinux/policy allows a user to copy the policy back out of the kernel.
This patch allows userspace to actually mmap that file and use it directly.
Signed-off-by: Eric Paris <eparis@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux')
-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 | ||