Skip to content

Commit 0532a1b

Browse files
jwrdegoedegregkh
authored andcommitted
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. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 80045e1 commit 0532a1b

File tree

8 files changed

+197
-71
lines changed

8 files changed

+197
-71
lines changed

drivers/virt/vboxguest/vboxguest_core.c

Lines changed: 72 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727

2828
#define GUEST_MAPPINGS_TRIES 5
2929

30+
#define VBG_KERNEL_REQUEST \
31+
(VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV | \
32+
VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN)
33+
3034
/**
3135
* Reserves memory in which the VMM can relocate any guest mappings
3236
* that are floating around.
@@ -48,7 +52,8 @@ static void vbg_guest_mappings_init(struct vbg_dev *gdev)
4852
int i, rc;
4953

5054
/* Query the required space. */
51-
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_GET_HYPERVISOR_INFO);
55+
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_GET_HYPERVISOR_INFO,
56+
VBG_KERNEL_REQUEST);
5257
if (!req)
5358
return;
5459

@@ -135,7 +140,8 @@ static void vbg_guest_mappings_exit(struct vbg_dev *gdev)
135140
* Tell the host that we're going to free the memory we reserved for
136141
* it, the free it up. (Leak the memory if anything goes wrong here.)
137142
*/
138-
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_HYPERVISOR_INFO);
143+
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_HYPERVISOR_INFO,
144+
VBG_KERNEL_REQUEST);
139145
if (!req)
140146
return;
141147

@@ -172,8 +178,10 @@ static int vbg_report_guest_info(struct vbg_dev *gdev)
172178
struct vmmdev_guest_info2 *req2 = NULL;
173179
int rc, ret = -ENOMEM;
174180

175-
req1 = vbg_req_alloc(sizeof(*req1), VMMDEVREQ_REPORT_GUEST_INFO);
176-
req2 = vbg_req_alloc(sizeof(*req2), VMMDEVREQ_REPORT_GUEST_INFO2);
181+
req1 = vbg_req_alloc(sizeof(*req1), VMMDEVREQ_REPORT_GUEST_INFO,
182+
VBG_KERNEL_REQUEST);
183+
req2 = vbg_req_alloc(sizeof(*req2), VMMDEVREQ_REPORT_GUEST_INFO2,
184+
VBG_KERNEL_REQUEST);
177185
if (!req1 || !req2)
178186
goto out_free;
179187

@@ -187,8 +195,8 @@ static int vbg_report_guest_info(struct vbg_dev *gdev)
187195
req2->additions_minor = VBG_VERSION_MINOR;
188196
req2->additions_build = VBG_VERSION_BUILD;
189197
req2->additions_revision = VBG_SVN_REV;
190-
/* (no features defined yet) */
191-
req2->additions_features = 0;
198+
req2->additions_features =
199+
VMMDEV_GUEST_INFO2_ADDITIONS_FEATURES_REQUESTOR_INFO;
192200
strlcpy(req2->name, VBG_VERSION_STRING,
193201
sizeof(req2->name));
194202

@@ -230,7 +238,8 @@ static int vbg_report_driver_status(struct vbg_dev *gdev, bool active)
230238
struct vmmdev_guest_status *req;
231239
int rc;
232240

233-
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_REPORT_GUEST_STATUS);
241+
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_REPORT_GUEST_STATUS,
242+
VBG_KERNEL_REQUEST);
234243
if (!req)
235244
return -ENOMEM;
236245

@@ -423,7 +432,8 @@ static int vbg_heartbeat_host_config(struct vbg_dev *gdev, bool enabled)
423432
struct vmmdev_heartbeat *req;
424433
int rc;
425434

426-
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_HEARTBEAT_CONFIGURE);
435+
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_HEARTBEAT_CONFIGURE,
436+
VBG_KERNEL_REQUEST);
427437
if (!req)
428438
return -ENOMEM;
429439

@@ -457,7 +467,8 @@ static int vbg_heartbeat_init(struct vbg_dev *gdev)
457467

458468
gdev->guest_heartbeat_req = vbg_req_alloc(
459469
sizeof(*gdev->guest_heartbeat_req),
460-
VMMDEVREQ_GUEST_HEARTBEAT);
470+
VMMDEVREQ_GUEST_HEARTBEAT,
471+
VBG_KERNEL_REQUEST);
461472
if (!gdev->guest_heartbeat_req)
462473
return -ENOMEM;
463474

@@ -528,7 +539,8 @@ static int vbg_reset_host_event_filter(struct vbg_dev *gdev,
528539
struct vmmdev_mask *req;
529540
int rc;
530541

531-
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_CTL_GUEST_FILTER_MASK);
542+
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_CTL_GUEST_FILTER_MASK,
543+
VBG_KERNEL_REQUEST);
532544
if (!req)
533545
return -ENOMEM;
534546

@@ -567,8 +579,14 @@ static int vbg_set_session_event_filter(struct vbg_dev *gdev,
567579
u32 changed, previous;
568580
int rc, ret = 0;
569581

570-
/* Allocate a request buffer before taking the spinlock */
571-
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_CTL_GUEST_FILTER_MASK);
582+
/*
583+
* Allocate a request buffer before taking the spinlock, when
584+
* the session is being terminated the requestor is the kernel,
585+
* as we're cleaning up.
586+
*/
587+
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_CTL_GUEST_FILTER_MASK,
588+
session_termination ? VBG_KERNEL_REQUEST :
589+
session->requestor);
572590
if (!req) {
573591
if (!session_termination)
574592
return -ENOMEM;
@@ -627,7 +645,8 @@ static int vbg_reset_host_capabilities(struct vbg_dev *gdev)
627645
struct vmmdev_mask *req;
628646
int rc;
629647

630-
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_GUEST_CAPABILITIES);
648+
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_GUEST_CAPABILITIES,
649+
VBG_KERNEL_REQUEST);
631650
if (!req)
632651
return -ENOMEM;
633652

@@ -662,8 +681,14 @@ static int vbg_set_session_capabilities(struct vbg_dev *gdev,
662681
u32 changed, previous;
663682
int rc, ret = 0;
664683

665-
/* Allocate a request buffer before taking the spinlock */
666-
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_GUEST_CAPABILITIES);
684+
/*
685+
* Allocate a request buffer before taking the spinlock, when
686+
* the session is being terminated the requestor is the kernel,
687+
* as we're cleaning up.
688+
*/
689+
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_GUEST_CAPABILITIES,
690+
session_termination ? VBG_KERNEL_REQUEST :
691+
session->requestor);
667692
if (!req) {
668693
if (!session_termination)
669694
return -ENOMEM;
@@ -722,7 +747,8 @@ static int vbg_query_host_version(struct vbg_dev *gdev)
722747
struct vmmdev_host_version *req;
723748
int rc, ret;
724749

725-
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_GET_HOST_VERSION);
750+
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_GET_HOST_VERSION,
751+
VBG_KERNEL_REQUEST);
726752
if (!req)
727753
return -ENOMEM;
728754

@@ -783,19 +809,24 @@ int vbg_core_init(struct vbg_dev *gdev, u32 fixed_events)
783809

784810
gdev->mem_balloon.get_req =
785811
vbg_req_alloc(sizeof(*gdev->mem_balloon.get_req),
786-
VMMDEVREQ_GET_MEMBALLOON_CHANGE_REQ);
812+
VMMDEVREQ_GET_MEMBALLOON_CHANGE_REQ,
813+
VBG_KERNEL_REQUEST);
787814
gdev->mem_balloon.change_req =
788815
vbg_req_alloc(sizeof(*gdev->mem_balloon.change_req),
789-
VMMDEVREQ_CHANGE_MEMBALLOON);
816+
VMMDEVREQ_CHANGE_MEMBALLOON,
817+
VBG_KERNEL_REQUEST);
790818
gdev->cancel_req =
791819
vbg_req_alloc(sizeof(*(gdev->cancel_req)),
792-
VMMDEVREQ_HGCM_CANCEL2);
820+
VMMDEVREQ_HGCM_CANCEL2,
821+
VBG_KERNEL_REQUEST);
793822
gdev->ack_events_req =
794823
vbg_req_alloc(sizeof(*gdev->ack_events_req),
795-
VMMDEVREQ_ACKNOWLEDGE_EVENTS);
824+
VMMDEVREQ_ACKNOWLEDGE_EVENTS,
825+
VBG_KERNEL_REQUEST);
796826
gdev->mouse_status_req =
797827
vbg_req_alloc(sizeof(*gdev->mouse_status_req),
798-
VMMDEVREQ_GET_MOUSE_STATUS);
828+
VMMDEVREQ_GET_MOUSE_STATUS,
829+
VBG_KERNEL_REQUEST);
799830

