• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * VMware VMCI Driver
3  *
4  * Copyright (C) 2012 VMware, Inc. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation version 2 and no later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  */
15 
16 #include <linux/vmw_vmci_defs.h>
17 #include <linux/vmw_vmci_api.h>
18 #include <linux/highmem.h>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/sched.h>
22 #include <linux/slab.h>
23 
24 #include "vmci_queue_pair.h"
25 #include "vmci_datagram.h"
26 #include "vmci_doorbell.h"
27 #include "vmci_context.h"
28 #include "vmci_driver.h"
29 #include "vmci_event.h"
30 
31 /* Use a wide upper bound for the maximum contexts. */
32 #define VMCI_MAX_CONTEXTS 2000
33 
34 /*
35  * List of current VMCI contexts.  Contexts can be added by
36  * vmci_ctx_create() and removed via vmci_ctx_destroy().
37  * These, along with context lookup, are protected by the
38  * list structure's lock.
39  */
40 static struct {
41 	struct list_head head;
42 	spinlock_t lock; /* Spinlock for context list operations */
43 } ctx_list = {
44 	.head = LIST_HEAD_INIT(ctx_list.head),
45 	.lock = __SPIN_LOCK_UNLOCKED(ctx_list.lock),
46 };
47 
48 /* Used by contexts that did not set up notify flag pointers */
49 static bool ctx_dummy_notify;
50 
ctx_signal_notify(struct vmci_ctx * context)51 static void ctx_signal_notify(struct vmci_ctx *context)
52 {
53 	*context->notify = true;
54 }
55 
ctx_clear_notify(struct vmci_ctx * context)56 static void ctx_clear_notify(struct vmci_ctx *context)
57 {
58 	*context->notify = false;
59 }
60 
61 /*
62  * If nothing requires the attention of the guest, clears both
63  * notify flag and call.
64  */
ctx_clear_notify_call(struct vmci_ctx * context)65 static void ctx_clear_notify_call(struct vmci_ctx *context)
66 {
67 	if (context->pending_datagrams == 0 &&
68 	    vmci_handle_arr_get_size(context->pending_doorbell_array) == 0)
69 		ctx_clear_notify(context);
70 }
71 
72 /*
73  * Sets the context's notify flag iff datagrams are pending for this
74  * context.  Called from vmci_setup_notify().
75  */
vmci_ctx_check_signal_notify(struct vmci_ctx * context)76 void vmci_ctx_check_signal_notify(struct vmci_ctx *context)
77 {
78 	spin_lock(&context->lock);
79 	if (context->pending_datagrams)
80 		ctx_signal_notify(context);
81 	spin_unlock(&context->lock);
82 }
83 
84 /*
85  * Allocates and initializes a VMCI context.
86  */
vmci_ctx_create(u32 cid,u32 priv_flags,uintptr_t event_hnd,int user_version,const struct cred * cred)87 struct vmci_ctx *vmci_ctx_create(u32 cid, u32 priv_flags,
88 				 uintptr_t event_hnd,
89 				 int user_version,
90 				 const struct cred *cred)
91 {
92 	struct vmci_ctx *context;
93 	int error;
94 
95 	if (cid == VMCI_INVALID_ID) {
96 		pr_devel("Invalid context ID for VMCI context\n");
97 		error = -EINVAL;
98 		goto err_out;
99 	}
100 
101 	if (priv_flags & ~VMCI_PRIVILEGE_ALL_FLAGS) {
102 		pr_devel("Invalid flag (flags=0x%x) for VMCI context\n",
103 			 priv_flags);
104 		error = -EINVAL;
105 		goto err_out;
106 	}
107 
108 	if (user_version == 0) {
109 		pr_devel("Invalid suer_version %d\n", user_version);
110 		error = -EINVAL;
111 		goto err_out;
112 	}
113 
114 	context = kzalloc(sizeof(*context), GFP_KERNEL);
115 	if (!context) {
116 		pr_warn("Failed to allocate memory for VMCI context\n");
117 		error = -EINVAL;
118 		goto err_out;
119 	}
120 
121 	kref_init(&context->kref);
122 	spin_lock_init(&context->lock);
123 	INIT_LIST_HEAD(&context->list_item);
124 	INIT_LIST_HEAD(&context->datagram_queue);
125 	INIT_LIST_HEAD(&context->notifier_list);
126 
127 	/* Initialize host-specific VMCI context. */
128 	init_waitqueue_head(&context->host_context.wait_queue);
129 
130 	context->queue_pair_array =
131 		vmci_handle_arr_create(0, VMCI_MAX_GUEST_QP_COUNT);
132 	if (!context->queue_pair_array) {
133 		error = -ENOMEM;
134 		goto err_free_ctx;
135 	}
136 
137 	context->doorbell_array =
138 		vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
139 	if (!context->doorbell_array) {
140 		error = -ENOMEM;
141 		goto err_free_qp_array;
142 	}
143 
144 	context->pending_doorbell_array =
145 		vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
146 	if (!context->pending_doorbell_array) {
147 		error = -ENOMEM;
148 		goto err_free_db_array;
149 	}
150 
151 	context->user_version = user_version;
152 
153 	context->priv_flags = priv_flags;
154 
155 	if (cred)
156 		context->cred = get_cred(cred);
157 
158 	context->notify = &ctx_dummy_notify;
159 	context->notify_page = NULL;
160 
161 	/*
162 	 * If we collide with an existing context we generate a new
163 	 * and use it instead. The VMX will determine if regeneration
164 	 * is okay. Since there isn't 4B - 16 VMs running on a given
165 	 * host, the below loop will terminate.
166 	 */
167 	spin_lock(&ctx_list.lock);
168 
169 	while (vmci_ctx_exists(cid)) {
170 		/* We reserve the lowest 16 ids for fixed contexts. */
171 		cid = max(cid, VMCI_RESERVED_CID_LIMIT - 1) + 1;
172 		if (cid == VMCI_INVALID_ID)
173 			cid = VMCI_RESERVED_CID_LIMIT;
174 	}
175 	context->cid = cid;
176 
177 	list_add_tail_rcu(&context->list_item, &ctx_list.head);
178 	spin_unlock(&ctx_list.lock);
179 
180 	return context;
181 
182  err_free_db_array:
183 	vmci_handle_arr_destroy(context->doorbell_array);
184  err_free_qp_array:
185 	vmci_handle_arr_destroy(context->queue_pair_array);
186  err_free_ctx:
187 	kfree(context);
188  err_out:
189 	return ERR_PTR(error);
190 }
191 
192 /*
193  * Destroy VMCI context.
194  */
vmci_ctx_destroy(struct vmci_ctx * context)195 void vmci_ctx_destroy(struct vmci_ctx *context)
196 {
197 	spin_lock(&ctx_list.lock);
198 	list_del_rcu(&context->list_item);
199 	spin_unlock(&ctx_list.lock);
200 	synchronize_rcu();
201 
202 	vmci_ctx_put(context);
203 }
204 
205 /*
206  * Fire notification for all contexts interested in given cid.
207  */
ctx_fire_notification(u32 context_id,u32 priv_flags)208 static int ctx_fire_notification(u32 context_id, u32 priv_flags)
209 {
210 	u32 i, array_size;
211 	struct vmci_ctx *sub_ctx;
212 	struct vmci_handle_arr *subscriber_array;
213 	struct vmci_handle context_handle =
214 		vmci_make_handle(context_id, VMCI_EVENT_HANDLER);
215 
216 	/*
217 	 * We create an array to hold the subscribers we find when
218 	 * scanning through all contexts.
219 	 */
220 	subscriber_array = vmci_handle_arr_create(0, VMCI_MAX_CONTEXTS);
221 	if (subscriber_array == NULL)
222 		return VMCI_ERROR_NO_MEM;
223 
224 	/*
225 	 * Scan all contexts to find who is interested in being
226 	 * notified about given contextID.
227 	 */
228 	rcu_read_lock();
229 	list_for_each_entry_rcu(sub_ctx, &ctx_list.head, list_item) {
230 		struct vmci_handle_list *node;
231 
232 		/*
233 		 * We only deliver notifications of the removal of
234 		 * contexts, if the two contexts are allowed to
235 		 * interact.
236 		 */
237 		if (vmci_deny_interaction(priv_flags, sub_ctx->priv_flags))
238 			continue;
239 
240 		list_for_each_entry_rcu(node, &sub_ctx->notifier_list, node) {
241 			if (!vmci_handle_is_equal(node->handle, context_handle))
242 				continue;
243 
244 			vmci_handle_arr_append_entry(&subscriber_array,
245 					vmci_make_handle(sub_ctx->cid,
246 							 VMCI_EVENT_HANDLER));
247 		}
248 	}
249 	rcu_read_unlock();
250 
251 	/* Fire event to all subscribers. */
252 	array_size = vmci_handle_arr_get_size(subscriber_array);
253 	for (i = 0; i < array_size; i++) {
254 		int result;
255 		struct vmci_event_ctx ev;
256 
257 		ev.msg.hdr.dst = vmci_handle_arr_get_entry(subscriber_array, i);
258 		ev.msg.hdr.src = vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID,
259 						  VMCI_CONTEXT_RESOURCE_ID);
260 		ev.msg.hdr.payload_size = sizeof(ev) - sizeof(ev.msg.hdr);
261 		ev.msg.event_data.event = VMCI_EVENT_CTX_REMOVED;
262 		ev.payload.context_id = context_id;
263 
264 		result = vmci_datagram_dispatch(VMCI_HYPERVISOR_CONTEXT_ID,
265 						&ev.msg.hdr, false);
266 		if (result < VMCI_SUCCESS) {
267 			pr_devel("Failed to enqueue event datagram (type=%d) for context (ID=0x%x)\n",
268 				 ev.msg.event_data.event,
269 				 ev.msg.hdr.dst.context);
270 			/* We continue to enqueue on next subscriber. */
271 		}
272 	}
273 	vmci_handle_arr_destroy(subscriber_array);
274 
275 	return VMCI_SUCCESS;
276 }
277 
278 /*
279  * Returns the current number of pending datagrams. The call may
280  * also serve as a synchronization point for the datagram queue,
281  * as no enqueue operations can occur concurrently.
282  */
vmci_ctx_pending_datagrams(u32 cid,u32 * pending)283 int vmci_ctx_pending_datagrams(u32 cid, u32 *pending)
284 {
285 	struct vmci_ctx *context;
286 
287 	context = vmci_ctx_get(cid);
288 	if (context == NULL)
289 		return VMCI_ERROR_INVALID_ARGS;
290 
291 	spin_lock(&context->lock);
292 	if (pending)
293 		*pending = context->pending_datagrams;
294 	spin_unlock(&context->lock);
295 	vmci_ctx_put(context);
296 
297 	return VMCI_SUCCESS;
298 }
299 
300 /*
301  * Queues a VMCI datagram for the appropriate target VM context.
302  */
vmci_ctx_enqueue_datagram(u32 cid,struct vmci_datagram * dg)303 int vmci_ctx_enqueue_datagram(u32 cid, struct vmci_datagram *dg)
304 {
305 	struct vmci_datagram_queue_entry *dq_entry;
306 	struct vmci_ctx *context;
307 	struct vmci_handle dg_src;
308 	size_t vmci_dg_size;
309 
310 	vmci_dg_size = VMCI_DG_SIZE(dg);
311 	if (vmci_dg_size > VMCI_MAX_DG_SIZE) {
312 		pr_devel("Datagram too large (bytes=%Zu)\n", vmci_dg_size);
313 		return VMCI_ERROR_INVALID_ARGS;
314 	}
315 
316 	/* Get the target VM's VMCI context. */
317 	context = vmci_ctx_get(cid);
318 	if (!context) {
319 		pr_devel("Invalid context (ID=0x%x)\n", cid);
320 		return VMCI_ERROR_INVALID_ARGS;
321 	}
322 
323 	/* Allocate guest call entry and add it to the target VM's queue. */
324 	dq_entry = kmalloc(sizeof(*dq_entry), GFP_KERNEL);
325 	if (dq_entry == NULL) {
326 		pr_warn("Failed to allocate memory for datagram\n");
327 		vmci_ctx_put(context);
328 		return VMCI_ERROR_NO_MEM;
329 	}
330 	dq_entry->dg = dg;
331 	dq_entry->dg_size = vmci_dg_size;
332 	dg_src = dg->src;
333 	INIT_LIST_HEAD(&dq_entry->list_item);
334 
335 	spin_lock(&context->lock);
336 
337 	/*
338 	 * We put a higher limit on datagrams from the hypervisor.  If
339 	 * the pending datagram is not from hypervisor, then we check
340 	 * if enqueueing it would exceed the
341 	 * VMCI_MAX_DATAGRAM_QUEUE_SIZE limit on the destination.  If
342 	 * the pending datagram is from hypervisor, we allow it to be
343 	 * queued at the destination side provided we don't reach the
344 	 * VMCI_MAX_DATAGRAM_AND_EVENT_QUEUE_SIZE limit.
345 	 */
346 	if (context->datagram_queue_size + vmci_dg_size >=
347 	    VMCI_MAX_DATAGRAM_QUEUE_SIZE &&
348 	    (!vmci_handle_is_equal(dg_src,
349 				vmci_make_handle
350 				(VMCI_HYPERVISOR_CONTEXT_ID,
351 				 VMCI_CONTEXT_RESOURCE_ID)) ||
352 	     context->datagram_queue_size + vmci_dg_size >=
353 	     VMCI_MAX_DATAGRAM_AND_EVENT_QUEUE_SIZE)) {
354 		spin_unlock(&context->lock);
355 		vmci_ctx_put(context);
356 		kfree(dq_entry);
357 		pr_devel("Context (ID=0x%x) receive queue is full\n", cid);
358 		return VMCI_ERROR_NO_RESOURCES;
359 	}
360 
361 	list_add(&dq_entry->list_item, &context->datagram_queue);
362 	context->pending_datagrams++;
363 	context->datagram_queue_size += vmci_dg_size;
364 	ctx_signal_notify(context);
365 	wake_up(&context->host_context.wait_queue);
366 	spin_unlock(&context->lock);
367 	vmci_ctx_put(context);
368 
369 	return vmci_dg_size;
370 }
371 
372 /*
373  * Verifies whether a context with the specified context ID exists.
374  * FIXME: utility is dubious as no decisions can be reliably made
375  * using this data as context can appear and disappear at any time.
376  */
vmci_ctx_exists(u32 cid)377 bool vmci_ctx_exists(u32 cid)
378 {
379 	struct vmci_ctx *context;
380 	bool exists = false;
381 
382 	rcu_read_lock();
383 
384 	list_for_each_entry_rcu(context, &ctx_list.head, list_item) {
385 		if (context->cid == cid) {
386 			exists = true;
387 			break;
388 		}
389 	}
390 
391 	rcu_read_unlock();
392 	return exists;
393 }
394 
395 /*
396  * Retrieves VMCI context corresponding to the given cid.
397  */
vmci_ctx_get(u32 cid)398 struct vmci_ctx *vmci_ctx_get(u32 cid)
399 {
400 	struct vmci_ctx *c, *context = NULL;
401 
402 	if (cid == VMCI_INVALID_ID)
403 		return NULL;
404 
405 	rcu_read_lock();
406 	list_for_each_entry_rcu(c, &ctx_list.head, list_item) {
407 		if (c->cid == cid) {
408 			/*
409 			 * The context owner drops its own reference to the
410 			 * context only after removing it from the list and
411 			 * waiting for RCU grace period to expire. This
412 			 * means that we are not about to increase the
413 			 * reference count of something that is in the
414 			 * process of being destroyed.
415 			 */
416 			context = c;
417 			kref_get(&context->kref);
418 			break;
419 		}
420 	}
421 	rcu_read_unlock();
422 
423 	return context;
424 }
425 
426 /*
427  * Deallocates all parts of a context data structure. This
428  * function doesn't lock the context, because it assumes that
429  * the caller was holding the last reference to context.
430  */
ctx_free_ctx(struct kref * kref)431 static void ctx_free_ctx(struct kref *kref)
432 {
433 	struct vmci_ctx *context = container_of(kref, struct vmci_ctx, kref);
434 	struct vmci_datagram_queue_entry *dq_entry, *dq_entry_tmp;
435 	struct vmci_handle temp_handle;
436 	struct vmci_handle_list *notifier, *tmp;
437 
438 	/*
439 	 * Fire event to all contexts interested in knowing this
440 	 * context is dying.
441 	 */
442 	ctx_fire_notification(context->cid, context->priv_flags);
443 
444 	/*
445 	 * Cleanup all queue pair resources attached to context.  If
446 	 * the VM dies without cleaning up, this code will make sure
447 	 * that no resources are leaked.
448 	 */
449 	temp_handle = vmci_handle_arr_get_entry(context->queue_pair_array, 0);
450 	while (!vmci_handle_is_equal(temp_handle, VMCI_INVALID_HANDLE)) {
451 		if (vmci_qp_broker_detach(temp_handle,
452 					  context) < VMCI_SUCCESS) {
453 			/*
454 			 * When vmci_qp_broker_detach() succeeds it
455 			 * removes the handle from the array.  If
456 			 * detach fails, we must remove the handle
457 			 * ourselves.
458 			 */
459 			vmci_handle_arr_remove_entry(context->queue_pair_array,
460 						     temp_handle);
461 		}
462 		temp_handle =
463 		    vmci_handle_arr_get_entry(context->queue_pair_array, 0);
464 	}
465 
466 	/*
467 	 * It is fine to destroy this without locking the callQueue, as
468 	 * this is the only thread having a reference to the context.
469 	 */
470 	list_for_each_entry_safe(dq_entry, dq_entry_tmp,
471 				 &context->datagram_queue, list_item) {
472 		WARN_ON(dq_entry->dg_size != VMCI_DG_SIZE(dq_entry->dg));
473 		list_del(&dq_entry->list_item);
474 		kfree(dq_entry->dg);
475 		kfree(dq_entry);
476 	}
477 
478 	list_for_each_entry_safe(notifier, tmp,
479 				 &context->notifier_list, node) {
480 		list_del(&notifier->node);
481 		kfree(notifier);
482 	}
483 
484 	vmci_handle_arr_destroy(context->queue_pair_array);
485 	vmci_handle_arr_destroy(context->doorbell_array);
486 	vmci_handle_arr_destroy(context->pending_doorbell_array);
487 	vmci_ctx_unset_notify(context);
488 	if (context->cred)
489 		put_cred(context->cred);
490 	kfree(context);
491 }
492 
493 /*
494  * Drops reference to VMCI context. If this is the last reference to
495  * the context it will be deallocated. A context is created with
496  * a reference count of one, and on destroy, it is removed from
497  * the context list before its reference count is decremented. Thus,
498  * if we reach zero, we are sure that nobody else are about to increment
499  * it (they need the entry in the context list for that), and so there
500  * is no need for locking.
501  */
vmci_ctx_put(struct vmci_ctx * context)502 void vmci_ctx_put(struct vmci_ctx *context)
503 {
504 	kref_put(&context->kref, ctx_free_ctx);
505 }
506 
507 /*
508  * Dequeues the next datagram and returns it to caller.
509  * The caller passes in a pointer to the max size datagram
510  * it can handle and the datagram is only unqueued if the
511  * size is less than max_size. If larger max_size is set to
512  * the size of the datagram to give the caller a chance to
513  * set up a larger buffer for the guestcall.
514  */
vmci_ctx_dequeue_datagram(struct vmci_ctx * context,size_t * max_size,struct vmci_datagram ** dg)515 int vmci_ctx_dequeue_datagram(struct vmci_ctx *context,
516 			      size_t *max_size,
517 			      struct vmci_datagram **dg)
518 {
519 	struct vmci_datagram_queue_entry *dq_entry;
520 	struct list_head *list_item;
521 	int rv;
522 
523 	/* Dequeue the next datagram entry. */
524 	spin_lock(&context->lock);
525 	if (context->pending_datagrams == 0) {
526 		ctx_clear_notify_call(context);
527 		spin_unlock(&context->lock);
528 		pr_devel("No datagrams pending\n");
529 		return VMCI_ERROR_NO_MORE_DATAGRAMS;
530 	}
531 
532 	list_item = context->datagram_queue.next;
533 
534 	dq_entry =
535 	    list_entry(list_item, struct vmci_datagram_queue_entry, list_item);
536 
537 	/* Check size of caller's buffer. */
538 	if (*max_size < dq_entry->dg_size) {
539 		*max_size = dq_entry->dg_size;
540 		spin_unlock(&context->lock);
541 		pr_devel("Caller's buffer should be at least (size=%u bytes)\n",
542 			 (u32) *max_size);
543 		return VMCI_ERROR_NO_MEM;
544 	}
545 
546 	list_del(list_item);
547 	context->pending_datagrams--;
548 	context->datagram_queue_size -= dq_entry->dg_size;
549 	if (context->pending_datagrams == 0) {
550 		ctx_clear_notify_call(context);
551 		rv = VMCI_SUCCESS;
552 	} else {
553 		/*
554 		 * Return the size of the next datagram.
555 		 */
556 		struct vmci_datagram_queue_entry *next_entry;
557 
558 		list_item = context->datagram_queue.next;
559 		next_entry =
560 		    list_entry(list_item, struct vmci_datagram_queue_entry,
561 			       list_item);
562 
563 		/*
564 		 * The following size_t -> int truncation is fine as
565 		 * the maximum size of a (routable) datagram is 68KB.
566 		 */
567 		rv = (int)next_entry->dg_size;
568 	}
569 	spin_unlock(&context->lock);
570 
571 	/* Caller must free datagram. */
572 	*dg = dq_entry->dg;
573 	dq_entry->dg = NULL;
574 	kfree(dq_entry);
575 
576 	return rv;
577 }
578 
579 /*
580  * Reverts actions set up by vmci_setup_notify().  Unmaps and unlocks the
581  * page mapped/locked by vmci_setup_notify().
582  */
vmci_ctx_unset_notify(struct vmci_ctx * context)583 void vmci_ctx_unset_notify(struct vmci_ctx *context)
584 {
585 	struct page *notify_page;
586 
587 	spin_lock(&context->lock);
588 
589 	notify_page = context->notify_page;
590 	context->notify = &ctx_dummy_notify;
591 	context->notify_page = NULL;
592 
593 	spin_unlock(&context->lock);
594 
595 	if (notify_page) {
596 		kunmap(notify_page);
597 		put_page(notify_page);
598 	}
599 }
600 
601 /*
602  * Add remote_cid to list of contexts current contexts wants
603  * notifications from/about.
604  */
vmci_ctx_add_notification(u32 context_id,u32 remote_cid)605 int vmci_ctx_add_notification(u32 context_id, u32 remote_cid)
606 {
607 	struct vmci_ctx *context;
608 	struct vmci_handle_list *notifier, *n;
609 	int result;
610 	bool exists = false;
611 
612 	context = vmci_ctx_get(context_id);
613 	if (!context)
614 		return VMCI_ERROR_NOT_FOUND;
615 
616 	if (VMCI_CONTEXT_IS_VM(context_id) && VMCI_CONTEXT_IS_VM(remote_cid)) {
617 		pr_devel("Context removed notifications for other VMs not supported (src=0x%x, remote=0x%x)\n",
618 			 context_id, remote_cid);
619 		result = VMCI_ERROR_DST_UNREACHABLE;
620 		goto out;
621 	}
622 
623 	if (context->priv_flags & VMCI_PRIVILEGE_FLAG_RESTRICTED) {
624 		result = VMCI_ERROR_NO_ACCESS;
625 		goto out;
626 	}
627 
628 	notifier = kmalloc(sizeof(struct vmci_handle_list), GFP_KERNEL);
629 	if (!notifier) {
630 		result = VMCI_ERROR_NO_MEM;
631 		goto out;
632 	}
633 
634 	INIT_LIST_HEAD(&notifier->node);
635 	notifier->handle = vmci_make_handle(remote_cid, VMCI_EVENT_HANDLER);
636 
637 	spin_lock(&context->lock);
638 
639 	if (context->n_notifiers < VMCI_MAX_CONTEXTS) {
640 		list_for_each_entry(n, &context->notifier_list, node) {
641 			if (vmci_handle_is_equal(n->handle, notifier->handle)) {
642 				exists = true;
643 				break;
644 			}
645 		}
646 
647 		if (exists) {
648 			kfree(notifier);
649 			result = VMCI_ERROR_ALREADY_EXISTS;
650 		} else {
651 			list_add_tail_rcu(&notifier->node,
652 					  &context->notifier_list);
653 			context->n_notifiers++;
654 			result = VMCI_SUCCESS;
655 		}
656 	} else {
657 		kfree(notifier);
658 		result = VMCI_ERROR_NO_MEM;
659 	}
660 
661 	spin_unlock(&context->lock);
662 
663  out:
664 	vmci_ctx_put(context);
665 	return result;
666 }
667 
668 /*
669  * Remove remote_cid from current context's list of contexts it is
670  * interested in getting notifications from/about.
671  */
vmci_ctx_remove_notification(u32 context_id,u32 remote_cid)672 int vmci_ctx_remove_notification(u32 context_id, u32 remote_cid)
673 {
674 	struct vmci_ctx *context;
675 	struct vmci_handle_list *notifier, *tmp;
676 	struct vmci_handle handle;
677 	bool found = false;
678 
679 	context = vmci_ctx_get(context_id);
680 	if (!context)
681 		return VMCI_ERROR_NOT_FOUND;
682 
683 	handle = vmci_make_handle(remote_cid, VMCI_EVENT_HANDLER);
684 
685 	spin_lock(&context->lock);
686 	list_for_each_entry_safe(notifier, tmp,
687 				 &context->notifier_list, node) {
688 		if (vmci_handle_is_equal(notifier->handle, handle)) {
689 			list_del_rcu(&notifier->node);
690 			context->n_notifiers--;
691 			found = true;
692 			break;
693 		}
694 	}
695 	spin_unlock(&context->lock);
696 
697 	if (found) {
698 		synchronize_rcu();
699 		kfree(notifier);
700 	}
701 
702 	vmci_ctx_put(context);
703 
704 	return found ? VMCI_SUCCESS : VMCI_ERROR_NOT_FOUND;
705 }
706 
vmci_ctx_get_chkpt_notifiers(struct vmci_ctx * context,u32 * buf_size,void ** pbuf)707 static int vmci_ctx_get_chkpt_notifiers(struct vmci_ctx *context,
708 					u32 *buf_size, void **pbuf)
709 {
710 	u32 *notifiers;
711 	size_t data_size;
712 	struct vmci_handle_list *entry;
713 	int i = 0;
714 
715 	if (context->n_notifiers == 0) {
716 		*buf_size = 0;
717 		*pbuf = NULL;
718 		return VMCI_SUCCESS;
719 	}
720 
721 	data_size = context->n_notifiers * sizeof(*notifiers);
722 	if (*buf_size < data_size) {
723 		*buf_size = data_size;
724 		return VMCI_ERROR_MORE_DATA;
725 	}
726 
727 	notifiers = kmalloc(data_size, GFP_ATOMIC); /* FIXME: want GFP_KERNEL */
728 	if (!notifiers)
729 		return VMCI_ERROR_NO_MEM;
730 
731 	list_for_each_entry(entry, &context->notifier_list, node)
732 		notifiers[i++] = entry->handle.context;
733 
734 	*buf_size = data_size;
735 	*pbuf = notifiers;
736 	return VMCI_SUCCESS;
737 }
738 
vmci_ctx_get_chkpt_doorbells(struct vmci_ctx * context,u32 * buf_size,void ** pbuf)739 static int vmci_ctx_get_chkpt_doorbells(struct vmci_ctx *context,
740 					u32 *buf_size, void **pbuf)
741 {
742 	struct dbell_cpt_state *dbells;
743 	u32 i, n_doorbells;
744 
745 	n_doorbells = vmci_handle_arr_get_size(context->doorbell_array);
746 	if (n_doorbells > 0) {
747 		size_t data_size = n_doorbells * sizeof(*dbells);
748 		if (*buf_size < data_size) {
749 			*buf_size = data_size;
750 			return VMCI_ERROR_MORE_DATA;
751 		}
752 
753 		dbells = kzalloc(data_size, GFP_ATOMIC);
754 		if (!dbells)
755 			return VMCI_ERROR_NO_MEM;
756 
757 		for (i = 0; i < n_doorbells; i++)
758 			dbells[i].handle = vmci_handle_arr_get_entry(
759 						context->doorbell_array, i);
760 
761 		*buf_size = data_size;
762 		*pbuf = dbells;
763 	} else {
764 		*buf_size = 0;
765 		*pbuf = NULL;
766 	}
767 
768 	return VMCI_SUCCESS;
769 }
770 
771 /*
772  * Get current context's checkpoint state of given type.
773  */
vmci_ctx_get_chkpt_state(u32 context_id,u32 cpt_type,u32 * buf_size,void ** pbuf)774 int vmci_ctx_get_chkpt_state(u32 context_id,
775 			     u32 cpt_type,
776 			     u32 *buf_size,
777 			     void **pbuf)
778 {
779 	struct vmci_ctx *context;
780 	int result;
781 
782 	context = vmci_ctx_get(context_id);
783 	if (!context)
784 		return VMCI_ERROR_NOT_FOUND;
785 
786 	spin_lock(&context->lock);
787 
788 	switch (cpt_type) {
789 	case VMCI_NOTIFICATION_CPT_STATE:
790 		result = vmci_ctx_get_chkpt_notifiers(context, buf_size, pbuf);
791 		break;
792 
793 	case VMCI_WELLKNOWN_CPT_STATE:
794 		/*
795 		 * For compatibility with VMX'en with VM to VM communication, we
796 		 * always return zero wellknown handles.
797 		 */
798 
799 		*buf_size = 0;
800 		*pbuf = NULL;
801 		result = VMCI_SUCCESS;
802 		break;
803 
804 	case VMCI_DOORBELL_CPT_STATE:
805 		result = vmci_ctx_get_chkpt_doorbells(context, buf_size, pbuf);
806 		break;
807 
808 	default:
809 		pr_devel("Invalid cpt state (type=%d)\n", cpt_type);
810 		result = VMCI_ERROR_INVALID_ARGS;
811 		break;
812 	}
813 
814 	spin_unlock(&context->lock);
815 	vmci_ctx_put(context);
816 
817 	return result;
818 }
819 
820 /*
821  * Set current context's checkpoint state of given type.
822  */
vmci_ctx_set_chkpt_state(u32 context_id,u32 cpt_type,u32 buf_size,void * cpt_buf)823 int vmci_ctx_set_chkpt_state(u32 context_id,
824 			     u32 cpt_type,
825 			     u32 buf_size,
826 			     void *cpt_buf)
827 {
828 	u32 i;
829 	u32 current_id;
830 	int result = VMCI_SUCCESS;
831 	u32 num_ids = buf_size / sizeof(u32);
832 
833 	if (cpt_type == VMCI_WELLKNOWN_CPT_STATE && num_ids > 0) {
834 		/*
835 		 * We would end up here if VMX with VM to VM communication
836 		 * attempts to restore a checkpoint with wellknown handles.
837 		 */
838 		pr_warn("Attempt to restore checkpoint with obsolete wellknown handles\n");
839 		return VMCI_ERROR_OBSOLETE;
840 	}
841 
842 	if (cpt_type != VMCI_NOTIFICATION_CPT_STATE) {
843 		pr_devel("Invalid cpt state (type=%d)\n", cpt_type);
844 		return VMCI_ERROR_INVALID_ARGS;
845 	}
846 
847 	for (i = 0; i < num_ids && result == VMCI_SUCCESS; i++) {
848 		current_id = ((u32 *)cpt_buf)[i];
849 		result = vmci_ctx_add_notification(context_id, current_id);
850 		if (result != VMCI_SUCCESS)
851 			break;
852 	}
853 	if (result != VMCI_SUCCESS)
854 		pr_devel("Failed to set cpt state (type=%d) (error=%d)\n",
855 			 cpt_type, result);
856 
857 	return result;
858 }
859 
860 /*
861  * Retrieves the specified context's pending notifications in the
862  * form of a handle array. The handle arrays returned are the
863  * actual data - not a copy and should not be modified by the
864  * caller. They must be released using
865  * vmci_ctx_rcv_notifications_release.
866  */
vmci_ctx_rcv_notifications_get(u32 context_id,struct vmci_handle_arr ** db_handle_array,struct vmci_handle_arr ** qp_handle_array)867 int vmci_ctx_rcv_notifications_get(u32 context_id,
868 				   struct vmci_handle_arr **db_handle_array,
869 				   struct vmci_handle_arr **qp_handle_array)
870 {
871 	struct vmci_ctx *context;
872 	int result = VMCI_SUCCESS;
873 
874 	context = vmci_ctx_get(context_id);
875 	if (context == NULL)
876 		return VMCI_ERROR_NOT_FOUND;
877 
878 	spin_lock(&context->lock);
879 
880 	*db_handle_array = context->pending_doorbell_array;
881 	context->pending_doorbell_array =
882 		vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
883 	if (!context->pending_doorbell_array) {
884 		context->pending_doorbell_array = *db_handle_array;
885 		*db_handle_array = NULL;
886 		result = VMCI_ERROR_NO_MEM;
887 	}
888 	*qp_handle_array = NULL;
889 
890 	spin_unlock(&context->lock);
891 	vmci_ctx_put(context);
892 
893 	return result;
894 }
895 
896 /*
897  * Releases handle arrays with pending notifications previously
898  * retrieved using vmci_ctx_rcv_notifications_get. If the
899  * notifications were not successfully handed over to the guest,
900  * success must be false.
901  */
vmci_ctx_rcv_notifications_release(u32 context_id,struct vmci_handle_arr * db_handle_array,struct vmci_handle_arr * qp_handle_array,bool success)902 void vmci_ctx_rcv_notifications_release(u32 context_id,
903 					struct vmci_handle_arr *db_handle_array,
904 					struct vmci_handle_arr *qp_handle_array,
905 					bool success)
906 {
907 	struct vmci_ctx *context = vmci_ctx_get(context_id);
908 
909 	spin_lock(&context->lock);
910 	if (!success) {
911 		struct vmci_handle handle;
912 
913 		/*
914 		 * New notifications may have been added while we were not
915 		 * holding the context lock, so we transfer any new pending
916 		 * doorbell notifications to the old array, and reinstate the
917 		 * old array.
918 		 */
919 
920 		handle = vmci_handle_arr_remove_tail(
921 					context->pending_doorbell_array);
922 		while (!vmci_handle_is_invalid(handle)) {
923 			if (!vmci_handle_arr_has_entry(db_handle_array,
924 						       handle)) {
925 				vmci_handle_arr_append_entry(
926 						&db_handle_array, handle);
927 			}
928 			handle = vmci_handle_arr_remove_tail(
929 					context->pending_doorbell_array);
930 		}
931 		vmci_handle_arr_destroy(context->pending_doorbell_array);
932 		context->pending_doorbell_array = db_handle_array;
933 		db_handle_array = NULL;
934 	} else {
935 		ctx_clear_notify_call(context);
936 	}
937 	spin_unlock(&context->lock);
938 	vmci_ctx_put(context);
939 
940 	if (db_handle_array)
941 		vmci_handle_arr_destroy(db_handle_array);
942 
943 	if (qp_handle_array)
944 		vmci_handle_arr_destroy(qp_handle_array);
945 }
946 
947 /*
948  * Registers that a new doorbell handle has been allocated by the
949  * context. Only doorbell handles registered can be notified.
950  */
vmci_ctx_dbell_create(u32 context_id,struct vmci_handle handle)951 int vmci_ctx_dbell_create(u32 context_id, struct vmci_handle handle)
952 {
953 	struct vmci_ctx *context;
954 	int result;
955 
956 	if (context_id == VMCI_INVALID_ID || vmci_handle_is_invalid(handle))
957 		return VMCI_ERROR_INVALID_ARGS;
958 
959 	context = vmci_ctx_get(context_id);
960 	if (context == NULL)
961 		return VMCI_ERROR_NOT_FOUND;
962 
963 	spin_lock(&context->lock);
964 	if (!vmci_handle_arr_has_entry(context->doorbell_array, handle))
965 		result = vmci_handle_arr_append_entry(&context->doorbell_array,
966 						      handle);
967 	else
968 		result = VMCI_ERROR_DUPLICATE_ENTRY;
969 
970 	spin_unlock(&context->lock);
971 	vmci_ctx_put(context);
972 
973 	return result;
974 }
975 
976 /*
977  * Unregisters a doorbell handle that was previously registered
978  * with vmci_ctx_dbell_create.
979  */
vmci_ctx_dbell_destroy(u32 context_id,struct vmci_handle handle)980 int vmci_ctx_dbell_destroy(u32 context_id, struct vmci_handle handle)
981 {
982 	struct vmci_ctx *context;
983 	struct vmci_handle removed_handle;
984 
985 	if (context_id == VMCI_INVALID_ID || vmci_handle_is_invalid(handle))
986 		return VMCI_ERROR_INVALID_ARGS;
987 
988 	context = vmci_ctx_get(context_id);
989 	if (context == NULL)
990 		return VMCI_ERROR_NOT_FOUND;
991 
992 	spin_lock(&context->lock);
993 	removed_handle =
994 	    vmci_handle_arr_remove_entry(context->doorbell_array, handle);
995 	vmci_handle_arr_remove_entry(context->pending_doorbell_array, handle);
996 	spin_unlock(&context->lock);
997 
998 	vmci_ctx_put(context);
999 
1000 	return vmci_handle_is_invalid(removed_handle) ?
1001 	    VMCI_ERROR_NOT_FOUND : VMCI_SUCCESS;
1002 }
1003 
1004 /*
1005  * Unregisters all doorbell handles that were previously
1006  * registered with vmci_ctx_dbell_create.
1007  */
vmci_ctx_dbell_destroy_all(u32 context_id)1008 int vmci_ctx_dbell_destroy_all(u32 context_id)
1009 {
1010 	struct vmci_ctx *context;
1011 	struct vmci_handle handle;
1012 
1013 	if (context_id == VMCI_INVALID_ID)
1014 		return VMCI_ERROR_INVALID_ARGS;
1015 
1016 	context = vmci_ctx_get(context_id);
1017 	if (context == NULL)
1018 		return VMCI_ERROR_NOT_FOUND;
1019 
1020 	spin_lock(&context->lock);
1021 	do {
1022 		struct vmci_handle_arr *arr = context->doorbell_array;
1023 		handle = vmci_handle_arr_remove_tail(arr);
1024 	} while (!vmci_handle_is_invalid(handle));
1025 	do {
1026 		struct vmci_handle_arr *arr = context->pending_doorbell_array;
1027 		handle = vmci_handle_arr_remove_tail(arr);
1028 	} while (!vmci_handle_is_invalid(handle));
1029 	spin_unlock(&context->lock);
1030 
1031 	vmci_ctx_put(context);
1032 
1033 	return VMCI_SUCCESS;
1034 }
1035 
1036 /*
1037  * Registers a notification of a doorbell handle initiated by the
1038  * specified source context. The notification of doorbells are
1039  * subject to the same isolation rules as datagram delivery. To
1040  * allow host side senders of notifications a finer granularity
1041  * of sender rights than those assigned to the sending context
1042  * itself, the host context is required to specify a different
1043  * set of privilege flags that will override the privileges of
1044  * the source context.
1045  */
vmci_ctx_notify_dbell(u32 src_cid,struct vmci_handle handle,u32 src_priv_flags)1046 int vmci_ctx_notify_dbell(u32 src_cid,
1047 			  struct vmci_handle handle,
1048 			  u32 src_priv_flags)
1049 {
1050 	struct vmci_ctx *dst_context;
1051 	int result;
1052 
1053 	if (vmci_handle_is_invalid(handle))
1054 		return VMCI_ERROR_INVALID_ARGS;
1055 
1056 	/* Get the target VM's VMCI context. */
1057 	dst_context = vmci_ctx_get(handle.context);
1058 	if (!dst_context) {
1059 		pr_devel("Invalid context (ID=0x%x)\n", handle.context);
1060 		return VMCI_ERROR_NOT_FOUND;
1061 	}
1062 
1063 	if (src_cid != handle.context) {
1064 		u32 dst_priv_flags;
1065 
1066 		if (VMCI_CONTEXT_IS_VM(src_cid) &&
1067 		    VMCI_CONTEXT_IS_VM(handle.context)) {
1068 			pr_devel("Doorbell notification from VM to VM not supported (src=0x%x, dst=0x%x)\n",
1069 				 src_cid, handle.context);
1070 			result = VMCI_ERROR_DST_UNREACHABLE;
1071 			goto out;
1072 		}
1073 
1074 		result = vmci_dbell_get_priv_flags(handle, &dst_priv_flags);
1075 		if (result < VMCI_SUCCESS) {
1076 			pr_warn("Failed to get privilege flags for destination (handle=0x%x:0x%x)\n",
1077 				handle.context, handle.resource);
1078 			goto out;
1079 		}
1080 
1081 		if (src_cid != VMCI_HOST_CONTEXT_ID ||
1082 		    src_priv_flags == VMCI_NO_PRIVILEGE_FLAGS) {
1083 			src_priv_flags = vmci_context_get_priv_flags(src_cid);
1084 		}
1085 
1086 		if (vmci_deny_interaction(src_priv_flags, dst_priv_flags)) {
1087 			result = VMCI_ERROR_NO_ACCESS;
1088 			goto out;
1089 		}
1090 	}
1091 
1092 	if (handle.context == VMCI_HOST_CONTEXT_ID) {
1093 		result = vmci_dbell_host_context_notify(src_cid, handle);
1094 	} else {
1095 		spin_lock(&dst_context->lock);
1096 
1097 		if (!vmci_handle_arr_has_entry(dst_context->doorbell_array,
1098 					       handle)) {
1099 			result = VMCI_ERROR_NOT_FOUND;
1100 		} else {
1101 			if (!vmci_handle_arr_has_entry(
1102 					dst_context->pending_doorbell_array,
1103 					handle)) {
1104 				result = vmci_handle_arr_append_entry(
1105 					&dst_context->pending_doorbell_array,
1106 					handle);
1107 				if (result == VMCI_SUCCESS) {
1108 					ctx_signal_notify(dst_context);
1109 					wake_up(&dst_context->host_context.wait_queue);
1110 				}
1111 			} else {
1112 				result = VMCI_SUCCESS;
1113 			}
1114 		}
1115 		spin_unlock(&dst_context->lock);
1116 	}
1117 
1118  out:
1119 	vmci_ctx_put(dst_context);
1120 
1121 	return result;
1122 }
1123 
vmci_ctx_supports_host_qp(struct vmci_ctx * context)1124 bool vmci_ctx_supports_host_qp(struct vmci_ctx *context)
1125 {
1126 	return context && context->user_version >= VMCI_VERSION_HOSTQP;
1127 }
1128 
1129 /*
1130  * Registers that a new queue pair handle has been allocated by
1131  * the context.
1132  */
vmci_ctx_qp_create(struct vmci_ctx * context,struct vmci_handle handle)1133 int vmci_ctx_qp_create(struct vmci_ctx *context, struct vmci_handle handle)
1134 {
1135 	int result;
1136 
1137 	if (context == NULL || vmci_handle_is_invalid(handle))
1138 		return VMCI_ERROR_INVALID_ARGS;
1139 
1140 	if (!vmci_handle_arr_has_entry(context->queue_pair_array, handle))
1141 		result = vmci_handle_arr_append_entry(
1142 			&context->queue_pair_array, handle);
1143 	else
1144 		result = VMCI_ERROR_DUPLICATE_ENTRY;
1145 
1146 	return result;
1147 }
1148 
1149 /*
1150  * Unregisters a queue pair handle that was previously registered
1151  * with vmci_ctx_qp_create.
1152  */
vmci_ctx_qp_destroy(struct vmci_ctx * context,struct vmci_handle handle)1153 int vmci_ctx_qp_destroy(struct vmci_ctx *context, struct vmci_handle handle)
1154 {
1155 	struct vmci_handle hndl;
1156 
1157 	if (context == NULL || vmci_handle_is_invalid(handle))
1158 		return VMCI_ERROR_INVALID_ARGS;
1159 
1160 	hndl = vmci_handle_arr_remove_entry(context->queue_pair_array, handle);
1161 
1162 	return vmci_handle_is_invalid(hndl) ?
1163 		VMCI_ERROR_NOT_FOUND : VMCI_SUCCESS;
1164 }
1165 
1166 /*
1167  * Determines whether a given queue pair handle is registered
1168  * with the given context.
1169  */
vmci_ctx_qp_exists(struct vmci_ctx * context,struct vmci_handle handle)1170 bool vmci_ctx_qp_exists(struct vmci_ctx *context, struct vmci_handle handle)
1171 {
1172 	if (context == NULL || vmci_handle_is_invalid(handle))
1173 		return false;
1174 
1175 	return vmci_handle_arr_has_entry(context->queue_pair_array, handle);
1176 }
1177 
1178 /*
1179  * vmci_context_get_priv_flags() - Retrieve privilege flags.
1180  * @context_id: The context ID of the VMCI context.
1181  *
1182  * Retrieves privilege flags of the given VMCI context ID.
1183  */
vmci_context_get_priv_flags(u32 context_id)1184 u32 vmci_context_get_priv_flags(u32 context_id)
1185 {
1186 	if (vmci_host_code_active()) {
1187 		u32 flags;
1188 		struct vmci_ctx *context;
1189 
1190 		context = vmci_ctx_get(context_id);
1191 		if (!context)
1192 			return VMCI_LEAST_PRIVILEGE_FLAGS;
1193 
1194 		flags = context->priv_flags;
1195 		vmci_ctx_put(context);
1196 		return flags;
1197 	}
1198 	return VMCI_NO_PRIVILEGE_FLAGS;
1199 }
1200 EXPORT_SYMBOL_GPL(vmci_context_get_priv_flags);
1201 
1202 /*
1203  * vmci_is_context_owner() - Determimnes if user is the context owner
1204  * @context_id: The context ID of the VMCI context.
1205  * @uid:        The host user id (real kernel value).
1206  *
1207  * Determines whether a given UID is the owner of given VMCI context.
1208  */
vmci_is_context_owner(u32 context_id,kuid_t uid)1209 bool vmci_is_context_owner(u32 context_id, kuid_t uid)
1210 {
1211 	bool is_owner = false;
1212 
1213 	if (vmci_host_code_active()) {
1214 		struct vmci_ctx *context = vmci_ctx_get(context_id);
1215 		if (context) {
1216 			if (context->cred)
1217 				is_owner = uid_eq(context->cred->uid, uid);
1218 			vmci_ctx_put(context);
1219 		}
1220 	}
1221 
1222 	return is_owner;
1223 }
1224 EXPORT_SYMBOL_GPL(vmci_is_context_owner);
1225