Skip to content

Commit

Permalink
Rework MAP_ANON|MAP_SHARED and shmat cap support
Browse files Browse the repository at this point in the history
mmap(..., MAP_ANON|MAP_SHARED, ...):
    Require PROT_CAP explicitly to enable capability support in
    shared, anonymous mappings.  When specified, set the MAP_SHARECAP
    cow flag which causes a backing object to be allocated and the
    OBJ_SHARECAP flag set to allow sharing capabilities across address
    spaces.

shmat:
    Always set OBJ_SHARECAP on SysV shared memory objects.  Use of them
    is straightforwardly auditable.  We might want to add an explict
    SHM_SHARECAP flag at some point rather than making this universal,
    but shmat is probably best left in the dustbin of history.
  • Loading branch information
brooksdavis committed Oct 17, 2024
1 parent 5909b4d commit 19b23ee
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 2 deletions.
1 change: 1 addition & 0 deletions sys/kern/sysv_shm.c
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,7 @@ shmget_allocate_segment(struct thread *td, key_t key, size_t size, int mode)
}

vm_object_set_flag(shm_object, OBJ_HASCAP);
vm_object_set_flag(shm_object, OBJ_SHARECAP);
shmseg->object = shm_object;
shmseg->u.shm_perm.cuid = shmseg->u.shm_perm.uid = cred->cr_uid;
shmseg->u.shm_perm.cgid = shmseg->u.shm_perm.gid = cred->cr_gid;
Expand Down
12 changes: 12 additions & 0 deletions sys/vm/vm_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ static uma_zone_t vmspace_zone;
static int vmspace_zinit(void *mem, int size, int flags);
static void _vm_map_init(vm_map_t map, pmap_t pmap, vm_pointer_t min,
vm_pointer_t max);
static inline void vm_map_entry_back(vm_map_entry_t entry);
static void vm_map_entry_deallocate(vm_map_entry_t entry, boolean_t system_map);
static void vm_map_entry_delete(vm_map_t map, vm_map_entry_t entry);
static void vm_map_entry_dispose(vm_map_t map, vm_map_entry_t entry);
Expand Down Expand Up @@ -2121,6 +2122,17 @@ vm_map_insert1(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
("overcommit: vm_map_insert leaks vm_map %p", new_entry));
new_entry->cred = cred;

if ((cow & MAP_SHARECAP) != 0) {
KASSERT(new_entry->inheritance == VM_INHERIT_SHARE,
("MAP_SHARECAP on unshared mapping"));
if (new_entry->object.vm_object == NULL)
vm_map_entry_back(new_entry);
VM_OBJECT_WLOCK(new_entry->object.vm_object);
vm_object_set_flag(new_entry->object.vm_object, OBJ_HASCAP);
vm_object_set_flag(new_entry->object.vm_object, OBJ_SHARECAP);
VM_OBJECT_WUNLOCK(new_entry->object.vm_object);
}

/*
* Insert the new entry into the list
*/
Expand Down
1 change: 1 addition & 0 deletions sys/vm/vm_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ long vmspace_resident_count(struct vmspace *vmspace);
#define MAP_NO_HINT 0x00200000
#define MAP_CREATE_SHADOW 0x00400000
#define MAP_INHERIT_NONE 0x00800000
#define MAP_SHARECAP 0x01000000

#define MAP_SPLIT_BOUNDARY_SHIFT 19

Expand Down
18 changes: 16 additions & 2 deletions sys/vm/vm_mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -696,9 +696,12 @@ kern_mmap(struct thread *td, const struct mmap_req *mrp)
/*
* Mapping blank space is trivial.
*/
if ((flags & MAP_SHARED) == 0) {
prot = VM_PROT_ADD_CAP(prot);
max_prot = VM_PROT_ADD_CAP(max_prot);
}
error = vm_mmap_object(&vms->vm_map, &addr, max_addr, size,
VM_PROT_ADD_CAP(prot), VM_PROT_ADD_CAP(max_prot), flags,
NULL, pos, FALSE, td);
prot, max_prot, flags, NULL, pos, FALSE, td);
} else {
/*
* Mapping file, get fp for validation and don't let the
Expand Down Expand Up @@ -2080,6 +2083,17 @@ vm_mmap_object(vm_map_t map, vm_pointer_t *addr, vm_offset_t max_addr,
docow |= MAP_CHECK_EXCL;
if ((flags & MAP_GUARD) != 0)
docow |= MAP_CREATE_GUARD;
/*
* If we're creating a new shared resevation with anonymous
* backing and capability permissions, let the vm system know so
* the entry can be backed and OBJ_SHARECAP set.
*
* XXX: there should be a permission check...
*/
if ((flags & (MAP_ANON | MAP_SHARED | MAP_RESERVATION_CREATE)) ==
(MAP_ANON | MAP_SHARED | MAP_RESERVATION_CREATE) &&
(maxprot & (VM_PROT_READ_CAP | VM_PROT_WRITE_CAP)) != 0)
docow |= MAP_SHARECAP;

if (fitit) {
if ((flags & MAP_ALIGNMENT_MASK) == MAP_ALIGNED_SUPER)
Expand Down

0 comments on commit 19b23ee

Please sign in to comment.