Skip to content

Commit 19b23ee

Browse files
committed
Rework MAP_ANON|MAP_SHARED and shmat cap support
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.
1 parent 5909b4d commit 19b23ee

File tree

4 files changed

+30
-2
lines changed

4 files changed

+30
-2
lines changed

sys/kern/sysv_shm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,7 @@ shmget_allocate_segment(struct thread *td, key_t key, size_t size, int mode)
900900
}
901901

902902
vm_object_set_flag(shm_object, OBJ_HASCAP);
903+
vm_object_set_flag(shm_object, OBJ_SHARECAP);
903904
shmseg->object = shm_object;
904905
shmseg->u.shm_perm.cuid = shmseg->u.shm_perm.uid = cred->cr_uid;
905906
shmseg->u.shm_perm.cgid = shmseg->u.shm_perm.gid = cred->cr_gid;

sys/vm/vm_map.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ static uma_zone_t vmspace_zone;
138138
static int vmspace_zinit(void *mem, int size, int flags);
139139
static void _vm_map_init(vm_map_t map, pmap_t pmap, vm_pointer_t min,
140140
vm_pointer_t max);
141+
static inline void vm_map_entry_back(vm_map_entry_t entry);
141142
static void vm_map_entry_deallocate(vm_map_entry_t entry, boolean_t system_map);
142143
static void vm_map_entry_delete(vm_map_t map, vm_map_entry_t entry);
143144
static void vm_map_entry_dispose(vm_map_t map, vm_map_entry_t entry);
@@ -2121,6 +2122,17 @@ vm_map_insert1(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
21212122
("overcommit: vm_map_insert leaks vm_map %p", new_entry));
21222123
new_entry->cred = cred;
21232124

2125+
if ((cow & MAP_SHARECAP) != 0) {
2126+
KASSERT(new_entry->inheritance == VM_INHERIT_SHARE,
2127+
("MAP_SHARECAP on unshared mapping"));
2128+
if (new_entry->object.vm_object == NULL)
2129+
vm_map_entry_back(new_entry);
2130+
VM_OBJECT_WLOCK(new_entry->object.vm_object);
2131+
vm_object_set_flag(new_entry->object.vm_object, OBJ_HASCAP);
2132+
vm_object_set_flag(new_entry->object.vm_object, OBJ_SHARECAP);
2133+
VM_OBJECT_WUNLOCK(new_entry->object.vm_object);
2134+
}
2135+
21242136
/*
21252137
* Insert the new entry into the list
21262138
*/

sys/vm/vm_map.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ long vmspace_resident_count(struct vmspace *vmspace);
471471
#define MAP_NO_HINT 0x00200000
472472
#define MAP_CREATE_SHADOW 0x00400000
473473
#define MAP_INHERIT_NONE 0x00800000
474+
#define MAP_SHARECAP 0x01000000
474475

475476
#define MAP_SPLIT_BOUNDARY_SHIFT 19
476477

sys/vm/vm_mmap.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -696,9 +696,12 @@ kern_mmap(struct thread *td, const struct mmap_req *mrp)
696696
/*
697697
* Mapping blank space is trivial.
698698
*/
699+
if ((flags & MAP_SHARED) == 0) {
700+
prot = VM_PROT_ADD_CAP(prot);
701+
max_prot = VM_PROT_ADD_CAP(max_prot);
702+
}
699703
error = vm_mmap_object(&vms->vm_map, &addr, max_addr, size,
700-
VM_PROT_ADD_CAP(prot), VM_PROT_ADD_CAP(max_prot), flags,
701-
NULL, pos, FALSE, td);
704+
prot, max_prot, flags, NULL, pos, FALSE, td);
702705
} else {
703706
/*
704707
* Mapping file, get fp for validation and don't let the
@@ -2080,6 +2083,17 @@ vm_mmap_object(vm_map_t map, vm_pointer_t *addr, vm_offset_t max_addr,
20802083
docow |= MAP_CHECK_EXCL;
20812084
if ((flags & MAP_GUARD) != 0)
20822085
docow |= MAP_CREATE_GUARD;
2086+
/*
2087+
* If we're creating a new shared resevation with anonymous
2088+
* backing and capability permissions, let the vm system know so
2089+
* the entry can be backed and OBJ_SHARECAP set.
2090+
*
2091+
* XXX: there should be a permission check...
2092+
*/
2093+
if ((flags & (MAP_ANON | MAP_SHARED | MAP_RESERVATION_CREATE)) ==
2094+
(MAP_ANON | MAP_SHARED | MAP_RESERVATION_CREATE) &&
2095+
(maxprot & (VM_PROT_READ_CAP | VM_PROT_WRITE_CAP)) != 0)
2096+
docow |= MAP_SHARECAP;
20832097

20842098
if (fitit) {
20852099
if ((flags & MAP_ALIGNMENT_MASK) == MAP_ALIGNED_SUPER)

0 commit comments

Comments
 (0)