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