Commit 0532a1b0 authored by Hans de Goede's avatar Hans de Goede Committed by Greg Kroah-Hartman

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: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 80045e14
This diff is collapsed.
...@@ -154,15 +154,15 @@ struct vbg_session { ...@@ -154,15 +154,15 @@ struct vbg_session {
* host. Protected by vbg_gdev.session_mutex. * host. Protected by vbg_gdev.session_mutex.
*/ */
u32 guest_caps; u32 guest_caps;
/** Does this session belong to a root process or a user one? */ /** VMMDEV_REQUESTOR_* flags */
bool user_session; u32 requestor;
/** Set on CANCEL_ALL_WAITEVENTS, protected by vbg_devevent_spinlock. */ /** Set on CANCEL_ALL_WAITEVENTS, protected by vbg_devevent_spinlock. */
bool cancel_waiters; bool cancel_waiters;
}; };
int vbg_core_init(struct vbg_dev *gdev, u32 fixed_events); int vbg_core_init(struct vbg_dev *gdev, u32 fixed_events);
void vbg_core_exit(struct vbg_dev *gdev); 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); 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_ioctl(struct vbg_session *session, unsigned int req, void *data);
int vbg_core_set_mouse_status(struct vbg_dev *gdev, u32 features); 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); ...@@ -172,12 +172,13 @@ irqreturn_t vbg_core_isr(int irq, void *dev_id);
void vbg_linux_mouse_event(struct vbg_dev *gdev); void vbg_linux_mouse_event(struct vbg_dev *gdev);
/* Private (non exported) functions form vboxguest_utils.c */ /* 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); void vbg_req_free(void *req, size_t len);
int vbg_req_perform(struct vbg_dev *gdev, void *req); int vbg_req_perform(struct vbg_dev *gdev, void *req);
int vbg_hgcm_call32( int vbg_hgcm_call32(
struct vbg_dev *gdev, u32 client_id, u32 function, u32 timeout_ms, struct vbg_dev *gdev, u32 requestor, u32 client_id, u32 function,
struct vmmdev_hgcm_function_parameter32 *parm32, u32 parm_count, u32 timeout_ms, struct vmmdev_hgcm_function_parameter32 *parm32,
int *vbox_status); u32 parm_count, int *vbox_status);
#endif #endif
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* Copyright (C) 2006-2016 Oracle Corporation * Copyright (C) 2006-2016 Oracle Corporation
*/ */
#include <linux/cred.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
...@@ -28,6 +29,23 @@ static DEFINE_MUTEX(vbg_gdev_mutex); ...@@ -28,6 +29,23 @@ static DEFINE_MUTEX(vbg_gdev_mutex);
/** Global vbg_gdev pointer used by vbg_get/put_gdev. */ /** Global vbg_gdev pointer used by vbg_get/put_gdev. */
static struct vbg_dev *vbg_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) static int vbg_misc_device_open(struct inode *inode, struct file *filp)
{ {
struct vbg_session *session; struct vbg_session *session;
...@@ -36,7 +54,7 @@ static int vbg_misc_device_open(struct inode *inode, struct file *filp) ...@@ -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 */ /* misc_open sets filp->private_data to our misc device */
gdev = container_of(filp->private_data, struct vbg_dev, 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)) if (IS_ERR(session))
return PTR_ERR(session); return PTR_ERR(session);
...@@ -53,7 +71,8 @@ static int vbg_misc_device_user_open(struct inode *inode, struct file *filp) ...@@ -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, gdev = container_of(filp->private_data, struct vbg_dev,
misc_device_user); 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)) if (IS_ERR(session))
return PTR_ERR(session); return PTR_ERR(session);
...@@ -115,7 +134,8 @@ static long vbg_misc_device_ioctl(struct file *filp, unsigned int req, ...@@ -115,7 +134,8 @@ static long vbg_misc_device_ioctl(struct file *filp, unsigned int req,
req == VBG_IOCTL_VMMDEV_REQUEST_BIG; req == VBG_IOCTL_VMMDEV_REQUEST_BIG;
if (is_vmmdev_req) 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 else
buf = kmalloc(size, GFP_KERNEL); buf = kmalloc(size, GFP_KERNEL);
if (!buf) if (!buf)
......
...@@ -62,7 +62,8 @@ VBG_LOG(vbg_err, pr_err); ...@@ -62,7 +62,8 @@ VBG_LOG(vbg_err, pr_err);
VBG_LOG(vbg_debug, pr_debug); VBG_LOG(vbg_debug, pr_debug);
#endif #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; struct vmmdev_request_header *req;
int order = get_order(PAGE_ALIGN(len)); int order = get_order(PAGE_ALIGN(len));
...@@ -78,7 +79,7 @@ void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type) ...@@ -78,7 +79,7 @@ void *vbg_req_alloc(size_t len, enum vmmdev_request_type req_type)
req->request_type = req_type; req->request_type = req_type;
req->rc = VERR_GENERAL_FAILURE; req->rc = VERR_GENERAL_FAILURE;
req->reserved1 = 0; req->reserved1 = 0;
req->reserved2 = 0; req->requestor = requestor;
return req; return req;
} }
...@@ -119,7 +120,7 @@ static bool hgcm_req_done(struct vbg_dev *gdev, ...@@ -119,7 +120,7 @@ static bool hgcm_req_done(struct vbg_dev *gdev,
return done; 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, struct vmmdev_hgcm_service_location *loc,
u32 *client_id, int *vbox_status) u32 *client_id, int *vbox_status)
{ {
...@@ -127,7 +128,7 @@ int vbg_hgcm_connect(struct vbg_dev *gdev, ...@@ -127,7 +128,7 @@ int vbg_hgcm_connect(struct vbg_dev *gdev,
int rc; int rc;
hgcm_connect = vbg_req_alloc(sizeof(*hgcm_connect), hgcm_connect = vbg_req_alloc(sizeof(*hgcm_connect),
VMMDEVREQ_HGCM_CONNECT); VMMDEVREQ_HGCM_CONNECT, requestor);
if (!hgcm_connect) if (!hgcm_connect)
return -ENOMEM; return -ENOMEM;
...@@ -153,13 +154,15 @@ int vbg_hgcm_connect(struct vbg_dev *gdev, ...@@ -153,13 +154,15 @@ int vbg_hgcm_connect(struct vbg_dev *gdev,
} }
EXPORT_SYMBOL(vbg_hgcm_connect); 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; struct vmmdev_hgcm_disconnect *hgcm_disconnect = NULL;
int rc; int rc;
hgcm_disconnect = vbg_req_alloc(sizeof(*hgcm_disconnect), hgcm_disconnect = vbg_req_alloc(sizeof(*hgcm_disconnect),
VMMDEVREQ_HGCM_DISCONNECT); VMMDEVREQ_HGCM_DISCONNECT,
requestor);
if (!hgcm_disconnect) if (!hgcm_disconnect)
return -ENOMEM; return -ENOMEM;
...@@ -593,9 +596,10 @@ static int hgcm_call_copy_back_result( ...@@ -593,9 +596,10 @@ static int hgcm_call_copy_back_result(
return 0; return 0;
} }
int vbg_hgcm_call(struct vbg_dev *gdev, u32 client_id, u32 function, int vbg_hgcm_call(struct vbg_dev *gdev, u32 requestor, u32 client_id,
u32 timeout_ms, struct vmmdev_hgcm_function_parameter *parms, u32 function, u32 timeout_ms,
u32 parm_count, int *vbox_status) struct vmmdev_hgcm_function_parameter *parms, u32 parm_count,
int *vbox_status)
{ {
struct vmmdev_hgcm_call *call; struct vmmdev_hgcm_call *call;
void **bounce_bufs = NULL; void **bounce_bufs = NULL;
...@@ -615,7 +619,7 @@ int vbg_hgcm_call(struct vbg_dev *gdev, u32 client_id, u32 function, ...@@ -615,7 +619,7 @@ int vbg_hgcm_call(struct vbg_dev *gdev, u32 client_id, u32 function,
goto free_bounce_bufs; goto free_bounce_bufs;
} }
call = vbg_req_alloc(size, VMMDEVREQ_HGCM_CALL); call = vbg_req_alloc(size, VMMDEVREQ_HGCM_CALL, requestor);
if (!call) { if (!call) {
ret = -ENOMEM; ret = -ENOMEM;
goto free_bounce_bufs; goto free_bounce_bufs;
...@@ -647,9 +651,9 @@ EXPORT_SYMBOL(vbg_hgcm_call); ...@@ -647,9 +651,9 @@ EXPORT_SYMBOL(vbg_hgcm_call);
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
int vbg_hgcm_call32( int vbg_hgcm_call32(
struct vbg_dev *gdev, u32 client_id, u32 function, u32 timeout_ms, struct vbg_dev *gdev, u32 requestor, u32 client_id, u32 function,
struct vmmdev_hgcm_function_parameter32 *parm32, u32 parm_count, u32 timeout_ms, struct vmmdev_hgcm_function_parameter32 *parm32,
int *vbox_status) u32 parm_count, int *vbox_status)
{ {
struct vmmdev_hgcm_function_parameter *parm64 = NULL; struct vmmdev_hgcm_function_parameter *parm64 = NULL;
u32 i, size; u32 i, size;
...@@ -689,7 +693,7 @@ int vbg_hgcm_call32( ...@@ -689,7 +693,7 @@ int vbg_hgcm_call32(
goto out_free; 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); parm64, parm_count, vbox_status);
if (ret < 0) if (ret < 0)
goto out_free; goto out_free;
......
...@@ -9,11 +9,10 @@ ...@@ -9,11 +9,10 @@
#ifndef __VBOX_VERSION_H__ #ifndef __VBOX_VERSION_H__
#define __VBOX_VERSION_H__ #define __VBOX_VERSION_H__
/* Last synced October 4th 2017 */ #define VBG_VERSION_MAJOR 6
#define VBG_VERSION_MAJOR 5 #define VBG_VERSION_MINOR 0
#define VBG_VERSION_MINOR 2
#define VBG_VERSION_BUILD 0 #define VBG_VERSION_BUILD 0
#define VBG_SVN_REV 68940 #define VBG_SVN_REV 127566
#define VBG_VERSION_STRING "5.2.0" #define VBG_VERSION_STRING "6.0.0"
#endif #endif
...@@ -98,8 +98,8 @@ struct vmmdev_request_header { ...@@ -98,8 +98,8 @@ struct vmmdev_request_header {
s32 rc; s32 rc;
/** Reserved field no.1. MBZ. */ /** Reserved field no.1. MBZ. */
u32 reserved1; u32 reserved1;
/** Reserved field no.2. MBZ. */ /** IN: Requestor information (VMMDEV_REQUESTOR_*) */
u32 reserved2; u32 requestor;
}; };
VMMDEV_ASSERT_SIZE(vmmdev_request_header, 24); VMMDEV_ASSERT_SIZE(vmmdev_request_header, 24);
...@@ -247,6 +247,8 @@ struct vmmdev_guest_info { ...@@ -247,6 +247,8 @@ struct vmmdev_guest_info {
}; };
VMMDEV_ASSERT_SIZE(vmmdev_guest_info, 24 + 8); 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_guestinfo2 - Guest information report, version 2. */
struct vmmdev_guest_info2 { struct vmmdev_guest_info2 {
/** Header. */ /** Header. */
...@@ -259,7 +261,7 @@ struct vmmdev_guest_info2 { ...@@ -259,7 +261,7 @@ struct vmmdev_guest_info2 {
u32 additions_build; u32 additions_build;
/** SVN revision. */ /** SVN revision. */
u32 additions_revision; u32 additions_revision;
/** Feature mask, currently unused. */ /** Feature mask. */
u32 additions_features; u32 additions_features;
/** /**
* The intentional meaning of this field was: * The intentional meaning of this field was:
......
...@@ -24,15 +24,17 @@ __printf(1, 2) void vbg_debug(const char *fmt, ...); ...@@ -24,15 +24,17 @@ __printf(1, 2) void vbg_debug(const char *fmt, ...);
#define vbg_debug pr_debug #define vbg_debug pr_debug
#endif #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, struct vmmdev_hgcm_service_location *loc,
u32 *client_id, int *vbox_status); 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, int vbg_hgcm_call(struct vbg_dev *gdev, u32 requestor, u32 client_id,
u32 timeout_ms, struct vmmdev_hgcm_function_parameter *parms, u32 function, u32 timeout_ms,
u32 parm_count, int *vbox_status); struct vmmdev_hgcm_function_parameter *parms, u32 parm_count,
int *vbox_status);
/** /**
* Convert a VirtualBox status code to a standard Linux kernel return value. * Convert a VirtualBox status code to a standard Linux kernel return value.
......
...@@ -102,6 +102,66 @@ enum vmmdev_request_type { ...@@ -102,6 +102,66 @@ enum vmmdev_request_type {
#define VMMDEVREQ_HGCM_CALL VMMDEVREQ_HGCM_CALL32 #define VMMDEVREQ_HGCM_CALL VMMDEVREQ_HGCM_CALL32
#endif #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. Note this is 0, check for !USERMODE instead. */
#define VMMDEV_REQUESTOR_KERNEL 0x00000000
/* User mode request. */
#define VMMDEV_REQUESTOR_USERMODE 0x00000008
/* User or kernel mode classification mask. */
#define VMMDEV_REQUESTOR_MODE_MASK 0x00000008
/* Don't know the physical console association of the requestor. */
#define VMMDEV_REQUESTOR_CON_DONT_KNOW 0x00000000
/*
* The request originates with a process that is NOT associated with the
* physical console.
*/
#define VMMDEV_REQUESTOR_CON_NO 0x00000010
/* Requestor process is associated with the physical console. */
#define VMMDEV_REQUESTOR_CON_YES 0x00000020
/* Console classification mask. */
#define VMMDEV_REQUESTOR_CON_MASK 0x00000030
/* Requestor is member of special VirtualBox user group. */
#define VMMDEV_REQUESTOR_GRP_VBOX 0x00000080
/* Note: trust level is for windows guests only, linux always uses not-given */
/* Requestor trust level: Unspecified */
#define VMMDEV_REQUESTOR_TRUST_NOT_GIVEN 0x00000000
/* Requestor trust level: Untrusted (SID S-1-16-0) */
#define VMMDEV_REQUESTOR_TRUST_UNTRUSTED 0x00001000
/* Requestor trust level: Untrusted (SID S-1-16-4096) */
#define VMMDEV_REQUESTOR_TRUST_LOW 0x00002000
/* Requestor trust level: Medium (SID S-1-16-8192) */
#define VMMDEV_REQUESTOR_TRUST_MEDIUM 0x00003000
/* Requestor trust level: Medium plus (SID S-1-16-8448) */
#define VMMDEV_REQUESTOR_TRUST_MEDIUM_PLUS 0x00004000
/* Requestor trust level: High (SID S-1-16-12288) */
#define VMMDEV_REQUESTOR_TRUST_HIGH 0x00005000
/* Requestor trust level: System (SID S-1-16-16384) */
#define VMMDEV_REQUESTOR_TRUST_SYSTEM 0x00006000
/* Requestor trust level >= Protected (SID S-1-16-20480, S-1-16-28672) */
#define VMMDEV_REQUESTOR_TRUST_PROTECTED 0x00007000
/* 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. */ /** HGCM service location types. */
enum vmmdev_hgcm_service_location_type { enum vmmdev_hgcm_service_location_type {
VMMDEV_HGCM_LOC_INVALID = 0, VMMDEV_HGCM_LOC_INVALID = 0,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment