Category Archives: English

VirtualBox and Mono – ‘Managed’ Virtual Machines on Linux

My previous post already explained how to embed and control a VirtualBox Virtual Machine in a C#/.Net application on Windows. That was too easy, and it’s really less fun if it does not work cross platform, so the next challenge was to make it work on Linux, with Mono as the .Net runtime. A few people have been working on this before, but that was a long time ago and I bet they never got this far. Nevertheless, they were the ones to implement XPCOM interop in mono, making my experiment a lot easier.

On Linux, VirtualBox uses XPCOM as it’s component model, to replace (MS)COM. The two appear to be essentially the same; they both use vtables, interfaces and IUnknown. The two are *almost* (binary) compatible. An important difference is in the object creation or ‘activation’. (MS)COM relies on a system wide database (somewhere deep in the Windows registry) to track all known Objects, and from there provides a platform API function to create an object instance. XPCOM, the Cross Platform Component Object Model, does not provide such a feature. Combined with some missing features and a lack of proper documentation, this resulted in slightly different implementations being in use today. Other, perhaps even more important differences are in how some data types are represented (especially arrays and strings), and the lack of IDispatch support in (VirtualBox) XPCOM. The last one is a real problem, as it changes the layout of *every* interface definition, making the Interop assembly generated by Visual Studio .Net useless on Linux, and making it very difficult if not impossible to support both COM and XPCOM with one codebase.

The object activation in VirtualBox is quite simple. The VBoxXPCOMC.so library provides a function named VBoxGetXPCOMCFunctions, which simply returns a structure with a bunch of function pointers (which looks much like a COM vtable). By calling the appropriate functions, one can easily activate the needed XPCOM objects.

To work around the missing IDispatch support in the XPCOM interfaces, the Interop assembly needs to be changed. I ended up writing some C# code which can automatically generate appropriate interface definitions based on the VirtualBox.xidl file (available in the SDK package and in the SVN repository, note that it is important to use the xidl file that corresponds to the VirtualBox version you want to use, as the interface definitions do change over time!). This also provides an opportunity to work around the differences in how strings are represented. Arrays are still troublesome, as VirtualBox internally represents one Array parameter as two parameters (size and a pointer to the first element). Such an array can be ‘marshaled’ as an UnmanagedType.LPArray, but having two parameters instead of one makes the definition incompatible with the one generated by VS.Net (and used on Windows/MSCOM).

So what’s the deal if it is not compatible? Well, if the interface definitions define the same managed interface members, one interop assembly can serve as a drop in replacement for the other. Note that only the functions we use need to match, and the order in which they are defined or their attributes are not relevant. One can write code in VS.Net while using the COM interop assembly, and run the same code on Linux with the XPCOM interop assembly. It’s even better: the framework only loads an assembly when it *needs* a type defined in it, and only if the type is not already available. So if we detect a Linux system, we can simply load the XPCOM interop assembly, before the framework loads the COM interop assembly, and the frontend code won’t know the difference! This is also the reason for using multiple stages in the program initialization (ProgramLoader.Main, ProgramLoader.Main2, ProgramRun.Run, and the Object type of ProgramRun.WaitingForProgress) – to prevent the runtime from loading the assembly before we have had a chance to load the alternative one.

So, arrays are still unsupported in the XPCOM interop code. We don’t really need them much, yet. Currently, only the VBoxEventListener uses an array parameter, and uses an ugly hack for this purpose: it defines an alternative version of the interface it wants to use, where the function it wants to call has two parameters for the array (size and pointer). It then decides which version of the interface to use based on the OS platform. Perhaps a way to properly marshal the arrays already exists, or could be created using custom marshaling. Alternatively, wrapper classes could be created for all COM interfaces, to convert the function parameters appropriately, essentially re-implementing the COM interop/proxying. The use of custom wrapper classes is probably the most flexible one as it gives full control over the marshaling.

Another near-showstopper is what I think is a bug in the Mono runtime: Mono releases COM interface pointers, which it receives as a result of a COM function call, twice. Once in the Interop calling code, and once while marshaling the interface pointer to a .Net interface. This results in crashes while accessing methods and properties which return an interface type. The fix for this is very simple, and will hopefully find it’s way to the Mono distribution soon. Alternatively, the custom COM wrapper classes can be used to work around this issue and avoid the Mono (XP)COM interop code altogether.

On Linux, most users do normally not have ‘root’ privileges, but root privileges are needed to access the VirtualBox kernel driver. VirtualBox handles this by making it’s executables ‘setuid root‘, meaning that any user can run the executables with root privileges. By itself, this would be a gaping security hole, so normally VirtualBox is compiled with ‘hardening’: a wrapper application is started as root, opens the kernel driver, drops all privileges (by calling setuid and setgid) and then loads a dynamic library containing the actual application.

This approach works very well as long as all executables and libraries involved are known, but we can’t easily add a new frontend application without recompiling all of the VirtualBox code. One hackish way is to replace one of the existing shared libraries, for example VBoxBFE, with our own version which will fire up mono. This approach works, but still requires modifications to the VirtualBox installation. Note that the mono engine has to be loaded as a library, as the kernel driver will be closed on exec(ution) of another executable.

