/** * Iterate on each item of the map, applying callback. */ void map_foreach(const map_t *m, keyval_fn_t cb, void *u) { map_check(m); g_assert(cb); switch (m->type) { case MAP_HASH: htable_foreach(m->u.ht, (ckeyval_fn_t) cb, u); break; case MAP_ORDERED_HASH: ohash_table_foreach(m->u.ot, cb, u); break; case MAP_PATRICIA: { struct pat_foreach ctx; ctx.cb = cb; ctx.u = u; patricia_foreach(m->u.pt, pat_foreach_wrapper, &ctx); } break; case MAP_MAXTYPE: g_assert_not_reached(); } }
static int mcast_hostlist(const char *vm_name, const char *vm_uuid, int state, void *priv) { struct mcast_hostlist_arg *arg = (struct mcast_hostlist_arg *)priv; host_state_t hinfo; struct timeval tv; int ret; if (map_check(arg->map, arg->src, vm_uuid) == 0) { /* if we don't have access to fence this VM, * we should not see it in a hostlist either */ return 0; } strncpy((char *)hinfo.domain, vm_name, sizeof(hinfo.domain)); strncpy((char *)hinfo.uuid, vm_uuid, sizeof(hinfo.uuid)); hinfo.state = state; tv.tv_sec = 1; tv.tv_usec = 0; ret = _write_retry(arg->fd, &hinfo, sizeof(hinfo), &tv); if (ret == sizeof(hinfo)) return 0; return 1; }
/** * Iterate over the map, applying callback on each item and removing it if * the callback returns TRUE. * * @return the amount of items deleted. */ size_t map_foreach_remove(const map_t *m, keyval_rm_fn_t cb, void *u) { map_check(m); g_assert(cb); switch (m->type) { case MAP_HASH: return htable_foreach_remove(m->u.ht, (ckeyval_rm_fn_t) cb, u); case MAP_ORDERED_HASH: return ohash_table_foreach_remove(m->u.ot, cb, u); case MAP_PATRICIA: { struct pat_foreach_remove ctx; ctx.cb = cb; ctx.u = u; return patricia_foreach_remove( m->u.pt, pat_foreach_remove_wrapper, &ctx); } case MAP_MAXTYPE: g_assert_not_reached(); } return 0; }
/** * Switch the implementation of an existing map to a PATRICIA tree. * Returns the previous implementation. */ void * map_switch_to_patricia(map_t *m, patricia_t *pt) { void *implementation; map_check(m); g_assert(pt); implementation = map_implementation(m); m->type = MAP_PATRICIA; m->u.pt = pt; return implementation; }
/** * Switch the implementation of an existing map to an ordered hash table. * Returns the previous implementation. */ void * map_switch_to_ordered_hash(map_t *m, ohash_table_t *ot) { void *implementation; map_check(m); g_assert(ot); implementation = map_implementation(m); m->type = MAP_ORDERED_HASH; m->u.ot = ot; return implementation; }
/** * Switch the implementation of an existing map to a hash table. * Returns the previous implementation. */ void * map_switch_to_hash(map_t *m, htable_t *ht) { void *implementation; map_check(m); g_assert(ht); implementation = map_implementation(m); m->type = MAP_HASH; m->u.ht = ht; return implementation; }
ATF_TC_BODY(mmap_prot_1, tc) { void *map; int fd; /* * Open a file write-only and try to * map it read-only. This should fail. */ fd = open(path, O_WRONLY | O_CREAT, 0700); if (fd < 0) return; ATF_REQUIRE(write(fd, "XXX", 3) == 3); map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0); map_check(map, 1); map = mmap(NULL, 3, PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0); map_check(map, 0); ATF_REQUIRE(close(fd) == 0); }
/** * Release the map encapsulation, returning the underlying implementation * object (will need to be cast back to the proper type for perusal). */ void * map_release(map_t *m) { void *implementation; map_check(m); implementation = map_implementation(m); m->type = MAP_MAXTYPE; m->magic = 0; WFREE(m); return implementation; }
ATF_TC_BODY(mmap_va0, tc) { int flags = MAP_ANON | MAP_FIXED | MAP_PRIVATE; size_t len = sizeof(int); void *map; int val; /* * Make an anonymous fixed mapping at zero address. If the address * is restricted as noted in security(7), the syscall should fail. */ #ifdef __FreeBSD__ if (sysctlbyname("security.bsd.map_at_zero", &val, &len, NULL, 0) != 0) atf_tc_fail("failed to read security.bsd.map_at_zero"); val = !val; /* 1 == enable map at zero */ #endif #ifdef __NetBSD__ if (sysctlbyname("vm.user_va0_disable", &val, &len, NULL, 0) != 0) atf_tc_fail("failed to read vm.user_va0_disable"); #endif map = mmap(NULL, page, PROT_EXEC, flags, -1, 0); map_check(map, val); map = mmap(NULL, page, PROT_READ, flags, -1, 0); map_check(map, val); map = mmap(NULL, page, PROT_WRITE, flags, -1, 0); map_check(map, val); map = mmap(NULL, page, PROT_READ|PROT_WRITE, flags, -1, 0); map_check(map, val); map = mmap(NULL, page, PROT_EXEC|PROT_READ|PROT_WRITE, flags, -1, 0); map_check(map, val); }
/** * Extended lookup of a key in the map, returning both key/value pointers. */ bool map_lookup_extended(const map_t *m, const void *key, void **okey, void **oval) { map_check(m); switch (m->type) { case MAP_HASH: return htable_lookup_extended(m->u.ht, key, (const void **) okey, oval); case MAP_ORDERED_HASH: return ohash_table_lookup_extended(m->u.ot, key, okey, oval); case MAP_PATRICIA: return patricia_lookup_extended(m->u.pt, key, okey, oval); case MAP_MAXTYPE: g_assert_not_reached(); } return FALSE; }
/** * @return amount of items held in map. */ size_t map_count(const map_t *m) { map_check(m); switch (m->type) { case MAP_HASH: return htable_count(m->u.ht); case MAP_ORDERED_HASH: return ohash_table_count(m->u.ot); case MAP_PATRICIA: return patricia_count(m->u.pt); case MAP_MAXTYPE: g_assert_not_reached(); } return 0; }
/** * Lookup a key in the map. */ void * map_lookup(const map_t *m, const void *key) { map_check(m); switch (m->type) { case MAP_HASH: return htable_lookup(m->u.ht, key); case MAP_ORDERED_HASH: return ohash_table_lookup(m->u.ot, key); case MAP_PATRICIA: return patricia_lookup(m->u.pt, key); case MAP_MAXTYPE: g_assert_not_reached(); } return NULL; }
/** * Check whether map contains the key. */ bool map_contains(const map_t *m, const void *key) { map_check(m); switch (m->type) { case MAP_HASH: return htable_contains(m->u.ht, key); case MAP_ORDERED_HASH: return ohash_table_contains(m->u.ot, key); case MAP_PATRICIA: return patricia_contains(m->u.pt, key); case MAP_MAXTYPE: g_assert_not_reached(); } return FALSE; }
/** * Returns the underlying map implementation. */ void * map_implementation(const map_t *m) { map_check(m); switch (m->type) { case MAP_HASH: return m->u.ht; case MAP_ORDERED_HASH: return m->u.ot; case MAP_PATRICIA: return m->u.pt; case MAP_MAXTYPE: g_assert_not_reached(); } return NULL; }
/** * Replace a key/value pair in the map. */ void map_replace(const map_t *m, const void *key, const void *value) { map_check(m); switch (m->type) { case MAP_HASH: htable_insert_const(m->u.ht, key, value); break; case MAP_ORDERED_HASH: ohash_table_replace(m->u.ot, key, value); break; case MAP_PATRICIA: patricia_insert(m->u.pt, key, value); /* Does replace */ break; case MAP_MAXTYPE: g_assert_not_reached(); } }
/** * Mark map as thread-safe. * * If the underlying implementation does not implement thread-safety, this * causes a fatal error. */ void map_thread_safe(const map_t *m) { const char *type = NULL; map_check(m); switch (m->type) { case MAP_HASH: htable_thread_safe(m->u.ht); return; case MAP_ORDERED_HASH: type = "ordered hash"; break; case MAP_PATRICIA: type = "PATRICIA"; break; case MAP_MAXTYPE: g_assert_not_reached(); } s_error("%s(): %s implementation is not thread-safe yet", G_STRFUNC, type); }
/** * Destroy a map. */ void map_destroy(map_t *m) { map_check(m); switch (m->type) { case MAP_HASH: htable_free_null(&m->u.ht); break; case MAP_ORDERED_HASH: ohash_table_destroy_null(&m->u.ot); break; case MAP_PATRICIA: patricia_destroy(m->u.pt); break; case MAP_MAXTYPE: g_assert_not_reached(); } m->type = MAP_MAXTYPE; m->magic = 0; WFREE(m); }
static int vsock_hostlist(const char *vm_name, const char *vm_uuid, int state, void *priv) { struct vsock_hostlist_arg *arg = (struct vsock_hostlist_arg *) priv; host_state_t hinfo; struct timeval tv; int ret; uint32_t peer_cid = 0; char peer_cid_str[24]; ret = get_peer_cid(arg->fd, &peer_cid); if (ret < 0) { printf("Unable to get peer CID: %s\n", strerror(errno)); peer_cid_str[0] = '\0'; } else snprintf(peer_cid_str, sizeof(peer_cid_str), "%u", peer_cid); /* Noops if auth == AUTH_NONE */ if (map_check(arg->map, peer_cid_str, vm_uuid) == 0) { /* if we don't have access to fence this VM, * we should not see it in a hostlist either */ return 0; } strncpy((char *)hinfo.domain, vm_name, sizeof(hinfo.domain)); strncpy((char *)hinfo.uuid, vm_uuid, sizeof(hinfo.uuid)); hinfo.state = state; tv.tv_sec = 1; tv.tv_usec = 0; ret = _write_retry(arg->fd, &hinfo, sizeof(hinfo), &tv); if (ret == sizeof(hinfo)) return 0; return 1; }
void _memory_init(struct multiboot_info *info) { // Use whatever information the bootloader gave us to figure out what // lives where in our address space and which parts of it we can use. if (info->flags & 1<<6) { // We have a BIOS memory map. struct memory_map *mmap = (struct memory_map*)info->memory_map_addr; map_check(mmap, info->memory_map_length); } else if (info->flags & 1<<0) { // We know how large the upper and lower memory banks are. simple_check(info->mem_lower * 1024, info->mem_upper * 1024); } if (IMAGE_BASE < memory_end && IMAGE_END > memory_base) { // The beginning of our memory region is already home to our // executable image and bootstrap stack. Move the allocation pointer // past it so we don't accidentally reuse it. memory_break = IMAGE_END; } else { memory_break = memory_base; } if (IMAGE_BASE > memory_base && IMAGE_BASE < memory_end) { // Truncate the memory region so it no longer overlaps the executable. memory_end = IMAGE_BASE; } }
static int do_fence_request_tcp(int fd, fence_req_t *req, tcp_info *info) { char ip_addr_src[1024]; char response = 1; struct tcp_hostlist_arg arg; /* Noops if auth == AUTH_NONE */ if (tcp_response(fd, info->args.auth, info->key, info->key_len, 10) <= 0) { printf("Failed to respond to challenge\n"); close(fd); return -1; } if (tcp_challenge(fd, info->args.auth, info->key, info->key_len, 10) <= 0) { printf("Remote failed challenge\n"); close(fd); return -1; } dbg_printf(2, "Request %d seqno %d target %s\n", req->request, req->seqno, req->domain); switch(req->request) { case FENCE_NULL: response = info->cb->null((char *)req->domain, info->priv); break; case FENCE_ON: if (map_check(info->map, ip_addr_src, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->on((char *)req->domain, ip_addr_src, req->seqno, info->priv); break; case FENCE_OFF: if (map_check(info->map, ip_addr_src, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->off((char *)req->domain, ip_addr_src, req->seqno, info->priv); break; case FENCE_REBOOT: if (map_check(info->map, ip_addr_src, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->reboot((char *)req->domain, ip_addr_src, req->seqno, info->priv); break; case FENCE_STATUS: if (map_check(info->map, ip_addr_src, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->status((char *)req->domain, info->priv); break; case FENCE_DEVSTATUS: response = info->cb->devstatus(info->priv); break; case FENCE_HOSTLIST: arg.map = info->map; arg.src = ip_addr_src; arg.fd = fd; tcp_hostlist_begin(arg.fd); response = info->cb->hostlist(tcp_hostlist, &arg, info->priv); tcp_hostlist_end(arg.fd); break; } dbg_printf(3, "Sending response to caller...\n"); if (write(fd, &response, 1) < 0) { perror("write"); } history_record(info->history, req); if (fd != -1) close(fd); return 1; }
static int do_fence_request_tcp(fence_req_t *req, mcast_info *info) { char ip_addr_src[1024]; int fd = -1; char response = 1; struct mcast_hostlist_arg arg; fd = connect_tcp(req, info->args.auth, info->key, info->key_len); if (fd < 0) { dbg_printf(2, "Could not send reply to fence request: %s\n", strerror(errno)); goto out; } inet_ntop(req->family, req->address, ip_addr_src, sizeof(ip_addr_src)); dbg_printf(2, "Request %d seqno %d src %s target %s\n", req->request, req->seqno, ip_addr_src, req->domain); switch(req->request) { case FENCE_NULL: response = info->cb->null((char *)req->domain, info->priv); break; case FENCE_ON: if (map_check(info->map, ip_addr_src, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->on((char *)req->domain, ip_addr_src, req->seqno, info->priv); break; case FENCE_OFF: if (map_check(info->map, ip_addr_src, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->off((char *)req->domain, ip_addr_src, req->seqno, info->priv); break; case FENCE_REBOOT: if (map_check(info->map, ip_addr_src, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->reboot((char *)req->domain, ip_addr_src, req->seqno, info->priv); break; case FENCE_STATUS: if (map_check(info->map, ip_addr_src, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->status((char *)req->domain, info->priv); break; case FENCE_DEVSTATUS: response = info->cb->devstatus(info->priv); break; case FENCE_HOSTLIST: arg.map = info->map; arg.src = ip_addr_src; arg.fd = fd; mcast_hostlist_begin(arg.fd); response = info->cb->hostlist(mcast_hostlist, &arg, info->priv); mcast_hostlist_end(arg.fd); break; } dbg_printf(3, "Sending response to caller...\n"); if (write(fd, &response, 1) < 0) { perror("write"); } /* XVM shotguns multicast packets, so we want to avoid * acting on the same request multiple times if the first * attempt was successful. */ history_record(info->history, req); out: if (fd != -1) close(fd); return 1; }
static int do_fence_request_vsock(int fd, fence_req_t *req, vsock_info *info) { char response = 1; struct vsock_hostlist_arg arg; uint32_t peer_cid = 0; char peer_cid_str[24]; int ret; ret = get_peer_cid(fd, &peer_cid); if (ret < 0) { printf("Unable to get peer CID: %s\n", strerror(errno)); return -1; } snprintf(peer_cid_str, sizeof(peer_cid_str), "%u", peer_cid); /* Noops if auth == AUTH_NONE */ if (sock_response(fd, info->args.auth, info->key, info->key_len, 10) <= 0) { printf("CID %u Failed to respond to challenge\n", peer_cid); close(fd); return -1; } ret = sock_challenge(fd, info->args.auth, info->key, info->key_len, 10); if (ret <= 0) { printf("Remote CID %u failed challenge\n", peer_cid); close(fd); return -1; } dbg_printf(2, "Request %d seqno %d target %s from CID %u\n", req->request, req->seqno, req->domain, peer_cid); switch(req->request) { case FENCE_NULL: response = info->cb->null((char *)req->domain, info->priv); break; case FENCE_ON: if (map_check(info->map, peer_cid_str, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->on((char *)req->domain, peer_cid_str, req->seqno, info->priv); break; case FENCE_OFF: if (map_check(info->map, peer_cid_str, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->off((char *)req->domain, peer_cid_str, req->seqno, info->priv); break; case FENCE_REBOOT: if (map_check(info->map, peer_cid_str, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->reboot((char *)req->domain, peer_cid_str, req->seqno, info->priv); break; case FENCE_STATUS: if (map_check(info->map, peer_cid_str, (const char *)req->domain) == 0) { response = RESP_PERM; break; } response = info->cb->status((char *)req->domain, info->priv); break; case FENCE_DEVSTATUS: response = info->cb->devstatus(info->priv); break; case FENCE_HOSTLIST: arg.map = info->map; arg.fd = fd; vsock_hostlist_begin(arg.fd); response = info->cb->hostlist(vsock_hostlist, &arg, info->priv); vsock_hostlist_end(arg.fd); break; } dbg_printf(3, "Sending response to caller CID %u...\n", peer_cid); if (_write_retry(fd, &response, 1, NULL) < 0) perror("write"); history_record(info->history, req); if (fd != -1) close(fd); return 1; }