800831
if (!gdev->mem_balloon.get_req || !gdev->mem_balloon.change_req ||
801832
!gdev->cancel_req || !gdev->ack_events_req ||
@@ -892,9 +923,9 @@ void vbg_core_exit(struct vbg_dev *gdev)
892923
* vboxguest_linux.c calls this when userspace opens the char-device.
893924
* Return: A pointer to the new session or an ERR_PTR on error.
894925
* @gdev: The Guest extension device.
895-
* @user: Set if this is a session for the vboxuser device.
926+
* @requestor: VMMDEV_REQUESTOR_* flags
896927
*/
897-
struct vbg_session *vbg_core_open_session(struct vbg_dev *gdev, bool user)
928+
struct vbg_session *vbg_core_open_session(struct vbg_dev *gdev, u32 requestor)
898929
{
899930
struct vbg_session *session;
900931

@@ -903,7 +934,7 @@ struct vbg_session *vbg_core_open_session(struct vbg_dev *gdev, bool user)
903934
return ERR_PTR(-ENOMEM);
904935

905936
session->gdev = gdev;
906-
session->user_session = user;
937+
session->requestor = requestor;
907938

908939
return session;
909940
}
@@ -924,7 +955,9 @@ void vbg_core_close_session(struct vbg_session *session)
924955
if (!session->hgcm_client_ids[i])
925956
continue;
926957

927-
vbg_hgcm_disconnect(gdev, session->hgcm_client_ids[i], &rc);
958+
/* requestor is kernel here, as we're cleaning up. */
959+
vbg_hgcm_disconnect(gdev, VBG_KERNEL_REQUEST,
960+
session->hgcm_client_ids[i], &rc);
928961
}
929962

930963
kfree(session);
@@ -1152,7 +1185,8 @@ static int vbg_req_allowed(struct vbg_dev *gdev, struct vbg_session *session,
11521185
return -EPERM;
11531186
}
11541187

