binder: fix issues with mremap()
Subsystems (3)
Carlos Llamas
maintainerv3 cover binder: fix issues with mremap()
This is a follow up series fixing some pre-existing issues found by sashiko during a review of an unrelated patchset here:
https://sashiko.dev/#/patchset/[email protected]
The goal is to safely reject mremap() requests on binder's vma to prevent pages from temporary leaking and accidental IPC tear-down.
--
v3:
- Switch to a range-check in vm_ops->close() and protect against partial munmap() as Sashiko points out.
v2:
- Set VM_DONTEXPAND in [1/5] and [2/5] per Sashiko's feedback.
- Check vma->vm_start to prevent incorrect ->close() in [3/5] per Sashiko's feedback.
https://lore.kernel.org/all/[email protected]/
v1:
https://lore.kernel.org/all/[email protected]/
Carlos Llamas (5):
binder: set VM_DONTEXPAND
rust_binder: set VM_DONTEXPAND
binder: check vma->vm_start in binder_vma_close()
binder: reject mremap()
rust_binder: reject mremap()
drivers/android/binder.c | 13 ++++++++++++- drivers/android/binder/page_range.rs | 15 ++++++++++++--- drivers/android/binder/process.rs | 1 + 3 files changed, 25 insertions(+), 4 deletions(-)
Signature · 1 line
2.55.0.966.g6673acef38-goog
Carlos Llamas
maintainerPATCH v3 1/5 binder: set VM_DONTEXPAND
Binder does not support expanding VMAs. It caches the original size under alloc->buffer_size during mmap() and expanding the VMA would only result in a wasted virtual range. Set the VM_DONTEXPAND flag to prevent the vma from being expanded via mremap().
--- drivers/android/binder.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/android/binder.c +2 -1
@@ -6056,7 +6056,8 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) proc->pid, vma->vm_start, vma->vm_end, "bad vm_flags", -EPERM);return -EPERM ; } -vm_flags_mod (vma,VM_DONTCOPY |VM_MIXEDMAP ,VM_MAYWRITE ); +vm_flags_mod (vma,VM_DONTCOPY |VM_MIXEDMAP |VM_DONTEXPAND , +VM_MAYWRITE ); vma->vm_ops = &binder_vm_ops; vma->vm_private_data = proc;
Signature · 1 line
2.55.0.966.g6673acef38-goog
Carlos Llamas
maintainerPATCH v3 2/5 rust_binder: set VM_DONTEXPAND
In reply to Carlos LlamasBinder does not support expanding VMAs. It uses the original size to create its RangeAllocator during mmap() and expanding the VMA would only result in a wasted virtual range. Set the VM_DONTEXPAND flag to prevent the vma from being expanded via mremap().
--- drivers/android/binder/process.rs | 1 + 1 file changed, 1 insertion(+)
drivers/android/binder/process.rs +1 -0
@@ -1786,6 +1786,7 @@ pub(crate) fn mmap( vma.try_clear_maywrite ().map_err (|_|EPERM )?; vma.set_dontcopy (); vma.set_mixedmap (); + vma.set_dontexpand ();// TODO: Set ops. We need to learn when the user unmaps so that we can stop using it. this.create_mapping (vma)
Signature · 1 line
2.55.0.966.g6673acef38-goog
Carlos Llamas
maintainerPATCH v3 3/5 binder: check vma->vm_start in binder_vma_close()
In reply to Carlos LlamasCertain operations like a failed mremap() might trigger vm_ops->close() on temporary mappings. To avoid tearing-down the main binder mapping on these, let's verify that the VMA is within the expected address range.
--- drivers/android/binder.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/android/binder.c +4 -0
@@ -6018,6 +6018,10 @@ static void binder_vma_close(struct vm_area_struct *vma) {struct binder_proc *proc = vma->vm_private_data; +if (vma->vm_start < proc->alloc.vm_start || + vma->vm_start >= (proc->alloc.vm_start + proc->alloc.buffer_size)) +return ; + binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end,
Signature · 1 line
2.55.0.966.g6673acef38-goog
Carlos Llamas
maintainerPATCH v3 4/5 binder: reject mremap()
In reply to Carlos LlamasBinder does not support mremap() as it caches the mapping address in alloc->vm_start. Moving the mapping breaks the IPC communication for the process and can temporarily leak pages during a shrinker reclaim.
Fix this by explicitly rejecting the .mremap() operation.
--- drivers/android/binder.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/android/binder.c +6 -0
@@ -6036,10 +6036,16 @@ VISIBLE_IF_KUNIT vm_fault_t binder_vm_fault(struct vm_fault *vmf) }EXPORT_SYMBOL_IF_KUNIT (binder_vm_fault); +static int binder_mremap (struct vm_area_struct *vma) +{ +return -EINVAL ; +} +static const struct vm_operations_struct binder_vm_ops = { .open = binder_vma_open, .close = binder_vma_close, .fault = binder_vm_fault, + .mremap = binder_mremap, };static int binder_mmap (struct file *filp,struct vm_area_struct *vma)
Signature · 1 line
2.55.0.966.g6673acef38-goog
Carlos Llamas
maintainerPATCH v3 5/5 rust_binder: reject mremap()
In reply to Carlos LlamasBinder does not support mremap() as it caches the mapping address in Inner::vma_addr. Moving the mapping breaks the IPC communication for the process and can temporarily leak pages during a shrinker reclaim.
Fix this by explicitly rejecting the .mremap() operation.
--- drivers/android/binder/page_range.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/android/binder/page_range.rs +12 -3
@@ -24,7 +24,7 @@use kernel::{ bindings, error::Result , - ffi::{c_ulong, c_void}, + ffi::{c_int, c_ulong, c_void}, mm::{virt,Mm ,MmWithUser }, new_mutex, new_spinlock, page::{Page ,PAGE_SHIFT ,PAGE_SIZE },
@@ -144,8 +144,17 @@ pub(crate) struct ShrinkablePageRange { _pin: PhantomPinned, } -// We do not define any ops. For now, used only to check identity of vmas. -static BINDER_VM_OPS :AssertSync <bindings::vm_operations_struct > =AssertSync (pin_init::zeroed ()); +unsafe extern "C" fn binder_mremap (_: *mut bindings::vm_area_struct ) ->c_int { +EINVAL .to_errno () +} + +static BINDER_VM_OPS :AssertSync <bindings::vm_operations_struct > = { +let ops = bindings::vm_operations_struct { + mremap:Some (binder_mremap), + ..pin_init::zeroed () + }; +AssertSync (ops) +};// To ensure that we do not accidentally install pages into or zap pages from the wrong vma, we // check its vm_ops and private data before using it.
Signature · 1 line
2.55.0.966.g6673acef38-goog
Carlos Llamas
maintainerQuoted 8 lines · Carlos Llamas
This is a follow up series fixing some pre-existing issues found by sashiko during a review of an unrelated patchset here:
https://sashiko.dev/#/patchset/[email protected]The goal is to safely reject
mremap()requests on binder's vma to prevent pages from temporary leaking and accidental IPC tear-down.--
Dang! Sashiko keeps finding pre-existing issues. AFAICT, all these are real issues. It's seems we also, need to reject partial range munmap(). This should be easy though via ->may_split().
I'll send out a v4 with this addition.
--
Carlos Llamas