brintos

brintos / linux-shallow public Read only

0
0
Text · 49.2 KiB · c6e9855 Raw
1855 lines · c
1/* SPDX-License-Identifier: (GPL-2.0 OR CDDL-1.0) */2/*3 * vboxguest core guest-device handling code, VBoxGuest.cpp in upstream svn.4 *5 * Copyright (C) 2007-2016 Oracle Corporation6 */7 8#include <linux/device.h>9#include <linux/io.h>10#include <linux/mm.h>11#include <linux/sched.h>12#include <linux/sizes.h>13#include <linux/slab.h>14#include <linux/vbox_err.h>15#include <linux/vbox_utils.h>16#include <linux/vmalloc.h>17#include "vboxguest_core.h"18#include "vboxguest_version.h"19 20/* Get the pointer to the first HGCM parameter. */21#define VBG_IOCTL_HGCM_CALL_PARMS(a) \22	((struct vmmdev_hgcm_function_parameter *)( \23		(u8 *)(a) + sizeof(struct vbg_ioctl_hgcm_call)))24/* Get the pointer to the first HGCM parameter in a 32-bit request. */25#define VBG_IOCTL_HGCM_CALL_PARMS32(a) \26	((struct vmmdev_hgcm_function_parameter32 *)( \27		(u8 *)(a) + sizeof(struct vbg_ioctl_hgcm_call)))28 29#define GUEST_MAPPINGS_TRIES	530 31#define VBG_KERNEL_REQUEST \32	(VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV | \33	 VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN)34 35/**36 * vbg_guest_mappings_init - Reserves memory in which the VMM can37 *	relocate any guest mappings that are floating around.38 * @gdev:		The Guest extension device.39 *40 * This operation is a little bit tricky since the VMM might not accept41 * just any address because of address clashes between the three contexts42 * it operates in, so we try several times.43 *44 * Failure to reserve the guest mappings is ignored.45 */46static void vbg_guest_mappings_init(struct vbg_dev *gdev)47{48	struct vmmdev_hypervisorinfo *req;49	void *guest_mappings[GUEST_MAPPINGS_TRIES];50	struct page **pages = NULL;51	u32 size, hypervisor_size;52	int i, rc;53 54	/* Query the required space. */55	req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_GET_HYPERVISOR_INFO,56			    VBG_KERNEL_REQUEST);57	if (!req)58		return;59 60	req->hypervisor_start = 0;61	req->hypervisor_size = 0;62	rc = vbg_req_perform(gdev, req);63	if (rc < 0)64		goto out;65 66	/*67	 * The VMM will report back if there is nothing it wants to map, like68	 * for instance in VT-x and AMD-V mode.69	 */70	if (req->hypervisor_size == 0)71		goto out;72 73	hypervisor_size = req->hypervisor_size;74	/* Add 4M so that we can align the vmap to 4MiB as the host requires. */75	size = PAGE_ALIGN(req->hypervisor_size) + SZ_4M;76 77	pages = kmalloc_array(size >> PAGE_SHIFT, sizeof(*pages), GFP_KERNEL);78	if (!pages)79		goto out;80 81	gdev->guest_mappings_dummy_page = alloc_page(GFP_HIGHUSER);82	if (!gdev->guest_mappings_dummy_page)83		goto out;84 85	for (i = 0; i < (size >> PAGE_SHIFT); i++)86		pages[i] = gdev->guest_mappings_dummy_page;87 88	/*89	 * Try several times, the VMM might not accept some addresses because90	 * of address clashes between the three contexts.91	 */92	for (i = 0; i < GUEST_MAPPINGS_TRIES; i++) {93		guest_mappings[i] = vmap(pages, (size >> PAGE_SHIFT),94					 VM_MAP, PAGE_KERNEL_RO);95		if (!guest_mappings[i])96			break;97 98		req->header.request_type = VMMDEVREQ_SET_HYPERVISOR_INFO;99		req->header.rc = VERR_INTERNAL_ERROR;100		req->hypervisor_size = hypervisor_size;101		req->hypervisor_start =102			(unsigned long)PTR_ALIGN(guest_mappings[i], SZ_4M);103 104		rc = vbg_req_perform(gdev, req);105		if (rc >= 0) {106			gdev->guest_mappings = guest_mappings[i];107			break;108		}109	}110 111	/* Free vmap's from failed attempts. */112	while (--i >= 0)113		vunmap(guest_mappings[i]);114 115	/* On failure free the dummy-page backing the vmap */116	if (!gdev->guest_mappings) {117		__free_page(gdev->guest_mappings_dummy_page);118		gdev->guest_mappings_dummy_page = NULL;119	}120 121out:122	vbg_req_free(req, sizeof(*req));123	kfree(pages);124}125 126/**127 * vbg_guest_mappings_exit - Undo what vbg_guest_mappings_init did.128 *129 * @gdev:		The Guest extension device.130 */131static void vbg_guest_mappings_exit(struct vbg_dev *gdev)132{133	struct vmmdev_hypervisorinfo *req;134	int rc;135 136	if (!gdev->guest_mappings)137		return;138 139	/*140	 * Tell the host that we're going to free the memory we reserved for141	 * it, the free it up. (Leak the memory if anything goes wrong here.)142	 */143	req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_HYPERVISOR_INFO,144			    VBG_KERNEL_REQUEST);145	if (!req)146		return;147 148	req->hypervisor_start = 0;149	req->hypervisor_size = 0;150 151	rc = vbg_req_perform(gdev, req);152 153	vbg_req_free(req, sizeof(*req));154 155	if (rc < 0) {156		vbg_err("%s error: %d\n", __func__, rc);157		return;158	}159 160	vunmap(gdev->guest_mappings);161	gdev->guest_mappings = NULL;162 163	__free_page(gdev->guest_mappings_dummy_page);164	gdev->guest_mappings_dummy_page = NULL;165}166 167/**168 * vbg_report_guest_info - Report the guest information to the host.169 * @gdev:		The Guest extension device.170 *171 * Return: %0 or negative errno value.172 */173static int vbg_report_guest_info(struct vbg_dev *gdev)174{175	/*176	 * Allocate and fill in the two guest info reports.177	 */178	struct vmmdev_guest_info *req1 = NULL;179	struct vmmdev_guest_info2 *req2 = NULL;180	int rc, ret = -ENOMEM;181 182	req1 = vbg_req_alloc(sizeof(*req1), VMMDEVREQ_REPORT_GUEST_INFO,183			     VBG_KERNEL_REQUEST);184	req2 = vbg_req_alloc(sizeof(*req2), VMMDEVREQ_REPORT_GUEST_INFO2,185			     VBG_KERNEL_REQUEST);186	if (!req1 || !req2)187		goto out_free;188 189	req1->interface_version = VMMDEV_VERSION;190	req1->os_type = VMMDEV_OSTYPE_LINUX26;191#if __BITS_PER_LONG == 64192	req1->os_type |= VMMDEV_OSTYPE_X64;193#endif194 195	req2->additions_major = VBG_VERSION_MAJOR;196	req2->additions_minor = VBG_VERSION_MINOR;197	req2->additions_build = VBG_VERSION_BUILD;198	req2->additions_revision = VBG_SVN_REV;199	req2->additions_features =200		VMMDEV_GUEST_INFO2_ADDITIONS_FEATURES_REQUESTOR_INFO;201	strscpy(req2->name, VBG_VERSION_STRING,202		sizeof(req2->name));203 204	/*205	 * There are two protocols here:206	 *      1. INFO2 + INFO1. Supported by >=3.2.51.207	 *      2. INFO1 and optionally INFO2. The old protocol.208	 *209	 * We try protocol 2 first.  It will fail with VERR_NOT_SUPPORTED210	 * if not supported by the VMMDev (message ordering requirement).211	 */212	rc = vbg_req_perform(gdev, req2);213	if (rc >= 0) {214		rc = vbg_req_perform(gdev, req1);215	} else if (rc == VERR_NOT_SUPPORTED || rc == VERR_NOT_IMPLEMENTED) {216		rc = vbg_req_perform(gdev, req1);217		if (rc >= 0) {218			rc = vbg_req_perform(gdev, req2);219			if (rc == VERR_NOT_IMPLEMENTED)220				rc = VINF_SUCCESS;221		}222	}223	ret = vbg_status_code_to_errno(rc);224 225out_free:226	vbg_req_free(req2, sizeof(*req2));227	vbg_req_free(req1, sizeof(*req1));228	return ret;229}230 231/**232 * vbg_report_driver_status - Report the guest driver status to the host.233 * @gdev:		The Guest extension device.234 * @active:		Flag whether the driver is now active or not.235 *236 * Return: 0 or negative errno value.237 */238static int vbg_report_driver_status(struct vbg_dev *gdev, bool active)239{240	struct vmmdev_guest_status *req;241	int rc;242 243	req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_REPORT_GUEST_STATUS,244			    VBG_KERNEL_REQUEST);245	if (!req)246		return -ENOMEM;247 248	req->facility = VBOXGUEST_FACILITY_TYPE_VBOXGUEST_DRIVER;249	if (active)250		req->status = VBOXGUEST_FACILITY_STATUS_ACTIVE;251	else252		req->status = VBOXGUEST_FACILITY_STATUS_INACTIVE;253	req->flags = 0;254 255	rc = vbg_req_perform(gdev, req);256	if (rc == VERR_NOT_IMPLEMENTED)	/* Compatibility with older hosts. */257		rc = VINF_SUCCESS;258 259	vbg_req_free(req, sizeof(*req));260 261	return vbg_status_code_to_errno(rc);262}263 264/**265 * vbg_balloon_inflate - Inflate the balloon by one chunk. The caller266 * owns the balloon mutex.267 * @gdev:		The Guest extension device.268 * @chunk_idx:		Index of the chunk.269 *270 * Return: %0 or negative errno value.271 */272static int vbg_balloon_inflate(struct vbg_dev *gdev, u32 chunk_idx)273{274	struct vmmdev_memballoon_change *req = gdev->mem_balloon.change_req;275	struct page **pages;276	int i, rc, ret;277 278	pages = kmalloc_array(VMMDEV_MEMORY_BALLOON_CHUNK_PAGES,279			      sizeof(*pages),280			      GFP_KERNEL | __GFP_NOWARN);281	if (!pages)282		return -ENOMEM;283 284	req->header.size = sizeof(*req);285	req->inflate = true;286	req->pages = VMMDEV_MEMORY_BALLOON_CHUNK_PAGES;287 288	for (i = 0; i < VMMDEV_MEMORY_BALLOON_CHUNK_PAGES; i++) {289		pages[i] = alloc_page(GFP_KERNEL | __GFP_NOWARN);290		if (!pages[i]) {291			ret = -ENOMEM;292			goto out_error;293		}294 295		req->phys_page[i] = page_to_phys(pages[i]);296	}297 298	rc = vbg_req_perform(gdev, req);299	if (rc < 0) {300		vbg_err("%s error, rc: %d\n", __func__, rc);301		ret = vbg_status_code_to_errno(rc);302		goto out_error;303	}304 305	gdev->mem_balloon.pages[chunk_idx] = pages;306 307	return 0;308 309out_error:310	while (--i >= 0)311		__free_page(pages[i]);312	kfree(pages);313 314	return ret;315}316 317/**318 * vbg_balloon_deflate - Deflate the balloon by one chunk. The caller319 * owns the balloon mutex.320 * @gdev:		The Guest extension device.321 * @chunk_idx:		Index of the chunk.322 *323 * Return: %0 or negative errno value.324 */325static int vbg_balloon_deflate(struct vbg_dev *gdev, u32 chunk_idx)326{327	struct vmmdev_memballoon_change *req = gdev->mem_balloon.change_req;328	struct page **pages = gdev->mem_balloon.pages[chunk_idx];329	int i, rc;330 331	req->header.size = sizeof(*req);332	req->inflate = false;333	req->pages = VMMDEV_MEMORY_BALLOON_CHUNK_PAGES;334 335	for (i = 0; i < VMMDEV_MEMORY_BALLOON_CHUNK_PAGES; i++)336		req->phys_page[i] = page_to_phys(pages[i]);337 338	rc = vbg_req_perform(gdev, req);339	if (rc < 0) {340		vbg_err("%s error, rc: %d\n", __func__, rc);341		return vbg_status_code_to_errno(rc);342	}343 344	for (i = 0; i < VMMDEV_MEMORY_BALLOON_CHUNK_PAGES; i++)345		__free_page(pages[i]);346	kfree(pages);347	gdev->mem_balloon.pages[chunk_idx] = NULL;348 349	return 0;350}351 352/*353 * Respond to VMMDEV_EVENT_BALLOON_CHANGE_REQUEST events, query the size354 * the host wants the balloon to be and adjust accordingly.355 */356static void vbg_balloon_work(struct work_struct *work)357{358	struct vbg_dev *gdev =359		container_of(work, struct vbg_dev, mem_balloon.work);360	struct vmmdev_memballoon_info *req = gdev->mem_balloon.get_req;361	u32 i, chunks;362	int rc, ret;363 364	/*365	 * Setting this bit means that we request the value from the host and366	 * change the guest memory balloon according to the returned value.367	 */368	req->event_ack = VMMDEV_EVENT_BALLOON_CHANGE_REQUEST;369	rc = vbg_req_perform(gdev, req);370	if (rc < 0) {371		vbg_err("%s error, rc: %d)\n", __func__, rc);372		return;373	}374 375	/*376	 * The host always returns the same maximum amount of chunks, so377	 * we do this once.378	 */379	if (!gdev->mem_balloon.max_chunks) {380		gdev->mem_balloon.pages =381			devm_kcalloc(gdev->dev, req->phys_mem_chunks,382				     sizeof(struct page **), GFP_KERNEL);383		if (!gdev->mem_balloon.pages)384			return;385 386		gdev->mem_balloon.max_chunks = req->phys_mem_chunks;387	}388 389	chunks = req->balloon_chunks;390	if (chunks > gdev->mem_balloon.max_chunks) {391		vbg_err("%s: illegal balloon size %u (max=%u)\n",392			__func__, chunks, gdev->mem_balloon.max_chunks);393		return;394	}395 396	if (chunks > gdev->mem_balloon.chunks) {397		/* inflate */398		for (i = gdev->mem_balloon.chunks; i < chunks; i++) {399			ret = vbg_balloon_inflate(gdev, i);400			if (ret < 0)401				return;402 403			gdev->mem_balloon.chunks++;404		}405	} else {406		/* deflate */407		for (i = gdev->mem_balloon.chunks; i-- > chunks;) {408			ret = vbg_balloon_deflate(gdev, i);409			if (ret < 0)410				return;411 412			gdev->mem_balloon.chunks--;413		}414	}415}416 417/*418 * Callback for heartbeat timer.419 */420static void vbg_heartbeat_timer(struct timer_list *t)421{422	struct vbg_dev *gdev = from_timer(gdev, t, heartbeat_timer);423 424	vbg_req_perform(gdev, gdev->guest_heartbeat_req);425	mod_timer(&gdev->heartbeat_timer,426		  msecs_to_jiffies(gdev->heartbeat_interval_ms));427}428 429/**430 * vbg_heartbeat_host_config - Configure the host to check guest's heartbeat431 *	and get heartbeat interval from the host.432 * @gdev:		The Guest extension device.433 * @enabled:		Set true to enable guest heartbeat checks on host.434 *435 * Return: %0 or negative errno value.436 */437static int vbg_heartbeat_host_config(struct vbg_dev *gdev, bool enabled)438{439	struct vmmdev_heartbeat *req;440	int rc;441 442	req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_HEARTBEAT_CONFIGURE,443			    VBG_KERNEL_REQUEST);444	if (!req)445		return -ENOMEM;446 447	req->enabled = enabled;448	req->interval_ns = 0;449	rc = vbg_req_perform(gdev, req);450	do_div(req->interval_ns, 1000000); /* ns -> ms */451	gdev->heartbeat_interval_ms = req->interval_ns;452	vbg_req_free(req, sizeof(*req));453 454	return vbg_status_code_to_errno(rc);455}456 457/**458 * vbg_heartbeat_init - Initializes the heartbeat timer. This feature459 * may be disabled by the host.460 * @gdev:		The Guest extension device.461 *462 * Return: %0 or negative errno value.463 */464static int vbg_heartbeat_init(struct vbg_dev *gdev)465{466	int ret;467 468	/* Make sure that heartbeat checking is disabled if we fail. */469	ret = vbg_heartbeat_host_config(gdev, false);470	if (ret < 0)471		return ret;472 473	ret = vbg_heartbeat_host_config(gdev, true);474	if (ret < 0)475		return ret;476 477	gdev->guest_heartbeat_req = vbg_req_alloc(478					sizeof(*gdev->guest_heartbeat_req),479					VMMDEVREQ_GUEST_HEARTBEAT,480					VBG_KERNEL_REQUEST);481	if (!gdev->guest_heartbeat_req)482		return -ENOMEM;483 484	vbg_info("%s: Setting up heartbeat to trigger every %d milliseconds\n",485		 __func__, gdev->heartbeat_interval_ms);486	mod_timer(&gdev->heartbeat_timer, 0);487 488	return 0;489}490 491/**492 * vbg_heartbeat_exit - Cleanup heartbeat code, stop HB timer and disable493 *	host heartbeat checking.494 * @gdev:		The Guest extension device.495 */496static void vbg_heartbeat_exit(struct vbg_dev *gdev)497{498	del_timer_sync(&gdev->heartbeat_timer);499	vbg_heartbeat_host_config(gdev, false);500	vbg_req_free(gdev->guest_heartbeat_req,501		     sizeof(*gdev->guest_heartbeat_req));502}503 504/**505 * vbg_track_bit_usage - Applies a change to the bit usage tracker.506 * @tracker:		The bit usage tracker.507 * @changed:		The bits to change.508 * @previous:		The previous value of the bits.509 *510 * Return: %true if the mask changed, %false if not.511 */512static bool vbg_track_bit_usage(struct vbg_bit_usage_tracker *tracker,513				u32 changed, u32 previous)514{515	bool global_change = false;516 517	while (changed) {518		u32 bit = ffs(changed) - 1;519		u32 bitmask = BIT(bit);520 521		if (bitmask & previous) {522			tracker->per_bit_usage[bit] -= 1;523			if (tracker->per_bit_usage[bit] == 0) {524				global_change = true;525				tracker->mask &= ~bitmask;526			}527		} else {528			tracker->per_bit_usage[bit] += 1;529			if (tracker->per_bit_usage[bit] == 1) {530				global_change = true;531				tracker->mask |= bitmask;532			}533		}534 535		changed &= ~bitmask;536	}537 538	return global_change;539}540 541/**542 * vbg_reset_host_event_filter - Init and termination worker for543 *	resetting the (host) event filter on the host544 * @gdev:		   The Guest extension device.545 * @fixed_events:	   Fixed events (init time).546 *547 * Return: %0 or negative errno value.548 */549static int vbg_reset_host_event_filter(struct vbg_dev *gdev,550				       u32 fixed_events)551{552	struct vmmdev_mask *req;553	int rc;554 555	req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_CTL_GUEST_FILTER_MASK,556			    VBG_KERNEL_REQUEST);557	if (!req)558		return -ENOMEM;559 560	req->not_mask = U32_MAX & ~fixed_events;561	req->or_mask = fixed_events;562	rc = vbg_req_perform(gdev, req);563	if (rc < 0)564		vbg_err("%s error, rc: %d\n", __func__, rc);565 566	vbg_req_free(req, sizeof(*req));567	return vbg_status_code_to_errno(rc);568}569 570/**571 * vbg_set_session_event_filter - Changes the event filter mask for the572 *	given session.573 * @gdev:			The Guest extension device.574 * @session:			The session.575 * @or_mask:			The events to add.576 * @not_mask:			The events to remove.577 * @session_termination:	Set if we're called by the session cleanup code.578 *				This tweaks the error handling so we perform579 *				proper session cleanup even if the host580 *				misbehaves.581 *582 * This is called in response to VBG_IOCTL_CHANGE_FILTER_MASK as well as to583 * do session cleanup. Takes the session mutex.584 *585 * Return: 0 or negative errno value.586 */587static int vbg_set_session_event_filter(struct vbg_dev *gdev,588					struct vbg_session *session,589					u32 or_mask, u32 not_mask,590					bool session_termination)591{592	struct vmmdev_mask *req;593	u32 changed, previous;594	int rc, ret = 0;595 596	/*597	 * Allocate a request buffer before taking the spinlock, when598	 * the session is being terminated the requestor is the kernel,599	 * as we're cleaning up.600	 */601	req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_CTL_GUEST_FILTER_MASK,602			    session_termination ? VBG_KERNEL_REQUEST :603						  session->requestor);604	if (!req) {605		if (!session_termination)606			return -ENOMEM;607		/* Ignore allocation failure, we must do session cleanup. */608	}609 610	mutex_lock(&gdev->session_mutex);611 612	/* Apply the changes to the session mask. */613	previous = session->event_filter;614	session->event_filter |= or_mask;615	session->event_filter &= ~not_mask;616 617	/* If anything actually changed, update the global usage counters. */618	changed = previous ^ session->event_filter;619	if (!changed)620		goto out;621 622	vbg_track_bit_usage(&gdev->event_filter_tracker, changed, previous);623	or_mask = gdev->fixed_events | gdev->event_filter_tracker.mask;624 625	if (gdev->event_filter_host == or_mask || !req)626		goto out;627 628	gdev->event_filter_host = or_mask;629	req->or_mask = or_mask;630	req->not_mask = ~or_mask;631	rc = vbg_req_perform(gdev, req);632	if (rc < 0) {633		ret = vbg_status_code_to_errno(rc);634 635		/* Failed, roll back (unless it's session termination time). */636		gdev->event_filter_host = U32_MAX;637		if (session_termination)638			goto out;639 640		vbg_track_bit_usage(&gdev->event_filter_tracker, changed,641				    session->event_filter);642		session->event_filter = previous;643	}644 645out:646	mutex_unlock(&gdev->session_mutex);647	vbg_req_free(req, sizeof(*req));648 649	return ret;650}651 652/**653 * vbg_reset_host_capabilities - Init and termination worker for set654 *	guest capabilities to zero on the host.655 * @gdev:		The Guest extension device.656 *657 * Return: %0 or negative errno value.658 */659static int vbg_reset_host_capabilities(struct vbg_dev *gdev)660{661	struct vmmdev_mask *req;662	int rc;663 664	req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_GUEST_CAPABILITIES,665			    VBG_KERNEL_REQUEST);666	if (!req)667		return -ENOMEM;668 669	req->not_mask = U32_MAX;670	req->or_mask = 0;671	rc = vbg_req_perform(gdev, req);672	if (rc < 0)673		vbg_err("%s error, rc: %d\n", __func__, rc);674 675	vbg_req_free(req, sizeof(*req));676	return vbg_status_code_to_errno(rc);677}678 679/**680 * vbg_set_host_capabilities - Set guest capabilities on the host.681 * @gdev:			The Guest extension device.682 * @session:			The session.683 * @session_termination:	Set if we're called by the session cleanup code.684 *685 * Must be called with gdev->session_mutex hold.686 *687 * Return: %0 or negative errno value.688 */689static int vbg_set_host_capabilities(struct vbg_dev *gdev,690				     struct vbg_session *session,691				     bool session_termination)692{693	struct vmmdev_mask *req;694	u32 caps;695	int rc;696 697	WARN_ON(!mutex_is_locked(&gdev->session_mutex));698 699	caps = gdev->acquired_guest_caps | gdev->set_guest_caps_tracker.mask;700 701	if (gdev->guest_caps_host == caps)702		return 0;703 704	/* On termination the requestor is the kernel, as we're cleaning up. */705	req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_GUEST_CAPABILITIES,706			    session_termination ? VBG_KERNEL_REQUEST :707						  session->requestor);708	if (!req) {709		gdev->guest_caps_host = U32_MAX;710		return -ENOMEM;711	}712 713	req->or_mask = caps;714	req->not_mask = ~caps;715	rc = vbg_req_perform(gdev, req);716	vbg_req_free(req, sizeof(*req));717 718	gdev->guest_caps_host = (rc >= 0) ? caps : U32_MAX;719 720	return vbg_status_code_to_errno(rc);721}722 723/**724 * vbg_acquire_session_capabilities - Acquire (get exclusive access)725 *	guest capabilities for a session.726 * @gdev:			The Guest extension device.727 * @session:			The session.728 * @flags:			Flags (VBGL_IOC_AGC_FLAGS_XXX).729 * @or_mask:			The capabilities to add.730 * @not_mask:			The capabilities to remove.731 * @session_termination:	Set if we're called by the session cleanup code.732 *				This tweaks the error handling so we perform733 *				proper session cleanup even if the host734 *				misbehaves.735 *736 * Takes the session mutex.737 *738 * Return: %0 or negative errno value.739 */740static int vbg_acquire_session_capabilities(struct vbg_dev *gdev,741					    struct vbg_session *session,742					    u32 or_mask, u32 not_mask,743					    u32 flags, bool session_termination)744{745	unsigned long irqflags;746	bool wakeup = false;747	int ret = 0;748 749	mutex_lock(&gdev->session_mutex);750 751	if (gdev->set_guest_caps_tracker.mask & or_mask) {752		vbg_err("%s error: cannot acquire caps which are currently set\n",753			__func__);754		ret = -EINVAL;755		goto out;756	}757 758	/*759	 * Mark any caps in the or_mask as now being in acquire-mode. Note760	 * once caps are in acquire_mode they always stay in this mode.761	 * This impacts event handling, so we take the event-lock.762	 */763	spin_lock_irqsave(&gdev->event_spinlock, irqflags);764	gdev->acquire_mode_guest_caps |= or_mask;765	spin_unlock_irqrestore(&gdev->event_spinlock, irqflags);766 767	/* If we only have to switch the caps to acquire mode, we're done. */768	if (flags & VBGL_IOC_AGC_FLAGS_CONFIG_ACQUIRE_MODE)769		goto out;770 771	not_mask &= ~or_mask; /* or_mask takes priority over not_mask */772	not_mask &= session->acquired_guest_caps;773	or_mask &= ~session->acquired_guest_caps;774 775	if (or_mask == 0 && not_mask == 0)776		goto out;777 778	if (gdev->acquired_guest_caps & or_mask) {779		ret = -EBUSY;780		goto out;781	}782 783	gdev->acquired_guest_caps |= or_mask;784	gdev->acquired_guest_caps &= ~not_mask;785	/* session->acquired_guest_caps impacts event handling, take the lock */786	spin_lock_irqsave(&gdev->event_spinlock, irqflags);787	session->acquired_guest_caps |= or_mask;788	session->acquired_guest_caps &= ~not_mask;789	spin_unlock_irqrestore(&gdev->event_spinlock, irqflags);790 791	ret = vbg_set_host_capabilities(gdev, session, session_termination);792	/* Roll back on failure, unless it's session termination time. */793	if (ret < 0 && !session_termination) {794		gdev->acquired_guest_caps &= ~or_mask;795		gdev->acquired_guest_caps |= not_mask;796		spin_lock_irqsave(&gdev->event_spinlock, irqflags);797		session->acquired_guest_caps &= ~or_mask;798		session->acquired_guest_caps |= not_mask;799		spin_unlock_irqrestore(&gdev->event_spinlock, irqflags);800	}801 802	/*803	 * If we added a capability, check if that means some other thread in804	 * our session should be unblocked because there are events pending805	 * (the result of vbg_get_allowed_event_mask_for_session() may change).806	 *807	 * HACK ALERT! When the seamless support capability is added we generate808	 *	a seamless change event so that the ring-3 client can sync with809	 *	the seamless state.810	 */811	if (ret == 0 && or_mask != 0) {812		spin_lock_irqsave(&gdev->event_spinlock, irqflags);813 814		if (or_mask & VMMDEV_GUEST_SUPPORTS_SEAMLESS)815			gdev->pending_events |=816				VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST;817 818		if (gdev->pending_events)819			wakeup = true;820 821		spin_unlock_irqrestore(&gdev->event_spinlock, irqflags);822 823		if (wakeup)824			wake_up(&gdev->event_wq);825	}826 827out:828	mutex_unlock(&gdev->session_mutex);829 830	return ret;831}832 833/**834 * vbg_set_session_capabilities - Sets the guest capabilities for a835 *	session. Takes the session mutex.836 * @gdev:			The Guest extension device.837 * @session:			The session.838 * @or_mask:			The capabilities to add.839 * @not_mask:			The capabilities to remove.840 * @session_termination:	Set if we're called by the session cleanup code.841 *				This tweaks the error handling so we perform842 *				proper session cleanup even if the host843 *				misbehaves.844 *845 * Return: %0 or negative errno value.846 */847static int vbg_set_session_capabilities(struct vbg_dev *gdev,848					struct vbg_session *session,849					u32 or_mask, u32 not_mask,850					bool session_termination)851{852	u32 changed, previous;853	int ret = 0;854 855	mutex_lock(&gdev->session_mutex);856 857	if (gdev->acquire_mode_guest_caps & or_mask) {858		vbg_err("%s error: cannot set caps which are in acquire_mode\n",859			__func__);860		ret = -EBUSY;861		goto out;862	}863 864	/* Apply the changes to the session mask. */865	previous = session->set_guest_caps;866	session->set_guest_caps |= or_mask;867	session->set_guest_caps &= ~not_mask;868 869	/* If anything actually changed, update the global usage counters. */870	changed = previous ^ session->set_guest_caps;871	if (!changed)872		goto out;873 874	vbg_track_bit_usage(&gdev->set_guest_caps_tracker, changed, previous);875 876	ret = vbg_set_host_capabilities(gdev, session, session_termination);877	/* Roll back on failure, unless it's session termination time. */878	if (ret < 0 && !session_termination) {879		vbg_track_bit_usage(&gdev->set_guest_caps_tracker, changed,880				    session->set_guest_caps);881		session->set_guest_caps = previous;882	}883 884out:885	mutex_unlock(&gdev->session_mutex);886 887	return ret;888}889 890/**891 * vbg_query_host_version - get the host feature mask and version information.892 * @gdev:		The Guest extension device.893 *894 * Return: %0 or negative errno value.895 */896static int vbg_query_host_version(struct vbg_dev *gdev)897{898	struct vmmdev_host_version *req;899	int rc, ret;900 901	req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_GET_HOST_VERSION,902			    VBG_KERNEL_REQUEST);903	if (!req)904		return -ENOMEM;905 906	rc = vbg_req_perform(gdev, req);907	ret = vbg_status_code_to_errno(rc);908	if (ret) {909		vbg_err("%s error: %d\n", __func__, rc);910		goto out;911	}912 913	snprintf(gdev->host_version, sizeof(gdev->host_version), "%u.%u.%ur%u",914		 req->major, req->minor, req->build, req->revision);915	gdev->host_features = req->features;916 917	vbg_info("vboxguest: host-version: %s %#x\n", gdev->host_version,918		 gdev->host_features);919 920	if (!(req->features & VMMDEV_HVF_HGCM_PHYS_PAGE_LIST)) {921		vbg_err("vboxguest: Error host too old (does not support page-lists)\n");922		ret = -ENODEV;923	}924 925out:926	vbg_req_free(req, sizeof(*req));927	return ret;928}929 930/**931 * vbg_core_init - Initializes the VBoxGuest device extension when the932 *	device driver is loaded.933 * @gdev:		The Guest extension device.934 * @fixed_events:	Events that will be enabled upon init and no client935 *			will ever be allowed to mask.936 *937 * The native code locates the VMMDev on the PCI bus and retrieve938 * the MMIO and I/O port ranges, this function will take care of939 * mapping the MMIO memory (if present). Upon successful return940 * the native code should set up the interrupt handler.941 *942 * Return: %0 or negative errno value.943 */944int vbg_core_init(struct vbg_dev *gdev, u32 fixed_events)945{946	int ret = -ENOMEM;947 948	gdev->fixed_events = fixed_events | VMMDEV_EVENT_HGCM;949	gdev->event_filter_host = U32_MAX;	/* forces a report */950	gdev->guest_caps_host = U32_MAX;	/* forces a report */951 952	init_waitqueue_head(&gdev->event_wq);953	init_waitqueue_head(&gdev->hgcm_wq);954	spin_lock_init(&gdev->event_spinlock);955	mutex_init(&gdev->session_mutex);956	mutex_init(&gdev->cancel_req_mutex);957	timer_setup(&gdev->heartbeat_timer, vbg_heartbeat_timer, 0);958	INIT_WORK(&gdev->mem_balloon.work, vbg_balloon_work);959 960	gdev->mem_balloon.get_req =961		vbg_req_alloc(sizeof(*gdev->mem_balloon.get_req),962			      VMMDEVREQ_GET_MEMBALLOON_CHANGE_REQ,963			      VBG_KERNEL_REQUEST);964	gdev->mem_balloon.change_req =965		vbg_req_alloc(sizeof(*gdev->mem_balloon.change_req),966			      VMMDEVREQ_CHANGE_MEMBALLOON,967			      VBG_KERNEL_REQUEST);968	gdev->cancel_req =969		vbg_req_alloc(sizeof(*(gdev->cancel_req)),970			      VMMDEVREQ_HGCM_CANCEL2,971			      VBG_KERNEL_REQUEST);972	gdev->ack_events_req =973		vbg_req_alloc(sizeof(*gdev->ack_events_req),974			      VMMDEVREQ_ACKNOWLEDGE_EVENTS,975			      VBG_KERNEL_REQUEST);976	gdev->mouse_status_req =977		vbg_req_alloc(sizeof(*gdev->mouse_status_req),978			      VMMDEVREQ_GET_MOUSE_STATUS,979			      VBG_KERNEL_REQUEST);980 981	if (!gdev->mem_balloon.get_req || !gdev->mem_balloon.change_req ||982	    !gdev->cancel_req || !gdev->ack_events_req ||983	    !gdev->mouse_status_req)984		goto err_free_reqs;985 986	ret = vbg_query_host_version(gdev);987	if (ret)988		goto err_free_reqs;989 990	ret = vbg_report_guest_info(gdev);991	if (ret) {992		vbg_err("vboxguest: vbg_report_guest_info error: %d\n", ret);993		goto err_free_reqs;994	}995 996	ret = vbg_reset_host_event_filter(gdev, gdev->fixed_events);997	if (ret) {998		vbg_err("vboxguest: Error setting fixed event filter: %d\n",999			ret);1000		goto err_free_reqs;1001	}1002 1003	ret = vbg_reset_host_capabilities(gdev);1004	if (ret) {1005		vbg_err("vboxguest: Error clearing guest capabilities: %d\n",1006			ret);1007		goto err_free_reqs;1008	}1009 1010	ret = vbg_core_set_mouse_status(gdev, 0);1011	if (ret) {1012		vbg_err("vboxguest: Error clearing mouse status: %d\n", ret);1013		goto err_free_reqs;1014	}1015 1016	/* These may fail without requiring the driver init to fail. */1017	vbg_guest_mappings_init(gdev);1018	vbg_heartbeat_init(gdev);1019 1020	/* All Done! */1021	ret = vbg_report_driver_status(gdev, true);1022	if (ret < 0)1023		vbg_err("vboxguest: Error reporting driver status: %d\n", ret);1024 1025	return 0;1026 1027err_free_reqs:1028	vbg_req_free(gdev->mouse_status_req,1029		     sizeof(*gdev->mouse_status_req));1030	vbg_req_free(gdev->ack_events_req,1031		     sizeof(*gdev->ack_events_req));1032	vbg_req_free(gdev->cancel_req,1033		     sizeof(*gdev->cancel_req));1034	vbg_req_free(gdev->mem_balloon.change_req,1035		     sizeof(*gdev->mem_balloon.change_req));1036	vbg_req_free(gdev->mem_balloon.get_req,1037		     sizeof(*gdev->mem_balloon.get_req));1038	return ret;1039}1040 1041/**1042 * vbg_core_exit - Call this on exit to clean-up vboxguest-core managed1043 *	resources.1044 * @gdev:		The Guest extension device.1045 *1046 * The native code should call this before the driver is loaded,1047 * but don't call this on shutdown.1048 */1049void vbg_core_exit(struct vbg_dev *gdev)1050{1051	vbg_heartbeat_exit(gdev);1052	vbg_guest_mappings_exit(gdev);1053 1054	/* Clear the host flags (mouse status etc). */1055	vbg_reset_host_event_filter(gdev, 0);1056	vbg_reset_host_capabilities(gdev);1057	vbg_core_set_mouse_status(gdev, 0);1058 1059	vbg_req_free(gdev->mouse_status_req,1060		     sizeof(*gdev->mouse_status_req));1061	vbg_req_free(gdev->ack_events_req,1062		     sizeof(*gdev->ack_events_req));1063	vbg_req_free(gdev->cancel_req,1064		     sizeof(*gdev->cancel_req));1065	vbg_req_free(gdev->mem_balloon.change_req,1066		     sizeof(*gdev->mem_balloon.change_req));1067	vbg_req_free(gdev->mem_balloon.get_req,1068		     sizeof(*gdev->mem_balloon.get_req));1069}1070 1071/**1072 * vbg_core_open_session - Creates a VBoxGuest user session.1073 * @gdev:		The Guest extension device.1074 * @requestor:		VMMDEV_REQUESTOR_* flags1075 *1076 * vboxguest_linux.c calls this when userspace opens the char-device.1077 *1078 * Return: A pointer to the new session or an ERR_PTR on error.1079 */1080struct vbg_session *vbg_core_open_session(struct vbg_dev *gdev, u32 requestor)1081{1082	struct vbg_session *session;1083 1084	session = kzalloc(sizeof(*session), GFP_KERNEL);1085	if (!session)1086		return ERR_PTR(-ENOMEM);1087 1088	session->gdev = gdev;1089	session->requestor = requestor;1090 1091	return session;1092}1093 1094/**1095 * vbg_core_close_session - Closes a VBoxGuest session.1096 * @session:		The session to close (and free).1097 */1098void vbg_core_close_session(struct vbg_session *session)1099{1100	struct vbg_dev *gdev = session->gdev;1101	int i, rc;1102 1103	vbg_acquire_session_capabilities(gdev, session, 0, U32_MAX, 0, true);1104	vbg_set_session_capabilities(gdev, session, 0, U32_MAX, true);1105	vbg_set_session_event_filter(gdev, session, 0, U32_MAX, true);1106 1107	for (i = 0; i < ARRAY_SIZE(session->hgcm_client_ids); i++) {1108		if (!session->hgcm_client_ids[i])1109			continue;1110 1111		/* requestor is kernel here, as we're cleaning up. */1112		vbg_hgcm_disconnect(gdev, VBG_KERNEL_REQUEST,1113				    session->hgcm_client_ids[i], &rc);1114	}1115 1116	kfree(session);1117}1118 1119static int vbg_ioctl_chk(struct vbg_ioctl_hdr *hdr, size_t in_size,1120			 size_t out_size)1121{1122	if (hdr->size_in  != (sizeof(*hdr) + in_size) ||1123	    hdr->size_out != (sizeof(*hdr) + out_size))1124		return -EINVAL;1125 1126	return 0;1127}1128 1129static int vbg_ioctl_driver_version_info(1130	struct vbg_ioctl_driver_version_info *info)1131{1132	const u16 vbg_maj_version = VBG_IOC_VERSION >> 16;1133	u16 min_maj_version, req_maj_version;1134 1135	if (vbg_ioctl_chk(&info->hdr, sizeof(info->u.in), sizeof(info->u.out)))1136		return -EINVAL;1137 1138	req_maj_version = info->u.in.req_version >> 16;1139	min_maj_version = info->u.in.min_version >> 16;1140 1141	if (info->u.in.min_version > info->u.in.req_version ||1142	    min_maj_version != req_maj_version)1143		return -EINVAL;1144 1145	if (info->u.in.min_version <= VBG_IOC_VERSION &&1146	    min_maj_version == vbg_maj_version) {1147		info->u.out.session_version = VBG_IOC_VERSION;1148	} else {1149		info->u.out.session_version = U32_MAX;1150		info->hdr.rc = VERR_VERSION_MISMATCH;1151	}1152 1153	info->u.out.driver_version  = VBG_IOC_VERSION;1154	info->u.out.driver_revision = 0;1155	info->u.out.reserved1      = 0;1156	info->u.out.reserved2      = 0;1157 1158	return 0;1159}1160 1161/* Must be called with the event_lock held */1162static u32 vbg_get_allowed_event_mask_for_session(struct vbg_dev *gdev,1163						  struct vbg_session *session)1164{1165	u32 acquire_mode_caps = gdev->acquire_mode_guest_caps;1166	u32 session_acquired_caps = session->acquired_guest_caps;1167	u32 allowed_events = VMMDEV_EVENT_VALID_EVENT_MASK;1168 1169	if ((acquire_mode_caps & VMMDEV_GUEST_SUPPORTS_GRAPHICS) &&1170	    !(session_acquired_caps & VMMDEV_GUEST_SUPPORTS_GRAPHICS))1171		allowed_events &= ~VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST;1172 1173	if ((acquire_mode_caps & VMMDEV_GUEST_SUPPORTS_SEAMLESS) &&1174	    !(session_acquired_caps & VMMDEV_GUEST_SUPPORTS_SEAMLESS))1175		allowed_events &= ~VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST;1176 1177	return allowed_events;1178}1179 1180static bool vbg_wait_event_cond(struct vbg_dev *gdev,1181				struct vbg_session *session,1182				u32 event_mask)1183{1184	unsigned long flags;1185	bool wakeup;1186	u32 events;1187 1188	spin_lock_irqsave(&gdev->event_spinlock, flags);1189 1190	events = gdev->pending_events & event_mask;1191	events &= vbg_get_allowed_event_mask_for_session(gdev, session);1192	wakeup = events || session->cancel_waiters;1193 1194	spin_unlock_irqrestore(&gdev->event_spinlock, flags);1195 1196	return wakeup;1197}1198 1199/* Must be called with the event_lock held */1200static u32 vbg_consume_events_locked(struct vbg_dev *gdev,1201				     struct vbg_session *session,1202				     u32 event_mask)1203{1204	u32 events = gdev->pending_events & event_mask;1205 1206	events &= vbg_get_allowed_event_mask_for_session(gdev, session);1207	gdev->pending_events &= ~events;1208	return events;1209}1210 1211static int vbg_ioctl_wait_for_events(struct vbg_dev *gdev,1212				     struct vbg_session *session,1213				     struct vbg_ioctl_wait_for_events *wait)1214{1215	u32 timeout_ms = wait->u.in.timeout_ms;1216	u32 event_mask = wait->u.in.events;1217	unsigned long flags;1218	long timeout;1219	int ret = 0;1220 1221	if (vbg_ioctl_chk(&wait->hdr, sizeof(wait->u.in), sizeof(wait->u.out)))1222		return -EINVAL;1223 1224	if (timeout_ms == U32_MAX)1225		timeout = MAX_SCHEDULE_TIMEOUT;1226	else1227		timeout = msecs_to_jiffies(timeout_ms);1228 1229	wait->u.out.events = 0;1230	do {1231		timeout = wait_event_interruptible_timeout(1232				gdev->event_wq,1233				vbg_wait_event_cond(gdev, session, event_mask),1234				timeout);1235 1236		spin_lock_irqsave(&gdev->event_spinlock, flags);1237 1238		if (timeout < 0 || session->cancel_waiters) {1239			ret = -EINTR;1240		} else if (timeout == 0) {1241			ret = -ETIMEDOUT;1242		} else {1243			wait->u.out.events =1244			   vbg_consume_events_locked(gdev, session, event_mask);1245		}1246 1247		spin_unlock_irqrestore(&gdev->event_spinlock, flags);1248 1249		/*1250		 * Someone else may have consumed the event(s) first, in1251		 * which case we go back to waiting.1252		 */1253	} while (ret == 0 && wait->u.out.events == 0);1254 1255	return ret;1256}1257 1258static int vbg_ioctl_interrupt_all_wait_events(struct vbg_dev *gdev,1259					       struct vbg_session *session,1260					       struct vbg_ioctl_hdr *hdr)1261{1262	unsigned long flags;1263 1264	if (hdr->size_in != sizeof(*hdr) || hdr->size_out != sizeof(*hdr))1265		return -EINVAL;1266 1267	spin_lock_irqsave(&gdev->event_spinlock, flags);1268	session->cancel_waiters = true;1269	spin_unlock_irqrestore(&gdev->event_spinlock, flags);1270 1271	wake_up(&gdev->event_wq);1272 1273	return 0;1274}1275 1276/**1277 * vbg_req_allowed - Checks if the VMM request is allowed in the1278 *	context of the given session.1279 * @gdev:		The Guest extension device.1280 * @session:		The calling session.1281 * @req:		The request.1282 *1283 * Return: %0 or negative errno value.1284 */1285static int vbg_req_allowed(struct vbg_dev *gdev, struct vbg_session *session,1286			   const struct vmmdev_request_header *req)1287{1288	const struct vmmdev_guest_status *guest_status;1289	bool trusted_apps_only;1290 1291	switch (req->request_type) {1292	/* Trusted users apps only. */1293	case VMMDEVREQ_QUERY_CREDENTIALS:1294	case VMMDEVREQ_REPORT_CREDENTIALS_JUDGEMENT:1295	case VMMDEVREQ_REGISTER_SHARED_MODULE:1296	case VMMDEVREQ_UNREGISTER_SHARED_MODULE:1297	case VMMDEVREQ_WRITE_COREDUMP:1298	case VMMDEVREQ_GET_CPU_HOTPLUG_REQ:1299	case VMMDEVREQ_SET_CPU_HOTPLUG_STATUS:1300	case VMMDEVREQ_CHECK_SHARED_MODULES:1301	case VMMDEVREQ_GET_PAGE_SHARING_STATUS:1302	case VMMDEVREQ_DEBUG_IS_PAGE_SHARED:1303	case VMMDEVREQ_REPORT_GUEST_STATS:1304	case VMMDEVREQ_REPORT_GUEST_USER_STATE:1305	case VMMDEVREQ_GET_STATISTICS_CHANGE_REQ:1306		trusted_apps_only = true;1307		break;1308 1309	/* Anyone. */1310	case VMMDEVREQ_GET_MOUSE_STATUS:1311	case VMMDEVREQ_SET_MOUSE_STATUS:1312	case VMMDEVREQ_SET_POINTER_SHAPE:1313	case VMMDEVREQ_GET_HOST_VERSION:1314	case VMMDEVREQ_IDLE:1315	case VMMDEVREQ_GET_HOST_TIME:1316	case VMMDEVREQ_SET_POWER_STATUS:1317	case VMMDEVREQ_ACKNOWLEDGE_EVENTS:1318	case VMMDEVREQ_CTL_GUEST_FILTER_MASK:1319	case VMMDEVREQ_REPORT_GUEST_STATUS:1320	case VMMDEVREQ_GET_DISPLAY_CHANGE_REQ:1321	case VMMDEVREQ_VIDEMODE_SUPPORTED:1322	case VMMDEVREQ_GET_HEIGHT_REDUCTION:1323	case VMMDEVREQ_GET_DISPLAY_CHANGE_REQ2:1324	case VMMDEVREQ_VIDEMODE_SUPPORTED2:1325	case VMMDEVREQ_VIDEO_ACCEL_ENABLE:1326	case VMMDEVREQ_VIDEO_ACCEL_FLUSH:1327	case VMMDEVREQ_VIDEO_SET_VISIBLE_REGION:1328	case VMMDEVREQ_VIDEO_UPDATE_MONITOR_POSITIONS:1329	case VMMDEVREQ_GET_DISPLAY_CHANGE_REQEX:1330	case VMMDEVREQ_GET_DISPLAY_CHANGE_REQ_MULTI:1331	case VMMDEVREQ_GET_SEAMLESS_CHANGE_REQ:1332	case VMMDEVREQ_GET_VRDPCHANGE_REQ:1333	case VMMDEVREQ_LOG_STRING:1334	case VMMDEVREQ_GET_SESSION_ID:1335		trusted_apps_only = false;1336		break;1337 1338	/* Depends on the request parameters... */1339	case VMMDEVREQ_REPORT_GUEST_CAPABILITIES:1340		guest_status = (const struct vmmdev_guest_status *)req;1341		switch (guest_status->facility) {1342		case VBOXGUEST_FACILITY_TYPE_ALL:1343		case VBOXGUEST_FACILITY_TYPE_VBOXGUEST_DRIVER:1344			vbg_err("Denying userspace vmm report guest cap. call facility %#08x\n",1345				guest_status->facility);1346			return -EPERM;1347		case VBOXGUEST_FACILITY_TYPE_VBOX_SERVICE:1348			trusted_apps_only = true;1349			break;1350		case VBOXGUEST_FACILITY_TYPE_VBOX_TRAY_CLIENT:1351		case VBOXGUEST_FACILITY_TYPE_SEAMLESS:1352		case VBOXGUEST_FACILITY_TYPE_GRAPHICS:1353		default:1354			trusted_apps_only = false;1355			break;1356		}1357		break;1358 1359	/* Anything else is not allowed. */1360	default:1361		vbg_err("Denying userspace vmm call type %#08x\n",1362			req->request_type);1363		return -EPERM;1364	}1365 1366	if (trusted_apps_only &&1367	    (session->requestor & VMMDEV_REQUESTOR_USER_DEVICE)) {1368		vbg_err("Denying userspace vmm call type %#08x through vboxuser device node\n",1369			req->request_type);1370		return -EPERM;1371	}1372 1373	return 0;1374}1375 1376static int vbg_ioctl_vmmrequest(struct vbg_dev *gdev,1377				struct vbg_session *session, void *data)1378{1379	struct vbg_ioctl_hdr *hdr = data;1380	int ret;1381 1382	if (hdr->size_in != hdr->size_out)1383		return -EINVAL;1384 1385	if (hdr->size_in > VMMDEV_MAX_VMMDEVREQ_SIZE)1386		return -E2BIG;1387 1388	if (hdr->type == VBG_IOCTL_HDR_TYPE_DEFAULT)1389		return -EINVAL;1390 1391	ret = vbg_req_allowed(gdev, session, data);1392	if (ret < 0)1393		return ret;1394 1395	vbg_req_perform(gdev, data);1396	WARN_ON(hdr->rc == VINF_HGCM_ASYNC_EXECUTE);1397 1398	return 0;1399}1400 1401static int vbg_ioctl_hgcm_connect(struct vbg_dev *gdev,1402				  struct vbg_session *session,1403				  struct vbg_ioctl_hgcm_connect *conn)1404{1405	u32 client_id;1406	int i, ret;1407 1408	if (vbg_ioctl_chk(&conn->hdr, sizeof(conn->u.in), sizeof(conn->u.out)))1409		return -EINVAL;1410 1411	/* Find a free place in the sessions clients array and claim it */1412	mutex_lock(&gdev->session_mutex);1413	for (i = 0; i < ARRAY_SIZE(session->hgcm_client_ids); i++) {1414		if (!session->hgcm_client_ids[i]) {1415			session->hgcm_client_ids[i] = U32_MAX;1416			break;1417		}1418	}1419	mutex_unlock(&gdev->session_mutex);1420 1421	if (i >= ARRAY_SIZE(session->hgcm_client_ids))1422		return -EMFILE;1423 1424	ret = vbg_hgcm_connect(gdev, session->requestor, &conn->u.in.loc,1425			       &client_id, &conn->hdr.rc);1426 1427	mutex_lock(&gdev->session_mutex);1428	if (ret == 0 && conn->hdr.rc >= 0) {1429		conn->u.out.client_id = client_id;1430		session->hgcm_client_ids[i] = client_id;1431	} else {1432		conn->u.out.client_id = 0;1433		session->hgcm_client_ids[i] = 0;1434	}1435	mutex_unlock(&gdev->session_mutex);1436 1437	return ret;1438}1439 1440static int vbg_ioctl_hgcm_disconnect(struct vbg_dev *gdev,1441				     struct vbg_session *session,1442				     struct vbg_ioctl_hgcm_disconnect *disconn)1443{1444	u32 client_id;1445	int i, ret;1446 1447	if (vbg_ioctl_chk(&disconn->hdr, sizeof(disconn->u.in), 0))1448		return -EINVAL;1449 1450	client_id = disconn->u.in.client_id;1451	if (client_id == 0 || client_id == U32_MAX)1452		return -EINVAL;1453 1454	mutex_lock(&gdev->session_mutex);1455	for (i = 0; i < ARRAY_SIZE(session->hgcm_client_ids); i++) {1456		if (session->hgcm_client_ids[i] == client_id) {1457			session->hgcm_client_ids[i] = U32_MAX;1458			break;1459		}1460	}1461	mutex_unlock(&gdev->session_mutex);1462 1463	if (i >= ARRAY_SIZE(session->hgcm_client_ids))1464		return -EINVAL;1465 1466	ret = vbg_hgcm_disconnect(gdev, session->requestor, client_id,1467				  &disconn->hdr.rc);1468 1469	mutex_lock(&gdev->session_mutex);1470	if (ret == 0 && disconn->hdr.rc >= 0)1471		session->hgcm_client_ids[i] = 0;1472	else1473		session->hgcm_client_ids[i] = client_id;1474	mutex_unlock(&gdev->session_mutex);1475 1476	return ret;1477}1478 1479static bool vbg_param_valid(enum vmmdev_hgcm_function_parameter_type type)1480{1481	switch (type) {1482	case VMMDEV_HGCM_PARM_TYPE_32BIT:1483	case VMMDEV_HGCM_PARM_TYPE_64BIT:1484	case VMMDEV_HGCM_PARM_TYPE_LINADDR:1485	case VMMDEV_HGCM_PARM_TYPE_LINADDR_IN:1486	case VMMDEV_HGCM_PARM_TYPE_LINADDR_OUT:1487		return true;1488	default:1489		return false;1490	}1491}1492 1493static int vbg_ioctl_hgcm_call(struct vbg_dev *gdev,1494			       struct vbg_session *session, bool f32bit,1495			       struct vbg_ioctl_hgcm_call *call)1496{1497	size_t actual_size;1498	u32 client_id;1499	int i, ret;1500 1501	if (call->hdr.size_in < sizeof(*call))1502		return -EINVAL;1503 1504	if (call->hdr.size_in != call->hdr.size_out)1505		return -EINVAL;1506 1507	if (call->parm_count > VMMDEV_HGCM_MAX_PARMS)1508		return -E2BIG;1509 1510	client_id = call->client_id;1511	if (client_id == 0 || client_id == U32_MAX)1512		return -EINVAL;1513 1514	actual_size = sizeof(*call);1515	if (f32bit)1516		actual_size += call->parm_count *1517			       sizeof(struct vmmdev_hgcm_function_parameter32);1518	else1519		actual_size += call->parm_count *1520			       sizeof(struct vmmdev_hgcm_function_parameter);1521	if (call->hdr.size_in < actual_size) {1522		vbg_debug("VBG_IOCTL_HGCM_CALL: hdr.size_in %d required size is %zd\n",1523			  call->hdr.size_in, actual_size);1524		return -EINVAL;1525	}1526	call->hdr.size_out = actual_size;1527 1528	/* Validate parameter types */1529	if (f32bit) {1530		struct vmmdev_hgcm_function_parameter32 *parm =1531			VBG_IOCTL_HGCM_CALL_PARMS32(call);1532 1533		for (i = 0; i < call->parm_count; i++)1534			if (!vbg_param_valid(parm[i].type))1535				return -EINVAL;1536	} else {1537		struct vmmdev_hgcm_function_parameter *parm =1538			VBG_IOCTL_HGCM_CALL_PARMS(call);1539 1540		for (i = 0; i < call->parm_count; i++)1541			if (!vbg_param_valid(parm[i].type))1542				return -EINVAL;1543	}1544 1545	/*1546	 * Validate the client id.1547	 */1548	mutex_lock(&gdev->session_mutex);1549	for (i = 0; i < ARRAY_SIZE(session->hgcm_client_ids); i++)1550		if (session->hgcm_client_ids[i] == client_id)1551			break;1552	mutex_unlock(&gdev->session_mutex);1553	if (i >= ARRAY_SIZE(session->hgcm_client_ids)) {1554		vbg_debug("VBG_IOCTL_HGCM_CALL: INVALID handle. u32Client=%#08x\n",1555			  client_id);1556		return -EINVAL;1557	}1558 1559	if (IS_ENABLED(CONFIG_COMPAT) && f32bit)1560		ret = vbg_hgcm_call32(gdev, session->requestor, client_id,1561				      call->function, call->timeout_ms,1562				      VBG_IOCTL_HGCM_CALL_PARMS32(call),1563				      call->parm_count, &call->hdr.rc);1564	else1565		ret = vbg_hgcm_call(gdev, session->requestor, client_id,1566				    call->function, call->timeout_ms,1567				    VBG_IOCTL_HGCM_CALL_PARMS(call),1568				    call->parm_count, &call->hdr.rc);1569 1570	if (ret == -E2BIG) {1571		/* E2BIG needs to be reported through the hdr.rc field. */1572		call->hdr.rc = VERR_OUT_OF_RANGE;1573		ret = 0;1574	}1575 1576	if (ret && ret != -EINTR && ret != -ETIMEDOUT)1577		vbg_err("VBG_IOCTL_HGCM_CALL error: %d\n", ret);1578 1579	return ret;1580}1581 1582static int vbg_ioctl_log(struct vbg_ioctl_log *log)1583{1584	if (log->hdr.size_out != sizeof(log->hdr))1585		return -EINVAL;1586 1587	vbg_info("%.*s", (int)(log->hdr.size_in - sizeof(log->hdr)),1588		 log->u.in.msg);1589 1590	return 0;1591}1592 1593static int vbg_ioctl_change_filter_mask(struct vbg_dev *gdev,1594					struct vbg_session *session,1595					struct vbg_ioctl_change_filter *filter)1596{1597	u32 or_mask, not_mask;1598 1599	if (vbg_ioctl_chk(&filter->hdr, sizeof(filter->u.in), 0))1600		return -EINVAL;1601 1602	or_mask = filter->u.in.or_mask;1603	not_mask = filter->u.in.not_mask;1604 1605	if ((or_mask | not_mask) & ~VMMDEV_EVENT_VALID_EVENT_MASK)1606		return -EINVAL;1607 1608	return vbg_set_session_event_filter(gdev, session, or_mask, not_mask,1609					    false);1610}1611 1612static int vbg_ioctl_acquire_guest_capabilities(struct vbg_dev *gdev,1613	     struct vbg_session *session,1614	     struct vbg_ioctl_acquire_guest_caps *caps)1615{1616	u32 flags, or_mask, not_mask;1617 1618	if (vbg_ioctl_chk(&caps->hdr, sizeof(caps->u.in), 0))1619		return -EINVAL;1620 1621	flags = caps->u.in.flags;1622	or_mask = caps->u.in.or_mask;1623	not_mask = caps->u.in.not_mask;1624 1625	if (flags & ~VBGL_IOC_AGC_FLAGS_VALID_MASK)1626		return -EINVAL;1627 1628	if ((or_mask | not_mask) & ~VMMDEV_GUEST_CAPABILITIES_MASK)1629		return -EINVAL;1630 1631	return vbg_acquire_session_capabilities(gdev, session, or_mask,1632						not_mask, flags, false);1633}1634 1635static int vbg_ioctl_change_guest_capabilities(struct vbg_dev *gdev,1636	     struct vbg_session *session, struct vbg_ioctl_set_guest_caps *caps)1637{1638	u32 or_mask, not_mask;1639	int ret;1640 1641	if (vbg_ioctl_chk(&caps->hdr, sizeof(caps->u.in), sizeof(caps->u.out)))1642		return -EINVAL;1643 1644	or_mask = caps->u.in.or_mask;1645	not_mask = caps->u.in.not_mask;1646 1647	if ((or_mask | not_mask) & ~VMMDEV_GUEST_CAPABILITIES_MASK)1648		return -EINVAL;1649 1650	ret = vbg_set_session_capabilities(gdev, session, or_mask, not_mask,1651					   false);1652	if (ret)1653		return ret;1654 1655	caps->u.out.session_caps = session->set_guest_caps;1656	caps->u.out.global_caps = gdev->guest_caps_host;1657 1658	return 0;1659}1660 1661static int vbg_ioctl_check_balloon(struct vbg_dev *gdev,1662				   struct vbg_ioctl_check_balloon *balloon_info)1663{1664	if (vbg_ioctl_chk(&balloon_info->hdr, 0, sizeof(balloon_info->u.out)))1665		return -EINVAL;1666 1667	balloon_info->u.out.balloon_chunks = gdev->mem_balloon.chunks;1668	/*1669	 * Under Linux we handle VMMDEV_EVENT_BALLOON_CHANGE_REQUEST1670	 * events entirely in the kernel, see vbg_core_isr().1671	 */1672	balloon_info->u.out.handle_in_r3 = false;1673 1674	return 0;1675}1676 1677static int vbg_ioctl_write_core_dump(struct vbg_dev *gdev,1678				     struct vbg_session *session,1679				     struct vbg_ioctl_write_coredump *dump)1680{1681	struct vmmdev_write_core_dump *req;1682 1683	if (vbg_ioctl_chk(&dump->hdr, sizeof(dump->u.in), 0))1684		return -EINVAL;1685 1686	req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_WRITE_COREDUMP,1687			    session->requestor);1688	if (!req)1689		return -ENOMEM;1690 1691	req->flags = dump->u.in.flags;1692	dump->hdr.rc = vbg_req_perform(gdev, req);1693 1694	vbg_req_free(req, sizeof(*req));1695	return 0;1696}1697 1698/**1699 * vbg_core_ioctl - Common IOCtl for user to kernel communication.1700 * @session:	The client session.1701 * @req:	The requested function.1702 * @data:	The i/o data buffer, minimum size sizeof(struct vbg_ioctl_hdr).1703 *1704 * Return: %0 or negative errno value.1705 */1706int vbg_core_ioctl(struct vbg_session *session, unsigned int req, void *data)1707{1708	unsigned int req_no_size = req & ~IOCSIZE_MASK;1709	struct vbg_dev *gdev = session->gdev;1710	struct vbg_ioctl_hdr *hdr = data;1711	bool f32bit = false;1712 1713	hdr->rc = VINF_SUCCESS;1714	if (!hdr->size_out)1715		hdr->size_out = hdr->size_in;1716 1717	/*1718	 * hdr->version and hdr->size_in / hdr->size_out minimum size are1719	 * already checked by vbg_misc_device_ioctl().1720	 */1721 1722	/* For VMMDEV_REQUEST hdr->type != VBG_IOCTL_HDR_TYPE_DEFAULT */1723	if (req_no_size == VBG_IOCTL_VMMDEV_REQUEST(0) ||1724	    req == VBG_IOCTL_VMMDEV_REQUEST_BIG ||1725	    req == VBG_IOCTL_VMMDEV_REQUEST_BIG_ALT)1726		return vbg_ioctl_vmmrequest(gdev, session, data);1727 1728	if (hdr->type != VBG_IOCTL_HDR_TYPE_DEFAULT)1729		return -EINVAL;1730 1731	/* Fixed size requests. */1732	switch (req) {1733	case VBG_IOCTL_DRIVER_VERSION_INFO:1734		return vbg_ioctl_driver_version_info(data);1735	case VBG_IOCTL_HGCM_CONNECT:1736		return vbg_ioctl_hgcm_connect(gdev, session, data);1737	case VBG_IOCTL_HGCM_DISCONNECT:1738		return vbg_ioctl_hgcm_disconnect(gdev, session, data);1739	case VBG_IOCTL_WAIT_FOR_EVENTS:1740		return vbg_ioctl_wait_for_events(gdev, session, data);1741	case VBG_IOCTL_INTERRUPT_ALL_WAIT_FOR_EVENTS:1742		return vbg_ioctl_interrupt_all_wait_events(gdev, session, data);1743	case VBG_IOCTL_CHANGE_FILTER_MASK:1744		return vbg_ioctl_change_filter_mask(gdev, session, data);1745	case VBG_IOCTL_ACQUIRE_GUEST_CAPABILITIES:1746		return vbg_ioctl_acquire_guest_capabilities(gdev, session, data);1747	case VBG_IOCTL_CHANGE_GUEST_CAPABILITIES:1748		return vbg_ioctl_change_guest_capabilities(gdev, session, data);1749	case VBG_IOCTL_CHECK_BALLOON:1750		return vbg_ioctl_check_balloon(gdev, data);1751	case VBG_IOCTL_WRITE_CORE_DUMP:1752		return vbg_ioctl_write_core_dump(gdev, session, data);1753	}1754 1755	/* Variable sized requests. */1756	switch (req_no_size) {1757#ifdef CONFIG_COMPAT1758	case VBG_IOCTL_HGCM_CALL_32(0):1759		f32bit = true;1760		fallthrough;1761#endif1762	case VBG_IOCTL_HGCM_CALL(0):1763		return vbg_ioctl_hgcm_call(gdev, session, f32bit, data);1764	case VBG_IOCTL_LOG(0):1765	case VBG_IOCTL_LOG_ALT(0):1766		return vbg_ioctl_log(data);1767	}1768 1769	vbg_err_ratelimited("Userspace made an unknown ioctl req %#08x\n", req);1770	return -ENOTTY;1771}1772 1773/**1774 * vbg_core_set_mouse_status - Report guest supported mouse-features to the host.1775 *1776 * @gdev:		The Guest extension device.1777 * @features:		The set of features to report to the host.1778 *1779 * Return: %0 or negative errno value.1780 */1781int vbg_core_set_mouse_status(struct vbg_dev *gdev, u32 features)1782{1783	struct vmmdev_mouse_status *req;1784	int rc;1785 1786	req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_MOUSE_STATUS,1787			    VBG_KERNEL_REQUEST);1788	if (!req)1789		return -ENOMEM;1790 1791	req->mouse_features = features;1792	req->pointer_pos_x = 0;1793	req->pointer_pos_y = 0;1794 1795	rc = vbg_req_perform(gdev, req);1796	if (rc < 0)1797		vbg_err("%s error, rc: %d\n", __func__, rc);1798 1799	vbg_req_free(req, sizeof(*req));1800	return vbg_status_code_to_errno(rc);1801}1802 1803/* Core interrupt service routine. */1804irqreturn_t vbg_core_isr(int irq, void *dev_id)1805{1806	struct vbg_dev *gdev = dev_id;1807	struct vmmdev_events *req = gdev->ack_events_req;1808	bool mouse_position_changed = false;1809	unsigned long flags;1810	u32 events = 0;1811	int rc;1812 1813	if (!gdev->mmio->V.V1_04.have_events)1814		return IRQ_NONE;1815 1816	/* Get and acknowlegde events. */1817	req->header.rc = VERR_INTERNAL_ERROR;1818	req->events = 0;1819	rc = vbg_req_perform(gdev, req);1820	if (rc < 0) {1821		vbg_err("Error performing events req, rc: %d\n", rc);1822		return IRQ_NONE;1823	}1824 1825	events = req->events;1826 1827	if (events & VMMDEV_EVENT_MOUSE_POSITION_CHANGED) {1828		mouse_position_changed = true;1829		events &= ~VMMDEV_EVENT_MOUSE_POSITION_CHANGED;1830	}1831 1832	if (events & VMMDEV_EVENT_HGCM) {1833		wake_up(&gdev->hgcm_wq);1834		events &= ~VMMDEV_EVENT_HGCM;1835	}1836 1837	if (events & VMMDEV_EVENT_BALLOON_CHANGE_REQUEST) {1838		schedule_work(&gdev->mem_balloon.work);1839		events &= ~VMMDEV_EVENT_BALLOON_CHANGE_REQUEST;1840	}1841 1842	if (events) {1843		spin_lock_irqsave(&gdev->event_spinlock, flags);1844		gdev->pending_events |= events;1845		spin_unlock_irqrestore(&gdev->event_spinlock, flags);1846 1847		wake_up(&gdev->event_wq);1848	}1849 1850	if (mouse_position_changed)1851		vbg_linux_mouse_event(gdev);1852 1853	return IRQ_HANDLED;1854}1855