VirtualBox

source: vbox/trunk/src/VBox/Installer/linux/vboxdrv.sh@ 69221

Last change on this file since 69221 was 68027, checked in by vboxsync, 7 years ago

bugref:3809: Linux installer maintenance
Clean up unneeded kernel modules when the vboxdrv service is started.

When a Linux kernel is removed on the host for which VirtualBox driver
modules were installed, the kernel directory and those modules were left
in place. This change adds a check to the vboxdrv service script to look
for such orphaned modules on start-up and remove them along with the
directories.

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 17.2 KB
Line 
1#! /bin/sh
2# Oracle VM VirtualBox
3# Linux kernel module init script
4
5#
6# Copyright (C) 2006-2015 Oracle Corporation
7#
8# This file is part of VirtualBox Open Source Edition (OSE), as
9# available from http://www.virtualbox.org. This file is free software;
10# you can redistribute it and/or modify it under the terms of the GNU
11# General Public License (GPL) as published by the Free Software
12# Foundation, in version 2 as it comes in the "COPYING" file of the
13# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15#
16
17# chkconfig: 345 20 80
18# description: VirtualBox Linux kernel module
19#
20### BEGIN INIT INFO
21# Provides: vboxdrv
22# Required-Start: $syslog
23# Required-Stop:
24# Default-Start: 2 3 4 5
25# Default-Stop: 0 1 6
26# Short-Description: VirtualBox Linux kernel module
27### END INIT INFO
28
29## @todo This file duplicates a lot of script with vboxadd.sh. When making
30# changes please try to reduce differences between the two wherever possible.
31
32## @todo Remove the stop_vms target so that this script is only relevant to
33# kernel modules. Nice but not urgent.
34
35PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
36DEVICE=/dev/vboxdrv
37LOG="/var/log/vbox-install.log"
38MODPROBE=/sbin/modprobe
39SCRIPTNAME=vboxdrv.sh
40
41# The below is GNU-specific. See VBox.sh for the longer Solaris/OS X version.
42TARGET=`readlink -e -- "${0}"` || exit 1
43SCRIPT_DIR="${TARGET%/[!/]*}"
44
45if $MODPROBE -c | grep -q '^allow_unsupported_modules *0'; then
46 MODPROBE="$MODPROBE --allow-unsupported-modules"
47fi
48
49[ -f /etc/vbox/vbox.cfg ] && . /etc/vbox/vbox.cfg
50export BUILD_TYPE
51export USERNAME
52export USER=$USERNAME
53
54if test -n "${INSTALL_DIR}" && test -x "${INSTALL_DIR}/VirtualBox"; then
55 MODULE_SRC="${INSTALL_DIR}/src/vboxhost"
56elif test -x /usr/lib/virtualbox/VirtualBox; then
57 INSTALL_DIR=/usr/lib/virtualbox
58 MODULE_SRC="/usr/share/virtualbox/src/vboxhost"
59elif test -x "${SCRIPT_DIR}/VirtualBox"; then
60 # Executing from the build directory
61 INSTALL_DIR="${SCRIPT_DIR}"
62 MODULE_SRC="${INSTALL_DIR}/src"
63else
64 # Silently exit if the package was uninstalled but not purged.
65 # Applies to Debian packages only (but shouldn't hurt elsewhere)
66 exit 0
67fi
68VIRTUALBOX="${INSTALL_DIR}/VirtualBox"
69VBOXMANAGE="${INSTALL_DIR}/VBoxManage"
70BUILDINTMP="${MODULE_SRC}/build_in_tmp"
71if test -u "${VIRTUALBOX}"; then
72 GROUP=root
73 DEVICE_MODE=0600
74else
75 GROUP=vboxusers
76 DEVICE_MODE=0660
77fi
78
79[ -r /etc/default/virtualbox ] && . /etc/default/virtualbox
80
81# Preamble for Gentoo
82if [ "`which $0`" = "/sbin/rc" ]; then
83 shift
84fi
85
86begin_msg()
87{
88 test -n "${2}" && echo "${SCRIPTNAME}: ${1}."
89 logger -t "${SCRIPTNAME}" "${1}."
90}
91
92succ_msg()
93{
94 logger -t "${SCRIPTNAME}" "${1}."
95}
96
97fail_msg()
98{
99 echo "${SCRIPTNAME}: failed: ${1}." >&2
100 logger -t "${SCRIPTNAME}" "failed: ${1}."
101}
102
103failure()
104{
105 fail_msg "$1"
106 exit 1
107}
108
109running()
110{
111 lsmod | grep -q "$1[^_-]"
112}
113
114## Output the vboxdrv part of our udev rule. This is redirected to the right file.
115udev_write_vboxdrv() {
116 VBOXDRV_GRP="$1"
117 VBOXDRV_MODE="$2"
118
119 echo "KERNEL==\"vboxdrv\", NAME=\"vboxdrv\", OWNER=\"root\", GROUP=\"$VBOXDRV_GRP\", MODE=\"$VBOXDRV_MODE\""
120 echo "KERNEL==\"vboxdrvu\", NAME=\"vboxdrvu\", OWNER=\"root\", GROUP=\"root\", MODE=\"0666\""
121 echo "KERNEL==\"vboxnetctl\", NAME=\"vboxnetctl\", OWNER=\"root\", GROUP=\"$VBOXDRV_GRP\", MODE=\"$VBOXDRV_MODE\""
122}
123
124## Output the USB part of our udev rule. This is redirected to the right file.
125udev_write_usb() {
126 INSTALLATION_DIR="$1"
127 USB_GROUP="$2"
128
129 echo "SUBSYSTEM==\"usb_device\", ACTION==\"add\", RUN+=\"$INSTALLATION_DIR/VBoxCreateUSBNode.sh \$major \$minor \$attr{bDeviceClass}${USB_GROUP}\""
130 echo "SUBSYSTEM==\"usb\", ACTION==\"add\", ENV{DEVTYPE}==\"usb_device\", RUN+=\"$INSTALLATION_DIR/VBoxCreateUSBNode.sh \$major \$minor \$attr{bDeviceClass}${USB_GROUP}\""
131 echo "SUBSYSTEM==\"usb_device\", ACTION==\"remove\", RUN+=\"$INSTALLATION_DIR/VBoxCreateUSBNode.sh --remove \$major \$minor\""
132 echo "SUBSYSTEM==\"usb\", ACTION==\"remove\", ENV{DEVTYPE}==\"usb_device\", RUN+=\"$INSTALLATION_DIR/VBoxCreateUSBNode.sh --remove \$major \$minor\""
133}
134
135## Generate our udev rule file. This takes a change in udev rule syntax in
136## version 55 into account. It only creates rules for USB for udev versions
137## recent enough to support USB device nodes.
138generate_udev_rule() {
139 VBOXDRV_GRP="$1" # The group owning the vboxdrv device
140 VBOXDRV_MODE="$2" # The access mode for the vboxdrv device
141 INSTALLATION_DIR="$3" # The directory VirtualBox is installed in
142 USB_GROUP="$4" # The group that has permission to access USB devices
143 NO_INSTALL="$5" # Set this to "1" to remove but not re-install rules
144
145 # Extra space!
146 case "$USB_GROUP" in ?*) USB_GROUP=" $USB_GROUP" ;; esac
147 case "$NO_INSTALL" in "1") return ;; esac
148 udev_write_vboxdrv "$VBOXDRV_GRP" "$VBOXDRV_MODE"
149 udev_write_usb "$INSTALLATION_DIR" "$USB_GROUP"
150}
151
152## Install udev rule (disable with INSTALL_NO_UDEV=1 in
153## /etc/default/virtualbox).
154install_udev() {
155 VBOXDRV_GRP="$1" # The group owning the vboxdrv device
156 VBOXDRV_MODE="$2" # The access mode for the vboxdrv device
157 INSTALLATION_DIR="$3" # The directory VirtualBox is installed in
158 USB_GROUP="$4" # The group that has permission to access USB devices
159 NO_INSTALL="$5" # Set this to "1" to remove but not re-install rules
160
161 if test -d /etc/udev/rules.d; then
162 generate_udev_rule "$VBOXDRV_GRP" "$VBOXDRV_MODE" "$INSTALLATION_DIR" \
163 "$USB_GROUP" "$NO_INSTALL"
164 fi
165 # Remove old udev description file
166 rm -f /etc/udev/rules.d/10-vboxdrv.rules 2> /dev/null
167}
168
169## Create a usb device node for a given sysfs path to a USB device.
170install_create_usb_node_for_sysfs() {
171 path="$1" # sysfs path for the device
172 usb_createnode="$2" # Path to the USB device node creation script
173 usb_group="$3" # The group to give ownership of the node to
174 if test -r "${path}/dev"; then
175 dev="`cat "${path}/dev" 2> /dev/null`"
176 major="`expr "$dev" : '\(.*\):' 2> /dev/null`"
177 minor="`expr "$dev" : '.*:\(.*\)' 2> /dev/null`"
178 class="`cat ${path}/bDeviceClass 2> /dev/null`"
179 sh "${usb_createnode}" "$major" "$minor" "$class" \
180 "${usb_group}" 2>/dev/null
181 fi
182}
183
184udev_rule_file=/etc/udev/rules.d/60-vboxdrv.rules
185sysfs_usb_devices="/sys/bus/usb/devices/*"
186
187## Install udev rules and create device nodes for usb access
188setup_usb() {
189 VBOXDRV_GRP="$1" # The group that should own /dev/vboxdrv
190 VBOXDRV_MODE="$2" # The mode to be used for /dev/vboxdrv
191 INSTALLATION_DIR="$3" # The directory VirtualBox is installed in
192 USB_GROUP="$4" # The group that should own the /dev/vboxusb device
193 # nodes unless INSTALL_NO_GROUP=1 in
194 # /etc/default/virtualbox. Optional.
195 usb_createnode="$INSTALLATION_DIR/VBoxCreateUSBNode.sh"
196 # install udev rule (disable with INSTALL_NO_UDEV=1 in
197 # /etc/default/virtualbox)
198 if [ "$INSTALL_NO_GROUP" != "1" ]; then
199 usb_group=$USB_GROUP
200 vboxdrv_group=$VBOXDRV_GRP
201 else
202 usb_group=root
203 vboxdrv_group=root
204 fi
205 install_udev "${vboxdrv_group}" "$VBOXDRV_MODE" \
206 "$INSTALLATION_DIR" "${usb_group}" \
207 "$INSTALL_NO_UDEV" > ${udev_rule_file}
208 # Build our device tree
209 for i in ${sysfs_usb_devices}; do # This line intentionally without quotes.
210 install_create_usb_node_for_sysfs "$i" "${usb_createnode}" \
211 "${usb_group}"
212 done
213}
214
215cleanup_usb()
216{
217 # Remove udev description file
218 rm -f /etc/udev/rules.d/60-vboxdrv.rules
219 rm -f /etc/udev/rules.d/10-vboxdrv.rules
220
221 # Remove our USB device tree
222 rm -rf /dev/vboxusb
223}
224
225start()
226{
227 begin_msg "Starting VirtualBox services" console
228 if [ -d /proc/xen ]; then
229 failure "Running VirtualBox in a Xen environment is not supported"
230 fi
231 if ! running vboxdrv; then
232 if ! rm -f $DEVICE; then
233 failure "Cannot remove $DEVICE"
234 fi
235 if ! $MODPROBE vboxdrv > /dev/null 2>&1; then
236 setup
237 if ! $MODPROBE vboxdrv > /dev/null 2>&1; then
238 failure "modprobe vboxdrv failed. Please use 'dmesg' to find out why"
239 fi
240 fi
241 sleep .2
242 fi
243 # ensure the character special exists
244 if [ ! -c $DEVICE ]; then
245 MAJOR=`sed -n 's;\([0-9]\+\) vboxdrv$;\1;p' /proc/devices`
246 if [ ! -z "$MAJOR" ]; then
247 MINOR=0
248 else
249 MINOR=`sed -n 's;\([0-9]\+\) vboxdrv$;\1;p' /proc/misc`
250 if [ ! -z "$MINOR" ]; then
251 MAJOR=10
252 fi
253 fi
254 if [ -z "$MAJOR" ]; then
255 rmmod vboxdrv 2>/dev/null
256 failure "Cannot locate the VirtualBox device"
257 fi
258 if ! mknod -m 0660 $DEVICE c $MAJOR $MINOR 2>/dev/null; then
259 rmmod vboxdrv 2>/dev/null
260 failure "Cannot create device $DEVICE with major $MAJOR and minor $MINOR"
261 fi
262 fi
263 # ensure permissions
264 if ! chown :"${GROUP}" $DEVICE 2>/dev/null; then
265 rmmod vboxpci 2>/dev/null
266 rmmod vboxnetadp 2>/dev/null
267 rmmod vboxnetflt 2>/dev/null
268 rmmod vboxdrv 2>/dev/null
269 failure "Cannot change group ${GROUP} for device $DEVICE"
270 fi
271 if ! $MODPROBE vboxnetflt > /dev/null 2>&1; then
272 failure "modprobe vboxnetflt failed. Please use 'dmesg' to find out why"
273 fi
274 if ! $MODPROBE vboxnetadp > /dev/null 2>&1; then
275 failure "modprobe vboxnetadp failed. Please use 'dmesg' to find out why"
276 fi
277 if ! $MODPROBE vboxpci > /dev/null 2>&1; then
278 failure "modprobe vboxpci failed. Please use 'dmesg' to find out why"
279 fi
280 # Create the /dev/vboxusb directory if the host supports that method
281 # of USB access. The USB code checks for the existance of that path.
282 if grep -q usb_device /proc/devices; then
283 mkdir -p -m 0750 /dev/vboxusb 2>/dev/null
284 chown root:vboxusers /dev/vboxusb 2>/dev/null
285 fi
286 # Remove any kernel modules left over from previously installed kernels.
287 cleanup only_old
288 succ_msg "VirtualBox services started"
289}
290
291stop()
292{
293 begin_msg "Stopping VirtualBox services" console
294
295 if running vboxpci; then
296 if ! rmmod vboxpci 2>/dev/null; then
297 failure "Cannot unload module vboxpci"
298 fi
299 fi
300 if running vboxnetadp; then
301 if ! rmmod vboxnetadp 2>/dev/null; then
302 failure "Cannot unload module vboxnetadp"
303 fi
304 fi
305 if running vboxdrv; then
306 if running vboxnetflt; then
307 if ! rmmod vboxnetflt 2>/dev/null; then
308 failure "Cannot unload module vboxnetflt"
309 fi
310 fi
311 if ! rmmod vboxdrv 2>/dev/null; then
312 failure "Cannot unload module vboxdrv"
313 fi
314 if ! rm -f $DEVICE; then
315 failure "Cannot unlink $DEVICE"
316 fi
317 fi
318 succ_msg "VirtualBox services stopped"
319}
320
321# enter the following variables in /etc/default/virtualbox:
322# SHUTDOWN_USERS="foo bar"
323# check for running VMs of user foo and user bar
324# SHUTDOWN=poweroff
325# SHUTDOWN=acpibutton
326# SHUTDOWN=savestate
327# select one of these shutdown methods for running VMs
328stop_vms()
329{
330 wait=0
331 for i in $SHUTDOWN_USERS; do
332 # don't create the ipcd directory with wrong permissions!
333 if [ -d /tmp/.vbox-$i-ipc ]; then
334 export VBOX_IPC_SOCKETID="$i"
335 VMS=`$VBOXMANAGE --nologo list runningvms | sed -e 's/^".*".*{\(.*\)}/\1/' 2>/dev/null`
336 if [ -n "$VMS" ]; then
337 if [ "$SHUTDOWN" = "poweroff" ]; then
338 begin_msg "Powering off remaining VMs"
339 for v in $VMS; do
340 $VBOXMANAGE --nologo controlvm $v poweroff
341 done
342 succ_msg "Remaining VMs powered off"
343 elif [ "$SHUTDOWN" = "acpibutton" ]; then
344 begin_msg "Sending ACPI power button event to remaining VMs"
345 for v in $VMS; do
346 $VBOXMANAGE --nologo controlvm $v acpipowerbutton
347 wait=30
348 done
349 succ_msg "ACPI power button event sent to remaining VMs"
350 elif [ "$SHUTDOWN" = "savestate" ]; then
351 begin_msg "Saving state of remaining VMs"
352 for v in $VMS; do
353 $VBOXMANAGE --nologo controlvm $v savestate
354 done
355 succ_msg "State of remaining VMs saved"
356 fi
357 fi
358 fi
359 done
360 # wait for some seconds when doing ACPI shutdown
361 if [ "$wait" -ne 0 ]; then
362 begin_msg "Waiting for $wait seconds for VM shutdown"
363 sleep $wait
364 succ_msg "Waited for $wait seconds for VM shutdown"
365 fi
366}
367
368cleanup()
369{
370 # If this is set, only remove kernel modules for no longer installed
371 # kernels. Note that only generated kernel modules should be placed
372 # in /lib/modules/*/misc. Anything that we should not remove automatically
373 # should go elsewhere.
374 only_old="${1}"
375 for i in /lib/modules/*; do
376 # Check whether we are only cleaning up for uninstalled kernels.
377 test -n "${only_old}" && test -e "${i}/kernel/drivers" && continue
378 # We could just do "rm -f", but we only want to try deleting folders if
379 # we are sure they were ours, i.e. they had our modules in beforehand.
380 if test -e "${i}/misc/vboxdrv.ko" \
381 || test -e "${i}/misc/vboxnetadp.ko" \
382 || test -e "${i}/misc/vboxnetflt.ko" \
383 || test -e "${i}/misc/vboxpci.ko"; then
384 rm -f "${i}/misc/vboxdrv.ko" "${i}/misc/vboxnetadp.ko" \
385 "${i}/misc/vboxnetflt.ko" "${i}/misc/vboxpci.ko"
386 # Remove the kernel version folder if it was empty except for us.
387 test "`echo ${i}/misc/* ${i}/misc/.?* ${i}/* ${i}/.?*`" \
388 = "${i}/misc/* ${i}/misc/.. ${i}/misc ${i}/.." &&
389 rmdir "${i}/misc" "${i}" # We used to leave empty folders.
390 version=`expr "${i}" : "/lib/modules/\(.*\)"`
391 depmod -a "${version}"
392 fi
393 done
394}
395
396# setup_script
397setup()
398{
399 begin_msg "Building VirtualBox kernel modules" console
400 if ! $BUILDINTMP \
401 --save-module-symvers /tmp/vboxdrv-Module.symvers \
402 --module-source "$MODULE_SRC/vboxdrv" \
403 --no-print-directory install >> $LOG 2>&1; then
404 "${INSTALL_DIR}/check_module_dependencies.sh" || exit 1
405 failure "Look at $LOG to find out what went wrong"
406 fi
407 if ! $BUILDINTMP \
408 --use-module-symvers /tmp/vboxdrv-Module.symvers \
409 --module-source "$MODULE_SRC/vboxnetflt" \
410 --no-print-directory install >> $LOG 2>&1; then
411 failure "Look at $LOG to find out what went wrong"
412 fi
413 if ! $BUILDINTMP \
414 --use-module-symvers /tmp/vboxdrv-Module.symvers \
415 --module-source "$MODULE_SRC/vboxnetadp" \
416 --no-print-directory install >> $LOG 2>&1; then
417 failure "Look at $LOG to find out what went wrong"
418 fi
419 if ! $BUILDINTMP \
420 --use-module-symvers /tmp/vboxdrv-Module.symvers \
421 --module-source "$MODULE_SRC/vboxpci" \
422 --no-print-directory install >> $LOG 2>&1; then
423 failure "Look at $LOG to find out what went wrong"
424 fi
425 rm -f /etc/vbox/module_not_compiled
426 depmod -a
427 succ_msg "VirtualBox kernel modules built"
428}
429
430dmnstatus()
431{
432 if running vboxdrv; then
433 str="vboxdrv"
434 if running vboxnetflt; then
435 str="$str, vboxnetflt"
436 if running vboxnetadp; then
437 str="$str, vboxnetadp"
438 fi
439 fi
440 if running vboxpci; then
441 str="$str, vboxpci"
442 fi
443 echo "VirtualBox kernel modules ($str) are loaded."
444 for i in $SHUTDOWN_USERS; do
445 # don't create the ipcd directory with wrong permissions!
446 if [ -d /tmp/.vbox-$i-ipc ]; then
447 export VBOX_IPC_SOCKETID="$i"
448 VMS=`$VBOXMANAGE --nologo list runningvms | sed -e 's/^".*".*{\(.*\)}/\1/' 2>/dev/null`
449 if [ -n "$VMS" ]; then
450 echo "The following VMs are currently running:"
451 for v in $VMS; do
452 echo " $v"
453 done
454 fi
455 fi
456 done
457 else
458 echo "VirtualBox kernel module is not loaded."
459 fi
460}
461
462case "$1" in
463start)
464 start
465 ;;
466stop)
467 stop_vms
468 stop
469 ;;
470stop_vms)
471 stop_vms
472 ;;
473restart)
474 stop && start
475 ;;
476setup)
477 # Create udev rule and USB device nodes.
478 ## todo Wouldn't it make more sense to install the rule to /lib/udev? This
479 ## is not a user-created configuration file after all.
480 ## todo Do we need a udev rule to create /dev/vboxdrv[u] at all? We have
481 ## working fall-back code here anyway, and the "right" code is more complex
482 ## than the fall-back. Unnecessary duplication?
483 stop && cleanup
484 setup_usb "$GROUP" "$DEVICE_MODE" "$INSTALL_DIR"
485 setup && start
486 ;;
487cleanup)
488 stop && cleanup
489 cleanup_usb
490 ;;
491force-reload)
492 stop
493 start
494 ;;
495status)
496 dmnstatus
497 ;;
498*)
499 echo "Usage: $0 {start|stop|stop_vms|restart|force-reload|status}"
500 exit 1
501esac
502
503exit 0
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette