diff --git a/bin/cheribsdtest/cheribsdtest_cheriabi.c b/bin/cheribsdtest/cheribsdtest_cheriabi.c index b7f9e439368c..34082b49f2f1 100644 --- a/bin/cheribsdtest/cheribsdtest_cheriabi.c +++ b/bin/cheribsdtest/cheribsdtest_cheriabi.c @@ -389,11 +389,16 @@ CHERIBSDTEST(cheriabi_minherit_invalid_ptr, CHERIBSDTEST_CHECK_CALL_ERROR(minherit(mappings.middle + mappings.maplen, mappings.maplen, INHERIT_NONE), EPROT); + /* + * minherit() should not be able to mark a MAP_ANON mapping shared + * upless it was initially marked as shared. + */ + CHERIBSDTEST_CHECK_CALL_ERROR(minherit(mappings.middle, mappings.maplen, + INHERIT_SHARE), EACCES); + /* Sanity check: minherit() on a valid capability should succeed. */ CHERIBSDTEST_CHECK_SYSCALL(minherit(mappings.middle, mappings.maplen, INHERIT_NONE)); - CHERIBSDTEST_CHECK_SYSCALL(minherit(mappings.middle, mappings.maplen, - INHERIT_SHARE)); /* Unmapping the original capabilities should succeed. */ free_adjacent_mappings(&mappings); diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index a85d0cc1d72f..73503e455f0b 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -3778,14 +3778,35 @@ vm_map_inherit(vm_map_t map, vm_offset_t start, vm_offset_t end, } } #endif - if (new_inheritance == VM_INHERIT_COPY) { + if (new_inheritance == VM_INHERIT_COPY || + new_inheritance == VM_INHERIT_SHARE) { for (entry = start_entry; entry->start < end; prev_entry = entry, entry = vm_map_entry_succ(entry)) { - if ((entry->eflags & MAP_ENTRY_SPLIT_BOUNDARY_MASK) + if (new_inheritance == VM_INHERIT_COPY && + (entry->eflags & MAP_ENTRY_SPLIT_BOUNDARY_MASK) != 0) { rv = KERN_INVALID_ARGUMENT; goto unlock; } + /* + * CheriABI: mostly disallow post-fork sharing via + * minherit(). Developers should use mmap and + * MAP_SHARED instead. Do allow no-op reqests + * and sharing of mappings that either have no + * capabilities or where objects have the + * OBJ_SHARECAP flag. + */ + if (new_inheritance == VM_INHERIT_SHARE && + entry->inheritance != VM_INHERIT_SHARE && + /* XXX: check reservations instead? */ + SV_CURPROC_FLAG(SV_CHERI) && + (entry->object.vm_object == NULL || + (entry->object.vm_object->flags & + (OBJ_NOCAP | OBJ_SHARECAP)) == 0)) { + rv = KERN_PROTECTION_FAILURE; + goto unlock; + } + } } for (entry = start_entry; entry->start < end; prev_entry = entry,