Another approach is to start mono as root, with the VBOX_USER_HOME variable set correctly. Then, after starting the VM, the application can drop it’s privileges. This works, but will result in files owned by root appearing in your VirtualBox data directory, possibly resulting in trouble when you want to use the standard frontends later on. Also, VirtualBox may not be able to clean up some unix sockets and pipes which it has created as root. And last, the GTK GUI library, which is used by the Windows.Forms implementation, does not like to be started as root, so the GUI can only be created after the VM has been started. To make it all a bit more friendly, it’s possible to create a ‘setuid root’ wrapper application, which simply executes mono (or loads mono as a library).

Luckily, VBoxXPCOMC.so also exports the hidden RTR3InitAndSUPLib function. This function can open the kernel driver, without starting a VM. This function can be called from the C# code, before dropping privileges, and the application can then safely create the GUI and start the VM. One problem here is that mono and the .Net code still needs to be started as root, which might be dangerous if we don’t properly lock down what code mono will run. An easy way to get around this, is to create a wrapper application in C, which initializes the kernel driver, drops privileges and then runs the .Net code. According to the VirtualBox team, it should be very difficult to abuse the kernel driver access for anything other than hanging the host system, so this should be pretty safe, although you should still be careful.

And again, the sourcecode for the complete project, including Linux support, is available in my Mercurial repository at http://oss.ucis.nl/hg/vboxdotnet/.

Posted in Computers, English | Tagged , , , , , , , , , | 1 Comment

VirtualBox and .Net – Virtual Machines in a Managed environment

About a week ago an old, crazy idea (re)occured to me: why not try to interface with VirtualBox from .Net? In case you did not know – VirtualBox is a Virtual Machine software, which allows you to run a virtual computer with it’s own operating system and software on another computer. The Microsoft .Net framework is an application (development) framework, runtime library, and comes with multiple high level programming languages. Microsoft calls programs that run in the .Net environment ‘Managed’. Ofcourse, .Net would not have been as good as it is if there were no Linux support for it, provided by the Mono software. And ofcourse, I could not resist making my VirtualBox frontend written in C# work on Linux.

On a Windows system, it’s all pretty straightforward. Create a new .Net project (I use C#), add a reference to the ‘VirtualBox type library’ COM library, and experiment. Create an instance of the VirtualBox.VirtualBoxClass, an instance of the VirtualBox.SessionClass, find an IMachine (using IVirtualBox.FindMachine), lock the machine to the session and power it up. You can find this code somewhere in the ProgramRun class. Yep, it is that simple. Now we have a running machine – but no graphics, no mouse, not even a keyboard. We’ve just created a simplified version of VBoxHeadless. No fun. Let’s start with some graphics.

By the way, notice that the IMachine interface also has a function call named LaunchVMProcess, which you can use to easily launch the standard “headless” or “gui” frontends, but this is ofcourse less fun. Also note that for the resulting executable to work, it may be necessary to copy it to the VirtualBox installation directory, or to copy a bunch of files from the VirtualBox installation directory to the application directory.

My approach, as I have done this before for the VirtualBox VNC support, was to create the Framebuffer class, which implements IFramebuffer. Basically, the framebuffer provides a buffer, a block of memory, where VirtualBox can write the image to. Now, to display the framebuffer, a Bitmap object is constructed, using the same block of memory. Then simply put this Bitmap instance in a PictureBox, or anything that can display an Image. All that’s left is to attach an instance of the framebuffer object to the Session.Console.Display. Note that the framebuffer may have to be resized when the Virtual Machine changes video modes, allocating a new block of memory and releasing the old one. Be careful that the old block of memory is really not used anymore, before releasing it. Also note that the form can set a VideoModeHint on the IDisplay interface, to inform the guest (additions) about the desired video mode. The guest may or may not listen to this request.

Adding some mouse support is quite simple, some mapping is needed for the buttons, and depending on the guest mouse driver, a relative position may have to be calculated. Also note that, when sending ‘absolute’ mouse positions, the top left pixel has the coordinate (1,1). This is handled in the Form’s Mouse* event handlers in the Display class.

The virtual keyboard is a bit more troublesome. VirtualBox expects ‘good old’ keyboard scancodes, as sent to the computer by old AT/PS2 keyboards. Each *key* has it’s own code (so the only difference between a 1 and a ! is whether the shift key is down). The scan codes appear to be ordered the same way as the keys on the keyboard (eg ‘Q’ comes before ‘W’). Some lookup tables are used to map the .Net key codes to these scancodes. Luckily, the framework does not differentiate between ‘1’ and ‘!’ either at this point, and sends the shift key like any other key, so we can get away with a simple one-to-one mapping, which is implemented in the VBoxKeyboardHelper class.

I have also added a VirtualBox EventListener to the user interface (Display class). The event listener itself is implemented in the VBoxEventListener class and simply forwards the events to a .Net EventHandler. It’s used for informative purposes, as well as to control the machine state flow.

My next blog post will talk about adding Linux/mono/XPCOM support to the application, which is perhaps (even) more interesting, and was definitely more challenging.

The sourcecode for the complete project, including Linux support, is available in my Mercurial repository at http://oss.ucis.nl/hg/vboxdotnet/.

Posted in Computers, English | Tagged , , , , , , , , , , , | 1 Comment