664 lines
24 KiB
Diff
664 lines
24 KiB
Diff
|
From 58b89b03f14fde3b5eda78b9137109b7a860a607 Mon Sep 17 00:00:00 2001
|
||
|
From: Hans de Goede <hdegoede@redhat.com>
|
||
|
Date: Tue, 19 Mar 2019 14:05:31 +0100
|
||
|
Subject: [PATCH] virt: vbox: Implement passing requestor info to the host for
|
||
|
VirtualBox 6.0.x
|
||
|
|
||
|
VirtualBox 6.0.x has a new feature where the guest kernel driver passes
|
||
|
info about the origin of the request (e.g. userspace or kernelspace) to
|
||
|
the hypervisor.
|
||
|
|
||
|
If we do not pass this information then when running the 6.0.x userspace
|
||
|
guest-additions tools on a 6.0.x host, some requests will get denied
|
||
|
with a VERR_VERSION_MISMATCH error, breaking vboxservice.service and
|
||
|
the mounting of shared folders marked to be auto-mounted.
|
||
|
|
||
|
This commit implements passing the requestor info to the host, fixing this.
|
||
|
|
||
|
Cc: stable@vger.kernel.org
|
||
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||
|
---
|
||
|
drivers/virt/vboxguest/vboxguest_core.c | 106 ++++++++++++++-------
|
||
|
drivers/virt/vboxguest/vboxguest_core.h | 15 +--
|
||
|
drivers/virt/vboxguest/vboxguest_linux.c | 26 ++++-
|
||
|
drivers/virt/vboxguest/vboxguest_utils.c | 32 ++++---
|
||
|
drivers/virt/vboxguest/vboxguest_version.h | 9 +-
|
||
|
drivers/virt/vboxguest/vmmdev.h | 8 +-
|
||
|
include/linux/vbox_utils.h | 12 ++-
|
||
|
include/uapi/linux/vbox_vmmdev_types.h | 31 ++++++
|
||
|
8 files changed, 168 insertions(+), 71 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/virt/vboxguest/vboxguest_core.c b/drivers/virt/vboxguest/vboxguest_core.c
|
||
|
index 1475ed5ffcde..2ec5b34ffed7 100644
|
||
|
--- a/drivers/virt/vboxguest/vboxguest_core.c
|
||
|
+++ b/drivers/virt/vboxguest/vboxguest_core.c
|
||
|
@@ -27,6 +27,10 @@
|
||
|
|
||
|
#define GUEST_MAPPINGS_TRIES 5
|
||
|
|
||
|
+#define VBG_KERNEL_REQUEST \
|
||
|
+ (VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV | \
|
||
|
+ VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN)
|
||
|
+
|
||
|
/**
|
||
|
* Reserves memory in which the VMM can relocate any guest mappings
|
||
|
* that are floating around.
|
||
|
@@ -48,7 +52,8 @@ static void vbg_guest_mappings_init(struct vbg_dev *gdev)
|
||
|
int i, rc;
|
||
|
|
||
|
/* Query the required space. */
|
||
|
- req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_GET_HYPERVISOR_INFO);
|
||
|
+ req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_GET_HYPERVISOR_INFO,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
if (!req)
|
||
|
return;
|
||
|
|
||
|
@@ -135,7 +140,8 @@ static void vbg_guest_mappings_exit(struct vbg_dev *gdev)
|
||
|
* Tell the host that we're going to free the memory we reserved for
|
||
|
* it, the free it up. (Leak the memory if anything goes wrong here.)
|
||
|
*/
|
||
|
- req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_HYPERVISOR_INFO);
|
||
|
+ req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_HYPERVISOR_INFO,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
if (!req)
|
||
|
return;
|
||
|
|
||
|
@@ -172,8 +178,10 @@ static int vbg_report_guest_info(struct vbg_dev *gdev)
|
||
|
struct vmmdev_guest_info2 *req2 = NULL;
|
||
|
int rc, ret = -ENOMEM;
|
||
|
|
||
|
- req1 = vbg_req_alloc(sizeof(*req1), VMMDEVREQ_REPORT_GUEST_INFO);
|
||
|
- req2 = vbg_req_alloc(sizeof(*req2), VMMDEVREQ_REPORT_GUEST_INFO2);
|
||
|
+ req1 = vbg_req_alloc(sizeof(*req1), VMMDEVREQ_REPORT_GUEST_INFO,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
+ req2 = vbg_req_alloc(sizeof(*req2), VMMDEVREQ_REPORT_GUEST_INFO2,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
if (!req1 || !req2)
|
||
|
goto out_free;
|
||
|
|
||
|
@@ -187,8 +195,8 @@ static int vbg_report_guest_info(struct vbg_dev *gdev)
|
||
|
req2->additions_minor = VBG_VERSION_MINOR;
|
||
|
req2->additions_build = VBG_VERSION_BUILD;
|
||
|
req2->additions_revision = VBG_SVN_REV;
|
||
|
- /* (no features defined yet) */
|
||
|
- req2->additions_features = 0;
|
||
|
+ req2->additions_features =
|
||
|
+ VMMDEV_GUEST_INFO2_ADDITIONS_FEATURES_REQUESTOR_INFO;
|
||
|
strlcpy(req2->name, VBG_VERSION_STRING,
|
||
|
sizeof(req2->name));
|
||
|
|
||
|
@@ -230,7 +238,8 @@ static int vbg_report_driver_status(struct vbg_dev *gdev, bool active)
|
||
|
struct vmmdev_guest_status *req;
|
||
|
int rc;
|
||
|
|
||
|
- req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_REPORT_GUEST_STATUS);
|
||
|
+ req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_REPORT_GUEST_STATUS,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
if (!req)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
@@ -423,7 +432,8 @@ static int vbg_heartbeat_host_config(struct vbg_dev *gdev, bool enabled)
|
||
|
struct vmmdev_heartbeat *req;
|
||
|
int rc;
|
||
|
|
||
|
- req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_HEARTBEAT_CONFIGURE);
|
||
|
+ req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_HEARTBEAT_CONFIGURE,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
if (!req)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
@@ -457,7 +467,8 @@ static int vbg_heartbeat_init(struct vbg_dev *gdev)
|
||
|
|
||
|
gdev->guest_heartbeat_req = vbg_req_alloc(
|
||
|
sizeof(*gdev->guest_heartbeat_req),
|
||
|
- VMMDEVREQ_GUEST_HEARTBEAT);
|
||
|
+ VMMDEVREQ_GUEST_HEARTBEAT,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
if (!gdev->guest_heartbeat_req)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
@@ -528,7 +539,8 @@ static int vbg_reset_host_event_filter(struct vbg_dev *gdev,
|
||
|
struct vmmdev_mask *req;
|
||
|
int rc;
|
||
|
|
||
|
- req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_CTL_GUEST_FILTER_MASK);
|
||
|
+ req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_CTL_GUEST_FILTER_MASK,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
if (!req)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
@@ -567,8 +579,14 @@ static int vbg_set_session_event_filter(struct vbg_dev *gdev,
|
||
|
u32 changed, previous;
|
||
|
int rc, ret = 0;
|
||
|
|
||
|
- /* Allocate a request buffer before taking the spinlock */
|
||
|
- req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_CTL_GUEST_FILTER_MASK);
|
||
|
+ /*
|
||
|
+ * Allocate a request buffer before taking the spinlock, when
|
||
|
+ * the session is being terminated the requestor is the kernel,
|
||
|
+ * as we're cleaning up.
|
||
|
+ */
|
||
|
+ req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_CTL_GUEST_FILTER_MASK,
|
||
|
+ session_termination ? VBG_KERNEL_REQUEST :
|
||
|
+ session->requestor);
|
||
|
if (!req) {
|
||
|
if (!session_termination)
|
||
|
return -ENOMEM;
|
||
|
@@ -627,7 +645,8 @@ static int vbg_reset_host_capabilities(struct vbg_dev *gdev)
|
||
|
struct vmmdev_mask *req;
|
||
|
int rc;
|
||
|
|
||
|
- req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_GUEST_CAPABILITIES);
|
||
|
+ req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_GUEST_CAPABILITIES,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
if (!req)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
@@ -662,8 +681,14 @@ static int vbg_set_session_capabilities(struct vbg_dev *gdev,
|
||
|
u32 changed, previous;
|
||
|
int rc, ret = 0;
|
||
|
|
||
|
- /* Allocate a request buffer before taking the spinlock */
|
||
|
- req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_GUEST_CAPABILITIES);
|
||
|
+ /*
|
||
|
+ * Allocate a request buffer before taking the spinlock, when
|
||
|
+ * the session is being terminated the requestor is the kernel,
|
||
|
+ * as we're cleaning up.
|
||
|
+ */
|
||
|
+ req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_GUEST_CAPABILITIES,
|
||
|
+ session_termination ? VBG_KERNEL_REQUEST :
|
||
|
+ session->requestor);
|
||
|
if (!req) {
|
||
|
if (!session_termination)
|
||
|
return -ENOMEM;
|
||
|
@@ -722,7 +747,8 @@ static int vbg_query_host_version(struct vbg_dev *gdev)
|
||
|
struct vmmdev_host_version *req;
|
||
|
int rc, ret;
|
||
|
|
||
|
- req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_GET_HOST_VERSION);
|
||
|
+ req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_GET_HOST_VERSION,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
if (!req)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
@@ -783,19 +809,24 @@ int vbg_core_init(struct vbg_dev *gdev, u32 fixed_events)
|
||
|
|
||
|
gdev->mem_balloon.get_req =
|
||
|
vbg_req_alloc(sizeof(*gdev->mem_balloon.get_req),
|
||
|
- VMMDEVREQ_GET_MEMBALLOON_CHANGE_REQ);
|
||
|
+ VMMDEVREQ_GET_MEMBALLOON_CHANGE_REQ,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
gdev->mem_balloon.change_req =
|
||
|
vbg_req_alloc(sizeof(*gdev->mem_balloon.change_req),
|
||
|
- VMMDEVREQ_CHANGE_MEMBALLOON);
|
||
|
+ VMMDEVREQ_CHANGE_MEMBALLOON,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
gdev->cancel_req =
|
||
|
vbg_req_alloc(sizeof(*(gdev->cancel_req)),
|
||
|
- VMMDEVREQ_HGCM_CANCEL2);
|
||
|
+ VMMDEVREQ_HGCM_CANCEL2,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
gdev->ack_events_req =
|
||
|
vbg_req_alloc(sizeof(*gdev->ack_events_req),
|
||
|
- VMMDEVREQ_ACKNOWLEDGE_EVENTS);
|
||
|
+ VMMDEVREQ_ACKNOWLEDGE_EVENTS,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
gdev->mouse_status_req =
|
||
|
vbg_req_alloc(sizeof(*gdev->mouse_status_req),
|
||
|
- VMMDEVREQ_GET_MOUSE_STATUS);
|
||
|
+ VMMDEVREQ_GET_MOUSE_STATUS,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
|
||
|
if (!gdev->mem_balloon.get_req || !gdev->mem_balloon.change_req ||
|
||
|
!gdev->cancel_req || !gdev->ack_events_req ||
|
||
|
@@ -892,9 +923,9 @@ void vbg_core_exit(struct vbg_dev *gdev)
|
||
|
* vboxguest_linux.c calls this when userspace opens the char-device.
|
||
|
* Return: A pointer to the new session or an ERR_PTR on error.
|
||
|
* @gdev: The Guest extension device.
|
||
|
- * @user: Set if this is a session for the vboxuser device.
|
||
|
+ * @requestor: VMMDEV_REQUESTOR_* flags
|
||
|
*/
|
||
|
-struct vbg_session *vbg_core_open_session(struct vbg_dev *gdev, bool user)
|
||
|
+struct vbg_session *vbg_core_open_session(struct vbg_dev *gdev, u32 requestor)
|
||
|
{
|
||
|
struct vbg_session *session;
|
||
|
|
||
|
@@ -903,7 +934,7 @@ struct vbg_session *vbg_core_open_session(struct vbg_dev *gdev, bool user)
|
||
|
return ERR_PTR(-ENOMEM);
|
||
|
|
||
|
session->gdev = gdev;
|
||
|
- session->user_session = user;
|
||
|
+ session->requestor = requestor;
|
||
|
|
||
|
return session;
|
||
|
}
|
||
|
@@ -924,7 +955,9 @@ void vbg_core_close_session(struct vbg_session *session)
|
||
|
if (!session->hgcm_client_ids[i])
|
||
|
continue;
|
||
|
|
||
|
- vbg_hgcm_disconnect(gdev, session->hgcm_client_ids[i], &rc);
|
||
|
+ /* requestor is kernel here, as we're cleaning up. */
|
||
|
+ vbg_hgcm_disconnect(gdev, VBG_KERNEL_REQUEST,
|
||
|
+ session->hgcm_client_ids[i], &rc);
|
||
|
}
|
||
|
|
||
|
kfree(session);
|
||
|
@@ -1152,7 +1185,8 @@ static int vbg_req_allowed(struct vbg_dev *gdev, struct vbg_session *session,
|
||
|
return -EPERM;
|
||
|
}
|
||
|
|
||
|
- if (trusted_apps_only && session->user_session) {
|
||
|
+ if (trusted_apps_only &&
|
||
|
+ (session->requestor & VMMDEV_REQUESTOR_USER_DEVICE)) {
|
||
|
vbg_err("Denying userspace vmm call type %#08x through vboxuser device node\n",
|
||
|
req->request_type);
|
||
|
return -EPERM;
|
||
|
@@ -1209,8 +1243,8 @@ static int vbg_ioctl_hgcm_connect(struct vbg_dev *gdev,
|
||
|
if (i >= ARRAY_SIZE(session->hgcm_client_ids))
|
||
|
return -EMFILE;
|
||
|
|
||
|
- ret = vbg_hgcm_connect(gdev, &conn->u.in.loc, &client_id,
|
||
|
- &conn->hdr.rc);
|
||
|
+ ret = vbg_hgcm_connect(gdev, session->requestor, &conn->u.in.loc,
|
||
|
+ &client_id, &conn->hdr.rc);
|
||
|
|
||
|
mutex_lock(&gdev->session_mutex);
|
||
|
if (ret == 0 && conn->hdr.rc >= 0) {
|
||
|
@@ -1251,7 +1285,8 @@ static int vbg_ioctl_hgcm_disconnect(struct vbg_dev *gdev,
|
||
|
if (i >= ARRAY_SIZE(session->hgcm_client_ids))
|
||
|
return -EINVAL;
|
||
|
|
||
|
- ret = vbg_hgcm_disconnect(gdev, client_id, &disconn->hdr.rc);
|
||
|
+ ret = vbg_hgcm_disconnect(gdev, session->requestor, client_id,
|
||
|
+ &disconn->hdr.rc);
|
||
|
|
||
|
mutex_lock(&gdev->session_mutex);
|
||
|
if (ret == 0 && disconn->hdr.rc >= 0)
|
||
|
@@ -1313,12 +1348,12 @@ static int vbg_ioctl_hgcm_call(struct vbg_dev *gdev,
|
||
|
}
|
||
|
|
||
|
if (IS_ENABLED(CONFIG_COMPAT) && f32bit)
|
||
|
- ret = vbg_hgcm_call32(gdev, client_id,
|
||
|
+ ret = vbg_hgcm_call32(gdev, session->requestor, client_id,
|
||
|
call->function, call->timeout_ms,
|
||
|
VBG_IOCTL_HGCM_CALL_PARMS32(call),
|
||
|
call->parm_count, &call->hdr.rc);
|
||
|
else
|
||
|
- ret = vbg_hgcm_call(gdev, client_id,
|
||
|
+ ret = vbg_hgcm_call(gdev, session->requestor, client_id,
|
||
|
call->function, call->timeout_ms,
|
||
|
VBG_IOCTL_HGCM_CALL_PARMS(call),
|
||
|
call->parm_count, &call->hdr.rc);
|
||
|
@@ -1408,6 +1443,7 @@ static int vbg_ioctl_check_balloon(struct vbg_dev *gdev,
|
||
|
}
|
||
|
|
||
|
static int vbg_ioctl_write_core_dump(struct vbg_dev *gdev,
|
||
|
+ struct vbg_session *session,
|
||
|
struct vbg_ioctl_write_coredump *dump)
|
||
|
{
|
||
|
struct vmmdev_write_core_dump *req;
|
||
|
@@ -1415,7 +1451,8 @@ static int vbg_ioctl_write_core_dump(struct vbg_dev *gdev,
|
||
|
if (vbg_ioctl_chk(&dump->hdr, sizeof(dump->u.in), 0))
|
||
|
return -EINVAL;
|
||
|
|
||
|
- req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_WRITE_COREDUMP);
|
||
|
+ req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_WRITE_COREDUMP,
|
||
|
+ session->requestor);
|
||
|
if (!req)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
@@ -1476,7 +1513,7 @@ int vbg_core_ioctl(struct vbg_session *session, unsigned int req, void *data)
|
||
|
case VBG_IOCTL_CHECK_BALLOON:
|
||
|
return vbg_ioctl_check_balloon(gdev, data);
|
||
|
case VBG_IOCTL_WRITE_CORE_DUMP:
|
||
|
- return vbg_ioctl_write_core_dump(gdev, data);
|
||
|
+ return vbg_ioctl_write_core_dump(gdev, session, data);
|
||
|
}
|
||
|
|
||
|
/* Variable sized requests. */
|
||
|
@@ -1508,7 +1545,8 @@ int vbg_core_set_mouse_status(struct vbg_dev *gdev, u32 features)
|
||
|
struct vmmdev_mouse_status *req;
|
||
|
int rc;
|
||
|
|
||
|
- req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_MOUSE_STATUS);
|
||
|
+ req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_MOUSE_STATUS,
|
||
|
+ VBG_KERNEL_REQUEST);
|
||
|
if (!req)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
diff --git a/drivers/virt/vboxguest/vboxguest_core.h b/drivers/virt/vboxguest/vboxguest_core.h
|
||
|
index 7ad9ec45bfa9..4188c12b839f 100644
|
||
|
--- a/drivers/virt/vboxguest/vboxguest_core.h
|
||
|
+++ b/drivers/virt/vboxguest/vboxguest_core.h
|
||
|
@@ -154,15 +154,15 @@ struct vbg_session {
|
||
|
* host. Protected by vbg_gdev.session_mutex.
|
||
|
*/
|
||
|
u32 guest_caps;
|
||
|
- /** Does this session belong to a root process or a user one? */
|
||
|
- bool user_session;
|
||
|
+ /** VMMDEV_REQUESTOR_* flags */
|
||
|
+ u32 requestor;
|
||
|
/** Set on CANCEL_ALL_WAITEVENTS, protected by vbg_devevent_spinlock. */
|
||
|
bool cancel_waiters;
|
||
|
};
|
||
|
|
||
|
int vbg_core_init(struct vbg_dev *gdev, u32 fixed_events);
|
||
|
void vbg_core_exit(struct vbg_dev *gdev);
|
||
|
-struct vbg_session *vbg_core_open_session(struct vbg_dev *gdev, bool user);
|
||
|
+struct vbg_session *vbg_core_open_session(struct vbg_dev *gdev, u32 requestor);
|
||
|
void vbg_core_close_session(struct vbg_session *session);
|
||
|
int vbg_core_ioctl(struct vbg_session *session, unsigned int req, void *data);
|
||
|
int vbg_core_set_mouse_status(struct vbg_dev *gdev, u32 features);
|
||
|
@@ -172,12 +172,13 @@ irqreturn_t vbg_core_isr(int irq, void *dev_id);
|
||
|
void vbg_linux_mouse_event(struct vbg_dev *gdev);
|
||
|
|
||
|
/* Private (non exported) functions form vboxguest_utils.c */
|
||
|
-void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type);
|
||
|
+void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type,
|
||
|
+ u32 requestor);
|
||
|
void vbg_req_free(void *req, size_t len);
|
||
|
int vbg_req_perform(struct vbg_dev *gdev, void *req);
|
||
|
int vbg_hgcm_call32(
|
||
|
- struct vbg_dev *gdev, u32 client_id, u32 function, u32 timeout_ms,
|
||
|
- struct vmmdev_hgcm_function_parameter32 *parm32, u32 parm_count,
|
||
|
- int *vbox_status);
|
||
|
+ struct vbg_dev *gdev, u32 requestor, u32 client_id, u32 function,
|
||
|
+ u32 timeout_ms, struct vmmdev_hgcm_function_parameter32 *parm32,
|
||
|
+ u32 parm_count, int *vbox_status);
|
||
|
|
||
|
#endif
|
||
|
diff --git a/drivers/virt/vboxguest/vboxguest_linux.c b/drivers/virt/vboxguest/vboxguest_linux.c
|
||
|
index 6e2a9619192d..6e8c0f1c1056 100644
|
||
|
--- a/drivers/virt/vboxguest/vboxguest_linux.c
|
||
|
+++ b/drivers/virt/vboxguest/vboxguest_linux.c
|
||
|
@@ -5,6 +5,7 @@
|
||
|
* Copyright (C) 2006-2016 Oracle Corporation
|
||
|
*/
|
||
|
|
||
|
+#include <linux/cred.h>
|
||
|
#include <linux/input.h>
|
||
|
#include <linux/kernel.h>
|
||
|
#include <linux/miscdevice.h>
|
||
|
@@ -28,6 +29,23 @@ static DEFINE_MUTEX(vbg_gdev_mutex);
|
||
|
/** Global vbg_gdev pointer used by vbg_get/put_gdev. */
|
||
|
static struct vbg_dev *vbg_gdev;
|
||
|
|
||
|
+static u32 vbg_misc_device_requestor(struct inode *inode)
|
||
|
+{
|
||
|
+ u32 requestor = VMMDEV_REQUESTOR_USERMODE |
|
||
|
+ VMMDEV_REQUESTOR_CON_DONT_KNOW |
|
||
|
+ VMMDEV_REQUESTOR_TRUST_NOT_GIVEN;
|
||
|
+
|
||
|
+ if (from_kuid(current_user_ns(), current->cred->uid) == 0)
|
||
|
+ requestor |= VMMDEV_REQUESTOR_USR_ROOT;
|
||
|
+ else
|
||
|
+ requestor |= VMMDEV_REQUESTOR_USR_USER;
|
||
|
+
|
||
|
+ if (in_egroup_p(inode->i_gid))
|
||
|
+ requestor |= VMMDEV_REQUESTOR_GRP_VBOX;
|
||
|
+
|
||
|
+ return requestor;
|
||
|
+}
|
||
|
+
|
||
|
static int vbg_misc_device_open(struct inode *inode, struct file *filp)
|
||
|
{
|
||
|
struct vbg_session *session;
|
||
|
@@ -36,7 +54,7 @@ static int vbg_misc_device_open(struct inode *inode, struct file *filp)
|
||
|
/* misc_open sets filp->private_data to our misc device */
|
||
|
gdev = container_of(filp->private_data, struct vbg_dev, misc_device);
|
||
|
|
||
|
- session = vbg_core_open_session(gdev, false);
|
||
|
+ session = vbg_core_open_session(gdev, vbg_misc_device_requestor(inode));
|
||
|
if (IS_ERR(session))
|
||
|
return PTR_ERR(session);
|
||
|
|
||
|
@@ -53,7 +71,8 @@ static int vbg_misc_device_user_open(struct inode *inode, struct file *filp)
|
||
|
gdev = container_of(filp->private_data, struct vbg_dev,
|
||
|
misc_device_user);
|
||
|
|
||
|
- session = vbg_core_open_session(gdev, false);
|
||
|
+ session = vbg_core_open_session(gdev, vbg_misc_device_requestor(inode) |
|
||
|
+ VMMDEV_REQUESTOR_USER_DEVICE);
|
||
|
if (IS_ERR(session))
|
||
|
return PTR_ERR(session);
|
||
|
|
||
|
@@ -115,7 +134,8 @@ static long vbg_misc_device_ioctl(struct file *filp, unsigned int req,
|
||
|
req == VBG_IOCTL_VMMDEV_REQUEST_BIG;
|
||
|
|
||
|
if (is_vmmdev_req)
|
||
|
- buf = vbg_req_alloc(size, VBG_IOCTL_HDR_TYPE_DEFAULT);
|
||
|
+ buf = vbg_req_alloc(size, VBG_IOCTL_HDR_TYPE_DEFAULT,
|
||
|
+ session->requestor);
|
||
|
else
|
||
|
buf = kmalloc(size, GFP_KERNEL);
|
||
|
if (!buf)
|
||
|
diff --git a/drivers/virt/vboxguest/vboxguest_utils.c b/drivers/virt/vboxguest/vboxguest_utils.c
|
||
|
index bf4474214b4d..75fd140b02ff 100644
|
||
|
--- a/drivers/virt/vboxguest/vboxguest_utils.c
|
||
|
+++ b/drivers/virt/vboxguest/vboxguest_utils.c
|
||
|
@@ -62,7 +62,8 @@ VBG_LOG(vbg_err, pr_err);
|
||
|
VBG_LOG(vbg_debug, pr_debug);
|
||
|
#endif
|
||
|
|
||
|
-void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type)
|
||
|
+void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type,
|
||
|
+ u32 requestor)
|
||
|
{
|
||
|
struct vmmdev_request_header *req;
|
||
|
int order = get_order(PAGE_ALIGN(len));
|
||
|
@@ -78,7 +79,7 @@ void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type)
|
||
|
req->request_type = req_type;
|
||
|
req->rc = VERR_GENERAL_FAILURE;
|
||
|
req->reserved1 = 0;
|
||
|
- req->reserved2 = 0;
|
||
|
+ req->requestor = requestor;
|
||
|
|
||
|
return req;
|
||
|
}
|
||
|
@@ -119,7 +120,7 @@ static bool hgcm_req_done(struct vbg_dev *gdev,
|
||
|
return done;
|
||
|
}
|
||
|
|
||
|
-int vbg_hgcm_connect(struct vbg_dev *gdev,
|
||
|
+int vbg_hgcm_connect(struct vbg_dev *gdev, u32 requestor,
|
||
|
struct vmmdev_hgcm_service_location *loc,
|
||
|
u32 *client_id, int *vbox_status)
|
||
|
{
|
||
|
@@ -127,7 +128,7 @@ int vbg_hgcm_connect(struct vbg_dev *gdev,
|
||
|
int rc;
|
||
|
|
||
|
hgcm_connect = vbg_req_alloc(sizeof(*hgcm_connect),
|
||
|
- VMMDEVREQ_HGCM_CONNECT);
|
||
|
+ VMMDEVREQ_HGCM_CONNECT, requestor);
|
||
|
if (!hgcm_connect)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
@@ -153,13 +154,15 @@ int vbg_hgcm_connect(struct vbg_dev *gdev,
|
||
|
}
|
||
|
EXPORT_SYMBOL(vbg_hgcm_connect);
|
||
|
|
||
|
-int vbg_hgcm_disconnect(struct vbg_dev *gdev, u32 client_id, int *vbox_status)
|
||
|
+int vbg_hgcm_disconnect(struct vbg_dev *gdev, u32 requestor,
|
||
|
+ u32 client_id, int *vbox_status)
|
||
|
{
|
||
|
struct vmmdev_hgcm_disconnect *hgcm_disconnect = NULL;
|
||
|
int rc;
|
||
|
|
||
|
hgcm_disconnect = vbg_req_alloc(sizeof(*hgcm_disconnect),
|
||
|
- VMMDEVREQ_HGCM_DISCONNECT);
|
||
|
+ VMMDEVREQ_HGCM_DISCONNECT,
|
||
|
+ requestor);
|
||
|
if (!hgcm_disconnect)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
@@ -593,9 +596,10 @@ static int hgcm_call_copy_back_result(
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
-int vbg_hgcm_call(struct vbg_dev *gdev, u32 client_id, u32 function,
|
||
|
- u32 timeout_ms, struct vmmdev_hgcm_function_parameter *parms,
|
||
|
- u32 parm_count, int *vbox_status)
|
||
|
+int vbg_hgcm_call(struct vbg_dev *gdev, u32 requestor, u32 client_id,
|
||
|
+ u32 function, u32 timeout_ms,
|
||
|
+ struct vmmdev_hgcm_function_parameter *parms, u32 parm_count,
|
||
|
+ int *vbox_status)
|
||
|
{
|
||
|
struct vmmdev_hgcm_call *call;
|
||
|
void **bounce_bufs = NULL;
|
||
|
@@ -615,7 +619,7 @@ int vbg_hgcm_call(struct vbg_dev *gdev, u32 client_id, u32 function,
|
||
|
goto free_bounce_bufs;
|
||
|
}
|
||
|
|
||
|
- call = vbg_req_alloc(size, VMMDEVREQ_HGCM_CALL);
|
||
|
+ call = vbg_req_alloc(size, VMMDEVREQ_HGCM_CALL, requestor);
|
||
|
if (!call) {
|
||
|
ret = -ENOMEM;
|
||
|
goto free_bounce_bufs;
|
||
|
@@ -647,9 +651,9 @@ EXPORT_SYMBOL(vbg_hgcm_call);
|
||
|
|
||
|
#ifdef CONFIG_COMPAT
|
||
|
int vbg_hgcm_call32(
|
||
|
- struct vbg_dev *gdev, u32 client_id, u32 function, u32 timeout_ms,
|
||
|
- struct vmmdev_hgcm_function_parameter32 *parm32, u32 parm_count,
|
||
|
- int *vbox_status)
|
||
|
+ struct vbg_dev *gdev, u32 requestor, u32 client_id, u32 function,
|
||
|
+ u32 timeout_ms, struct vmmdev_hgcm_function_parameter32 *parm32,
|
||
|
+ u32 parm_count, int *vbox_status)
|
||
|
{
|
||
|
struct vmmdev_hgcm_function_parameter *parm64 = NULL;
|
||
|
u32 i, size;
|
||
|
@@ -689,7 +693,7 @@ int vbg_hgcm_call32(
|
||
|
goto out_free;
|
||
|
}
|
||
|
|
||
|
- ret = vbg_hgcm_call(gdev, client_id, function, timeout_ms,
|
||
|
+ ret = vbg_hgcm_call(gdev, requestor, client_id, function, timeout_ms,
|
||
|
parm64, parm_count, vbox_status);
|
||
|
if (ret < 0)
|
||
|
goto out_free;
|
||
|
diff --git a/drivers/virt/vboxguest/vboxguest_version.h b/drivers/virt/vboxguest/vboxguest_version.h
|
||
|
index 77f0c8f8a231..84834dad38d5 100644
|
||
|
--- a/drivers/virt/vboxguest/vboxguest_version.h
|
||
|
+++ b/drivers/virt/vboxguest/vboxguest_version.h
|
||
|
@@ -9,11 +9,10 @@
|
||
|
#ifndef __VBOX_VERSION_H__
|
||
|
#define __VBOX_VERSION_H__
|
||
|
|
||
|
-/* Last synced October 4th 2017 */
|
||
|
-#define VBG_VERSION_MAJOR 5
|
||
|
-#define VBG_VERSION_MINOR 2
|
||
|
+#define VBG_VERSION_MAJOR 6
|
||
|
+#define VBG_VERSION_MINOR 0
|
||
|
#define VBG_VERSION_BUILD 0
|
||
|
-#define VBG_SVN_REV 68940
|
||
|
-#define VBG_VERSION_STRING "5.2.0"
|
||
|
+#define VBG_SVN_REV 127566
|
||
|
+#define VBG_VERSION_STRING "6.0.0"
|
||
|
|
||
|
#endif
|
||
|
diff --git a/drivers/virt/vboxguest/vmmdev.h b/drivers/virt/vboxguest/vmmdev.h
|
||
|
index 5e2ae978935d..6337b8d75d96 100644
|
||
|
--- a/drivers/virt/vboxguest/vmmdev.h
|
||
|
+++ b/drivers/virt/vboxguest/vmmdev.h
|
||
|
@@ -98,8 +98,8 @@ struct vmmdev_request_header {
|
||
|
s32 rc;
|
||
|
/** Reserved field no.1. MBZ. */
|
||
|
u32 reserved1;
|
||
|
- /** Reserved field no.2. MBZ. */
|
||
|
- u32 reserved2;
|
||
|
+ /** IN: Requestor information (VMMDEV_REQUESTOR_*) */
|
||
|
+ u32 requestor;
|
||
|
};
|
||
|
VMMDEV_ASSERT_SIZE(vmmdev_request_header, 24);
|
||
|
|
||
|
@@ -247,6 +247,8 @@ struct vmmdev_guest_info {
|
||
|
};
|
||
|
VMMDEV_ASSERT_SIZE(vmmdev_guest_info, 24 + 8);
|
||
|
|
||
|
+#define VMMDEV_GUEST_INFO2_ADDITIONS_FEATURES_REQUESTOR_INFO BIT(0)
|
||
|
+
|
||
|
/** struct vmmdev_guestinfo2 - Guest information report, version 2. */
|
||
|
struct vmmdev_guest_info2 {
|
||
|
/** Header. */
|
||
|
@@ -259,7 +261,7 @@ struct vmmdev_guest_info2 {
|
||
|
u32 additions_build;
|
||
|
/** SVN revision. */
|
||
|
u32 additions_revision;
|
||
|
- /** Feature mask, currently unused. */
|
||
|
+ /** Feature mask. */
|
||
|
u32 additions_features;
|
||
|
/**
|
||
|
* The intentional meaning of this field was:
|
||
|
diff --git a/include/linux/vbox_utils.h b/include/linux/vbox_utils.h
|
||
|
index a240ed2a0372..ff56c443180c 100644
|
||
|
--- a/include/linux/vbox_utils.h
|
||
|
+++ b/include/linux/vbox_utils.h
|
||
|
@@ -24,15 +24,17 @@ __printf(1, 2) void vbg_debug(const char *fmt, ...);
|
||
|
#define vbg_debug pr_debug
|
||
|
#endif
|
||
|
|
||
|
-int vbg_hgcm_connect(struct vbg_dev *gdev,
|
||
|
+int vbg_hgcm_connect(struct vbg_dev *gdev, u32 requestor,
|
||
|
struct vmmdev_hgcm_service_location *loc,
|
||
|
u32 *client_id, int *vbox_status);
|
||
|
|
||
|
-int vbg_hgcm_disconnect(struct vbg_dev *gdev, u32 client_id, int *vbox_status);
|
||
|
+int vbg_hgcm_disconnect(struct vbg_dev *gdev, u32 requestor,
|
||
|
+ u32 client_id, int *vbox_status);
|
||
|
|
||
|
-int vbg_hgcm_call(struct vbg_dev *gdev, u32 client_id, u32 function,
|
||
|
- u32 timeout_ms, struct vmmdev_hgcm_function_parameter *parms,
|
||
|
- u32 parm_count, int *vbox_status);
|
||
|
+int vbg_hgcm_call(struct vbg_dev *gdev, u32 requestor, u32 client_id,
|
||
|
+ u32 function, u32 timeout_ms,
|
||
|
+ struct vmmdev_hgcm_function_parameter *parms, u32 parm_count,
|
||
|
+ int *vbox_status);
|
||
|
|
||
|
/**
|
||
|
* Convert a VirtualBox status code to a standard Linux kernel return value.
|
||
|
diff --git a/include/uapi/linux/vbox_vmmdev_types.h b/include/uapi/linux/vbox_vmmdev_types.h
|
||
|
index 0e68024f36c7..8c535c2594ad 100644
|
||
|
--- a/include/uapi/linux/vbox_vmmdev_types.h
|
||
|
+++ b/include/uapi/linux/vbox_vmmdev_types.h
|
||
|
@@ -102,6 +102,37 @@ enum vmmdev_request_type {
|
||
|
#define VMMDEVREQ_HGCM_CALL VMMDEVREQ_HGCM_CALL32
|
||
|
#endif
|
||
|
|
||
|
+/* vmmdev_request_header.requestor defines */
|
||
|
+
|
||
|
+/* Requestor user not given. */
|
||
|
+#define VMMDEV_REQUESTOR_USR_NOT_GIVEN 0x00000000
|
||
|
+/* The kernel driver (VBoxGuest) is the requestor. */
|
||
|
+#define VMMDEV_REQUESTOR_USR_DRV 0x00000001
|
||
|
+/* Some other kernel driver is the requestor. */
|
||
|
+#define VMMDEV_REQUESTOR_USR_DRV_OTHER 0x00000002
|
||
|
+/* The root or a admin user is the requestor. */
|
||
|
+#define VMMDEV_REQUESTOR_USR_ROOT 0x00000003
|
||
|
+/* Regular joe user is making the request. */
|
||
|
+#define VMMDEV_REQUESTOR_USR_USER 0x00000006
|
||
|
+/* User classification mask. */
|
||
|
+#define VMMDEV_REQUESTOR_USR_MASK 0x00000007
|
||
|
+/* Kernel mode request. */
|
||
|
+#define VMMDEV_REQUESTOR_KERNEL 0x00000000
|
||
|
+/* User mode request. */
|
||
|
+#define VMMDEV_REQUESTOR_USERMODE 0x00000008
|
||
|
+/* Don't know the physical console association of the requestor. */
|
||
|
+#define VMMDEV_REQUESTOR_CON_DONT_KNOW 0x00000000
|
||
|
+/* Console classification mask. */
|
||
|
+#define VMMDEV_REQUESTOR_CON_MASK 0x00000040
|
||
|
+/* Requestor is member of special VirtualBox user group. */
|
||
|
+#define VMMDEV_REQUESTOR_GRP_VBOX 0x00000080
|
||
|
+/* Requestor trust level: Unspecified */
|
||
|
+#define VMMDEV_REQUESTOR_TRUST_NOT_GIVEN 0x00000000
|
||
|
+/* Requestor trust level mask */
|
||
|
+#define VMMDEV_REQUESTOR_TRUST_MASK 0x00007000
|
||
|
+/* Requestor is using the less trusted user device node (/dev/vboxuser) */
|
||
|
+#define VMMDEV_REQUESTOR_USER_DEVICE 0x00008000
|
||
|
+
|
||
|
/** HGCM service location types. */
|
||
|
enum vmmdev_hgcm_service_location_type {
|
||
|
VMMDEV_HGCM_LOC_INVALID = 0,
|
||
|
--
|
||
|
2.21.0
|
||
|
|