1155-
if (trusted_apps_only && session->user_session) {
1188+
if (trusted_apps_only &&
1189+
(session->requestor & VMMDEV_REQUESTOR_USER_DEVICE)) {
11561190
vbg_err("Denying userspace vmm call type %#08x through vboxuser device node\n",
11571191
req->request_type);
11581192
return -EPERM;
@@ -1209,8 +1243,8 @@ static int vbg_ioctl_hgcm_connect(struct vbg_dev *gdev,
12091243
if (i >= ARRAY_SIZE(session->hgcm_client_ids))
12101244
return -EMFILE;
12111245

1212-
ret = vbg_hgcm_connect(gdev, &conn->u.in.loc, &client_id,
1213-
&conn->hdr.rc);
1246+
ret = vbg_hgcm_connect(gdev, session->requestor, &conn->u.in.loc,
1247+
&client_id, &conn->hdr.rc);
12141248

12151249
mutex_lock(&gdev->session_mutex);
12161250
if (ret == 0 && conn->hdr.rc >= 0) {
@@ -1251,7 +1285,8 @@ static int vbg_ioctl_hgcm_disconnect(struct vbg_dev *gdev,
12511285
if (i >= ARRAY_SIZE(session->hgcm_client_ids))
12521286
return -EINVAL;
12531287

1254-
ret = vbg_hgcm_disconnect(gdev, client_id, &disconn->hdr.rc);
1288+
ret = vbg_hgcm_disconnect(gdev, session->requestor, client_id,
1289+
&disconn->hdr.rc);
12551290

12561291
mutex_lock(&gdev->session_mutex);
12571292
if (ret == 0 && disconn->hdr.rc >= 0)
@@ -1313,12 +1348,12 @@ static int vbg_ioctl_hgcm_call(struct vbg_dev *gdev,
13131348
}
13141349

13151350
if (IS_ENABLED(CONFIG_COMPAT) && f32bit)
1316-
ret = vbg_hgcm_call32(gdev, client_id,
1351+
ret = vbg_hgcm_call32(gdev, session->requestor, client_id,
13171352
call->function, call->timeout_ms,
13181353
VBG_IOCTL_HGCM_CALL_PARMS32(call),
13191354
call->parm_count, &call->hdr.rc);
13201355
else
1321-
ret = vbg_hgcm_call(gdev, client_id,
1356+
ret = vbg_hgcm_call(gdev, session->requestor, client_id,
13221357
call->function, call->timeout_ms,
13231358
VBG_IOCTL_HGCM_CALL_PARMS(call),
13241359
call->parm_count, &call->hdr.rc);
@@ -1408,14 +1443,16 @@ static int vbg_ioctl_check_balloon(struct vbg_dev *gdev,
14081443
}
14091444

14101445
static int vbg_ioctl_write_core_dump(struct vbg_dev *gdev,
1446+
struct vbg_session *session,
14111447
struct vbg_ioctl_write_coredump *dump)
14121448
{
14131449
struct vmmdev_write_core_dump *req;
14141450

14151451
if (vbg_ioctl_chk(&dump->hdr, sizeof(dump->u.in), 0))
14161452
return -EINVAL;
14171453

1418-
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_WRITE_COREDUMP);
1454+
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_WRITE_COREDUMP,
1455+
session->requestor);
14191456
if (!req)
14201457
return -ENOMEM;
14211458

@@ -1476,7 +1513,7 @@ int vbg_core_ioctl(struct vbg_session *session, unsigned int req, void *data)
14761513
case VBG_IOCTL_CHECK_BALLOON:
14771514
return vbg_ioctl_check_balloon(gdev, data);
14781515
case VBG_IOCTL_WRITE_CORE_DUMP:
1479-
return vbg_ioctl_write_core_dump(gdev, data);
1516+
return vbg_ioctl_write_core_dump(gdev, session, data);
14801517
}
14811518

14821519
/* Variable sized requests. */
@@ -1508,7 +1545,8 @@ int vbg_core_set_mouse_status(struct vbg_dev *gdev, u32 features)
15081545
struct vmmdev_mouse_status *req;
15091546
int rc;
15101547

1511-
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_MOUSE_STATUS);
1548+
req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_MOUSE_STATUS,
1549+
VBG_KERNEL_REQUEST);
15121550
if (!req)
15131551
return -ENOMEM;
15141552

drivers/virt/vboxguest/vboxguest_core.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,15 @@ struct vbg_session {
154154
* host. Protected by vbg_gdev.session_mutex.
155155
*/
156156
u32 guest_caps;
157-
/** Does this session belong to a root process or a user one? */
158-
bool user_session;
157+
/** VMMDEV_REQUESTOR_* flags */
158+
u32 requestor;
159159
/** Set on CANCEL_ALL_WAITEVENTS, protected by vbg_devevent_spinlock. */
160160
bool cancel_waiters;
161161
};
162162

163163
int vbg_core_init(struct vbg_dev *gdev, u32 fixed_events);
164164
void vbg_core_exit(struct vbg_dev *gdev);
165-
struct vbg_session *vbg_core_open_session(struct vbg_dev *gdev, bool user);
165+
struct vbg_session *vbg_core_open_session(struct vbg_dev *gdev, u32 requestor);
166166
void vbg_core_close_session(struct vbg_session *session);
167167
int vbg_core_ioctl(struct vbg_session *session, unsigned int req, void *data);
168168
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);
172172
void vbg_linux_mouse_event(struct vbg_dev *gdev);
173173

174174
/* Private (non exported) functions form vboxguest_utils.c */
175-
void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type);
175+
void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type,
176+
u32 requestor);
176177
void vbg_req_free(void *req, size_t len);
177178
int vbg_req_perform(struct vbg_dev *gdev, void *req);
178179
int vbg_hgcm_call32(
179-
struct vbg_dev *gdev, u32 client_id, u32 function, u32 timeout_ms,
180-
struct vmmdev_hgcm_function_parameter32 *parm32, u32 parm_count,
181-
int *vbox_status);
180+
struct vbg_dev *gdev, u32 requestor, u32 client_id, u32 function,
181+
u32 timeout_ms, struct vmmdev_hgcm_function_parameter32 *parm32,
182+
u32 parm_count, int *vbox_status);
182183

183184
#endif

drivers/virt/vboxguest/vboxguest_linux.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Copyright (C) 2006-2016 Oracle Corporation
66
*/
77

8+
#include <linux/cred.h>
89
#include <linux/input.h>
910
#include <linux/kernel.h>
1011
#include <linux/miscdevice.h>
@@ -28,6 +29,23 @@ static DEFINE_MUTEX(vbg_gdev_mutex);
2829
/** Global vbg_gdev pointer used by vbg_get/put_gdev. */
2930
static struct vbg_dev *vbg_gdev;
3031

32+
static u32 vbg_misc_device_requestor(struct inode *inode)
33+
{
34+
u32 requestor = VMMDEV_REQUESTOR_USERMODE |
35+
VMMDEV_REQUESTOR_CON_DONT_KNOW |
36+
VMMDEV_REQUESTOR_TRUST_NOT_GIVEN;
37+
38+
if (from_kuid(current_user_ns(), current->cred->uid) == 0)
39+
requestor |= VMMDEV_REQUESTOR_USR_ROOT;
40+
else
41+
requestor |= VMMDEV_REQUESTOR_USR_USER;
42+
43+
if (in_egroup_p(inode->i_gid))
44+
requestor |= VMMDEV_REQUESTOR_GRP_VBOX;
45+
46+
return requestor;
47+
}
48+
3149
static int vbg_misc_device_open(struct inode *inode, struct file *filp)
3250
{
3351
struct vbg_session *session;
@@ -36,7 +54,7 @@ static int vbg_misc_device_open(struct inode *inode, struct file *filp)
3654
/* misc_open sets filp->private_data to our misc device */
3755
gdev = container_of(filp->private_data, struct vbg_dev, misc_device);
3856

39-
session = vbg_core_open_session(gdev, false);
57+
session = vbg_core_open_session(gdev, vbg_misc_device_requestor(inode));
4058
if (IS_ERR(session))
4159
return PTR_ERR(session);
4260

@@ -53,7 +71,8 @@ static int vbg_misc_device_user_open(struct inode *inode, struct file *filp)
5371
gdev = container_of(filp->private_data, struct vbg_dev,
5472
misc_device_user);
5573

56-
session = vbg_core_open_session(gdev, false);
74+
session = vbg_core_open_session(gdev, vbg_misc_device_requestor(inode) |
75+
VMMDEV_REQUESTOR_USER_DEVICE);
5776
if (IS_ERR(session))
5877
return PTR_ERR(session);
5978

@@ -115,7 +134,8 @@ static long vbg_misc_device_ioctl(struct file *filp, unsigned int req,
115134
req == VBG_IOCTL_VMMDEV_REQUEST_BIG;
116135

117136
if (is_vmmdev_req)
118-
buf = vbg_req_alloc(size, VBG_IOCTL_HDR_TYPE_DEFAULT);
137+
buf = vbg_req_alloc(size, VBG_IOCTL_HDR_TYPE_DEFAULT,
138+
session->requestor);
119139
else
120140
buf = kmalloc(size, GFP_KERNEL);
121141
if (!buf)

0 commit comments

Comments
 (0)