VirtualBox

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

Last change on this file since 99536 was 99536, checked in by vboxsync, 13 months ago

Linux: rcvboxdrv, rcvboxadd: Improved condition check when kernel modules need to be signed, bugref:10287.

Also fixed issue with parsing kernel config when scripts/config tool is not available.

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 30.6 KB
Line 
1#! /bin/sh
2# Oracle VM VirtualBox
3# Linux kernel module init script
4
5#
6# Copyright (C) 2006-2023 Oracle and/or its affiliates.
7#
8# This file is part of VirtualBox base platform packages, as
9# available from https://www.virtualbox.org.
10#
11# This program is free software; you can redistribute it and/or
12# modify it under the terms of the GNU General Public License
13# as published by the Free Software Foundation, in version 3 of the
14# License.
15#
16# This program is distributed in the hope that it will be useful, but
17# WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19# General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program; if not, see <https://www.gnu.org/licenses>.
23#
24# SPDX-License-Identifier: GPL-3.0-only
25#
26
27# chkconfig: 345 20 80
28# description: VirtualBox Linux kernel module
29#
30### BEGIN INIT INFO
31# Provides: vboxdrv
32# Required-Start: $syslog
33# Required-Stop:
34# Default-Start: 2 3 4 5
35# Default-Stop: 0 1 6
36# Short-Description: VirtualBox Linux kernel module
37### END INIT INFO
38
39## @todo This file duplicates a lot of script with vboxadd.sh. When making
40# changes please try to reduce differences between the two wherever possible.
41
42## @todo Remove the stop_vms target so that this script is only relevant to
43# kernel modules. Nice but not urgent.
44
45PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
46DEVICE=/dev/vboxdrv
47MODPROBE=/sbin/modprobe
48SCRIPTNAME=vboxdrv.sh
49
50# The below is GNU-specific. See VBox.sh for the longer Solaris/OS X version.
51TARGET=`readlink -e -- "${0}"` || exit 1
52SCRIPT_DIR="${TARGET%/[!/]*}"
53
54if $MODPROBE -c | grep -q '^allow_unsupported_modules *0'; then
55 MODPROBE="$MODPROBE --allow-unsupported-modules"
56fi
57
58setup_log()
59{
60 test -n "${LOG}" && return 0
61 # Rotate log files
62 LOG="/var/log/vbox-setup.log"
63 mv "${LOG}.3" "${LOG}.4" 2>/dev/null
64 mv "${LOG}.2" "${LOG}.3" 2>/dev/null
65 mv "${LOG}.1" "${LOG}.2" 2>/dev/null
66 mv "${LOG}" "${LOG}.1" 2>/dev/null
67}
68
69[ -f /etc/vbox/vbox.cfg ] && . /etc/vbox/vbox.cfg
70export VBOX_KBUILD_TYPE
71export USERNAME
72export USER=$USERNAME
73
74if test -n "${INSTALL_DIR}" && test -x "${INSTALL_DIR}/VirtualBox"; then
75 MODULE_SRC="${INSTALL_DIR}/src/vboxhost"
76elif test -x /usr/lib/virtualbox/VirtualBox; then
77 INSTALL_DIR=/usr/lib/virtualbox
78 MODULE_SRC="/usr/share/virtualbox/src/vboxhost"
79elif test -x "${SCRIPT_DIR}/VirtualBox"; then
80 # Executing from the build directory
81 INSTALL_DIR="${SCRIPT_DIR}"
82 MODULE_SRC="${INSTALL_DIR}/src"
83else
84 # Silently exit if the package was uninstalled but not purged.
85 # Applies to Debian packages only (but shouldn't hurt elsewhere)
86 exit 0
87fi
88VIRTUALBOX="${INSTALL_DIR}/VirtualBox"
89VBOXMANAGE="${INSTALL_DIR}/VBoxManage"
90BUILDINTMP="${MODULE_SRC}/build_in_tmp"
91if test -u "${VIRTUALBOX}"; then
92 GROUP=root
93 DEVICE_MODE=0600
94else
95 GROUP=vboxusers
96 DEVICE_MODE=0660
97fi
98
99KERN_VER=`uname -r`
100
101# Prepend PATH for building UEK7 on OL8 distribution.
102case "$KERN_VER" in
103 5.15.0-*.el8uek*) PATH="/opt/rh/gcc-toolset-11/root/usr/bin:$PATH";;
104esac
105
106if test -e "${MODULE_SRC}/vboxpci"; then
107 MODULE_LIST="vboxdrv vboxnetflt vboxnetadp vboxpci"
108else
109 MODULE_LIST="vboxdrv vboxnetflt vboxnetadp"
110fi
111# Secure boot state.
112case "`mokutil --sb-state 2>/dev/null`" in
113 *"disabled in shim"*) unset HAVE_SEC_BOOT;;
114 *"SecureBoot enabled"*) HAVE_SEC_BOOT=true;;
115 *) unset HAVE_SEC_BOOT;;
116esac
117# So far we can only sign modules on Ubuntu and on Debian 10 and later.
118DEB_PUB_KEY=/var/lib/shim-signed/mok/MOK.der
119DEB_PRIV_KEY=/var/lib/shim-signed/mok/MOK.priv
120unset HAVE_DEB_KEY
121case "`mokutil --test-key "$DEB_PUB_KEY" 2>/dev/null`" in
122 *"is already"*) DEB_KEY_ENROLLED=true;;
123 *) unset DEB_KEY_ENROLLED;;
124esac
125
126# Try to find a tool for modules signing.
127SIGN_TOOL=$(which kmodsign 2>/dev/null)
128# Attempt to use in-kernel signing tool if kmodsign not found.
129if test -z "$SIGN_TOOL"; then
130 if test -x "/lib/modules/$KERN_VER/build/scripts/sign-file"; then
131 SIGN_TOOL="/lib/modules/$KERN_VER/build/scripts/sign-file"
132 fi
133fi
134
135# Check if update-secureboot-policy tool supports required commandline options.
136update_secureboot_policy_supports()
137{
138 opt_name="$1"
139 [ -n "$opt_name" ] || return
140
141 [ -z "$(update-secureboot-policy --help 2>&1 | grep "$opt_name")" ] && return
142 echo "1"
143}
144
145HAVE_UPDATE_SECUREBOOT_POLICY_TOOL=
146if type update-secureboot-policy >/dev/null 2>&1; then
147 [ "$(update_secureboot_policy_supports new-key)" = "1" -a "$(update_secureboot_policy_supports enroll-key)" = "1" ] && \
148 HAVE_UPDATE_SECUREBOOT_POLICY_TOOL=true
149fi
150
151[ -r /etc/default/virtualbox ] && . /etc/default/virtualbox
152
153# Preamble for Gentoo
154if [ "`which $0`" = "/sbin/rc" ]; then
155 shift
156fi
157
158begin_msg()
159{
160 test -n "${2}" && echo "${SCRIPTNAME}: ${1}."
161 logger -t "${SCRIPTNAME}" "${1}."
162}
163
164succ_msg()
165{
166 logger -t "${SCRIPTNAME}" "${1}."
167}
168
169fail_msg()
170{
171 echo "${SCRIPTNAME}: failed: ${1}." >&2
172 logger -t "${SCRIPTNAME}" "failed: ${1}."
173}
174
175failure()
176{
177 fail_msg "$1"
178 exit 1
179}
180
181running()
182{
183 lsmod | grep -q "$1[^_-]"
184}
185
186log()
187{
188 setup_log
189 echo "${1}" >> "${LOG}"
190}
191
192module_build_log()
193{
194 setup_log
195 echo "${1}" | egrep -v \
196 "^test -e include/generated/autoconf.h|^echo >&2|^/bin/false\)$" \
197 >> "${LOG}"
198}
199
200# Detect VirtualBox version info or report error.
201VBOX_VERSION="`"$VBOXMANAGE" -v | cut -d r -f1`"
202[ -n "$VBOX_VERSION" ] || failure 'Cannot detect VirtualBox version number'
203VBOX_REVISION="r`"$VBOXMANAGE" -v | cut -d r -f2`"
204[ "$VBOX_REVISION" != "r" ] || failure 'Cannot detect VirtualBox revision number'
205
206## Output the vboxdrv part of our udev rule. This is redirected to the right file.
207udev_write_vboxdrv() {
208 VBOXDRV_GRP="$1"
209 VBOXDRV_MODE="$2"
210
211 echo "KERNEL==\"vboxdrv\", OWNER=\"root\", GROUP=\"$VBOXDRV_GRP\", MODE=\"$VBOXDRV_MODE\""
212 echo "KERNEL==\"vboxdrvu\", OWNER=\"root\", GROUP=\"root\", MODE=\"0666\""
213 echo "KERNEL==\"vboxnetctl\", OWNER=\"root\", GROUP=\"$VBOXDRV_GRP\", MODE=\"$VBOXDRV_MODE\""
214}
215
216## Output the USB part of our udev rule. This is redirected to the right file.
217udev_write_usb() {
218 INSTALLATION_DIR="$1"
219 USB_GROUP="$2"
220
221 echo "SUBSYSTEM==\"usb_device\", ACTION==\"add\", RUN+=\"$INSTALLATION_DIR/VBoxCreateUSBNode.sh \$major \$minor \$attr{bDeviceClass}${USB_GROUP}\""
222 echo "SUBSYSTEM==\"usb\", ACTION==\"add\", ENV{DEVTYPE}==\"usb_device\", RUN+=\"$INSTALLATION_DIR/VBoxCreateUSBNode.sh \$major \$minor \$attr{bDeviceClass}${USB_GROUP}\""
223 echo "SUBSYSTEM==\"usb_device\", ACTION==\"remove\", RUN+=\"$INSTALLATION_DIR/VBoxCreateUSBNode.sh --remove \$major \$minor\""
224 echo "SUBSYSTEM==\"usb\", ACTION==\"remove\", ENV{DEVTYPE}==\"usb_device\", RUN+=\"$INSTALLATION_DIR/VBoxCreateUSBNode.sh --remove \$major \$minor\""
225}
226
227## Generate our udev rule file. This takes a change in udev rule syntax in
228## version 55 into account. It only creates rules for USB for udev versions
229## recent enough to support USB device nodes.
230generate_udev_rule() {
231 VBOXDRV_GRP="$1" # The group owning the vboxdrv device
232 VBOXDRV_MODE="$2" # The access mode for the vboxdrv device
233 INSTALLATION_DIR="$3" # The directory VirtualBox is installed in
234 USB_GROUP="$4" # The group that has permission to access USB devices
235 NO_INSTALL="$5" # Set this to "1" to remove but not re-install rules
236
237 # Extra space!
238 case "$USB_GROUP" in ?*) USB_GROUP=" $USB_GROUP" ;; esac
239 case "$NO_INSTALL" in "1") return ;; esac
240 udev_write_vboxdrv "$VBOXDRV_GRP" "$VBOXDRV_MODE"
241 udev_write_usb "$INSTALLATION_DIR" "$USB_GROUP"
242}
243
244## Install udev rule (disable with INSTALL_NO_UDEV=1 in
245## /etc/default/virtualbox).
246install_udev() {
247 VBOXDRV_GRP="$1" # The group owning the vboxdrv device
248 VBOXDRV_MODE="$2" # The access mode for the vboxdrv device
249 INSTALLATION_DIR="$3" # The directory VirtualBox is installed in
250 USB_GROUP="$4" # The group that has permission to access USB devices
251 NO_INSTALL="$5" # Set this to "1" to remove but not re-install rules
252
253 if test -d /etc/udev/rules.d; then
254 generate_udev_rule "$VBOXDRV_GRP" "$VBOXDRV_MODE" "$INSTALLATION_DIR" \
255 "$USB_GROUP" "$NO_INSTALL"
256 fi
257 # Remove old udev description file
258 rm -f /etc/udev/rules.d/10-vboxdrv.rules 2> /dev/null
259}
260
261## Create a usb device node for a given sysfs path to a USB device.
262install_create_usb_node_for_sysfs() {
263 path="$1" # sysfs path for the device
264 usb_createnode="$2" # Path to the USB device node creation script
265 usb_group="$3" # The group to give ownership of the node to
266 if test -r "${path}/dev"; then
267 dev="`cat "${path}/dev" 2> /dev/null`"
268 major="`expr "$dev" : '\(.*\):' 2> /dev/null`"
269 minor="`expr "$dev" : '.*:\(.*\)' 2> /dev/null`"
270 class="`cat ${path}/bDeviceClass 2> /dev/null`"
271 sh "${usb_createnode}" "$major" "$minor" "$class" \
272 "${usb_group}" 2>/dev/null
273 fi
274}
275
276udev_rule_file=/etc/udev/rules.d/60-vboxdrv.rules
277sysfs_usb_devices="/sys/bus/usb/devices/*"
278
279## Install udev rules and create device nodes for usb access
280setup_usb() {
281 VBOXDRV_GRP="$1" # The group that should own /dev/vboxdrv
282 VBOXDRV_MODE="$2" # The mode to be used for /dev/vboxdrv
283 INSTALLATION_DIR="$3" # The directory VirtualBox is installed in
284 USB_GROUP="$4" # The group that should own the /dev/vboxusb device
285 # nodes unless INSTALL_NO_GROUP=1 in
286 # /etc/default/virtualbox. Optional.
287 usb_createnode="$INSTALLATION_DIR/VBoxCreateUSBNode.sh"
288 # install udev rule (disable with INSTALL_NO_UDEV=1 in
289 # /etc/default/virtualbox)
290 if [ "$INSTALL_NO_GROUP" != "1" ]; then
291 usb_group=$USB_GROUP
292 vboxdrv_group=$VBOXDRV_GRP
293 else
294 usb_group=root
295 vboxdrv_group=root
296 fi
297 install_udev "${vboxdrv_group}" "$VBOXDRV_MODE" \
298 "$INSTALLATION_DIR" "${usb_group}" \
299 "$INSTALL_NO_UDEV" > ${udev_rule_file}
300 # Build our device tree
301 for i in ${sysfs_usb_devices}; do # This line intentionally without quotes.
302 install_create_usb_node_for_sysfs "$i" "${usb_createnode}" \
303 "${usb_group}"
304 done
305}
306
307cleanup_usb()
308{
309 # Remove udev description file
310 rm -f /etc/udev/rules.d/60-vboxdrv.rules
311 rm -f /etc/udev/rules.d/10-vboxdrv.rules
312
313 # Remove our USB device tree
314 rm -rf /dev/vboxusb
315}
316
317# Returns path to module file as seen by modinfo(8) or empty string.
318module_path()
319{
320 mod="$1"
321 [ -n "$mod" ] || return
322
323 modinfo "$mod" 2>/dev/null | grep -e "^filename:" | tr -s ' ' | cut -d " " -f2
324}
325
326# Returns module version if module is available or empty string.
327module_version()
328{
329 mod="$1"
330 [ -n "$mod" ] || return
331
332 modinfo "$mod" 2>/dev/null | grep -e "^version:" | tr -s ' ' | cut -d " " -f2
333}
334
335# Returns module revision if module is available in the system or empty string.
336module_revision()
337{
338 mod="$1"
339 [ -n "$mod" ] || return
340
341 modinfo "$mod" 2>/dev/null | grep -e "^version:" | tr -s ' ' | cut -d " " -f3
342}
343
344# Reads kernel configuration option.
345kernel_get_config_opt()
346{
347 opt_name="$1"
348 [ -n "$opt_name" ] || return
349
350 # Check if there is a kernel tool which can extract config option.
351 if test -x /lib/modules/"$KERN_VER"/build/scripts/config; then
352 /lib/modules/"$KERN_VER"/build/scripts/config \
353 --file /lib/modules/"$KERN_VER"/build/.config \
354 --state "$opt_name" 2>/dev/null
355 elif test -f /lib/modules/"$KERN_VER"/build/.config; then
356 # Extract config option manually.
357 grep "$opt_name=" /lib/modules/"$KERN_VER"/build/.config | sed -e "s/^$opt_name=//" -e "s/\"//g"
358 fi
359}
360
361# Reads CONFIG_MODULE_SIG_HASH from kernel config.
362kernel_module_sig_hash()
363{
364 kernel_get_config_opt "CONFIG_MODULE_SIG_HASH"
365}
366
367# Returns "1" if kernel module signature hash algorithm
368# is supported by us. Or empty string otherwise.
369module_sig_hash_supported()
370{
371 sig_hashalgo="$1"
372 [ -n "$sig_hashalgo" ] || return
373
374 # Go through supported list.
375 [ "$sig_hashalgo" = "sha1" \
376 -o "$sig_hashalgo" = "sha224" \
377 -o "$sig_hashalgo" = "sha256" \
378 -o "$sig_hashalgo" = "sha384" \
379 -o "$sig_hashalgo" = "sha512" ] || return
380
381 echo "1"
382}
383
384# Check if kernel configuration requires modules signature.
385kernel_requires_module_signature()
386{
387 vbox_sys_lockdown_path="/sys/kernel/security/lockdown"
388
389 requires=""
390 # We consider that if kernel is running in the following configurations,
391 # it will require modules to be signed.
392 if [ "$(kernel_get_config_opt "CONFIG_MODULE_SIG")" = "y" ]; then
393
394 # Modules signature verification is hardcoded in kernel config.
395 [ "$(kernel_get_config_opt "CONFIG_MODULE_SIG_FORCE")" = "y" ] && requires="1"
396
397 # Unsigned modules loading is restricted by "lockdown" feature in runtime.
398 if [ "$(kernel_get_config_opt "CONFIG_SECURITY_LOCKDOWN_LSM")" = "y" \
399 -o "$(kernel_get_config_opt "CONFIG_SECURITY_LOCKDOWN_LSM_EARLY")" = "y" ]; then
400
401 # Once lockdown level is set to something different than "none" (e.g., "integrity"
402 # or "confidentiality"), kernel will reject unsigned modules loading.
403 if [ -r "$vbox_sys_lockdown_path" ]; then
404 [ -n "$(cat "$vbox_sys_lockdown_path" | grep "\[integrity\]")" ] && requires="1"
405 [ -n "$(cat "$vbox_sys_lockdown_path" | grep "\[confidentiality\]")" ] && requires="1"
406 fi
407
408 # This configuration is used by a number of modern Linux distributions and restricts
409 # unsigned modules loading when Secure Boot mode is enabled.
410 [ "$(kernel_get_config_opt "CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT")" = "y" -a -n "$HAVE_SEC_BOOT" ] && requires="1"
411 fi
412 fi
413
414 [ -n "$requires" ] && echo "1"
415}
416
417# Returns "1" if module is signed and signature can be verified
418# with public key provided in DEB_PUB_KEY. Or empty string otherwise.
419module_signed()
420{
421 mod="$1"
422 [ -n "$mod" ] || return
423
424 # Be nice with distributions which do not provide tools which we
425 # use in order to verify module signature. This variable needs to
426 # be explicitly set by administrator. This script will look for it
427 # in /etc/vbox/vbox.cfg. Make sure that you know what you do!
428 if [ "$VBOX_BYPASS_MODULES_SIGNATURE_CHECK" = "1" ]; then
429 echo "1"
430 return
431 fi
432
433 extraction_tool=/lib/modules/"$(uname -r)"/build/scripts/extract-module-sig.pl
434 mod_path=$(module_path "$mod" 2>/dev/null)
435 openssl_tool=$(which openssl 2>/dev/null)
436 # Do not use built-in printf!
437 printf_tool=$(which printf 2>/dev/null)
438
439 # Make sure all the tools required for signature validation are available.
440 [ -x "$extraction_tool" ] || return
441 [ -n "$mod_path" ] || return
442 [ -n "$openssl_tool" ] || return
443 [ -n "$printf_tool" ] || return
444
445 # Make sure openssl can handle hash algorithm.
446 sig_hashalgo=$(modinfo -F sig_hashalgo "$mod" 2>/dev/null)
447 [ "$(module_sig_hash_supported $sig_hashalgo)" = "1" ] || return
448
449 # Generate file names for temporary stuff.
450 mod_pub_key=$(mktemp -u)
451 mod_signature=$(mktemp -u)
452 mod_unsigned=$(mktemp -u)
453
454 # Convert public key in DER format into X509 certificate form.
455 "$openssl_tool" x509 -pubkey -inform DER -in "$DEB_PUB_KEY" -out "$mod_pub_key" 2>/dev/null
456 # Extract raw module signature and convert it into binary format.
457 "$printf_tool" \\x$(modinfo -F signature "$mod" | sed -z 's/[ \t\n]//g' | sed -e "s/:/\\\x/g") 2>/dev/null > "$mod_signature"
458 # Extract unsigned module for further digest calculation.
459 "$extraction_tool" -0 "$mod_path" 2>/dev/null > "$mod_unsigned"
460
461 # Verify signature.
462 rc=""
463 "$openssl_tool" dgst "-$sig_hashalgo" -binary -verify "$mod_pub_key" -signature "$mod_signature" "$mod_unsigned" 2>&1 >/dev/null && rc="1"
464 # Clean up.
465 rm -f $mod_pub_key $mod_signature $mod_unsigned
466
467 # Check result.
468 [ "$rc" = "1" ] || return
469
470 echo "1"
471}
472
473# Returns "1" if externally built module is available in the system and its
474# version and revision number do match to current VirtualBox installation.
475# Or empty string otherwise.
476module_available()
477{
478 mod="$1"
479 [ -n "$mod" ] || return
480
481 [ "$VBOX_VERSION" = "$(module_version "$mod")" ] || return
482 [ "$VBOX_REVISION" = "$(module_revision "$mod")" ] || return
483
484 # Check if module belongs to VirtualBox installation.
485 #
486 # We have a convention that only modules from /lib/modules/*/misc
487 # belong to us. Modules from other locations are treated as
488 # externally built.
489 mod_path="$(module_path "$mod")"
490
491 # If module path points to a symbolic link, resolve actual file location.
492 [ -L "$mod_path" ] && mod_path="$(readlink -e -- "$mod_path")"
493
494 # File exists?
495 [ -f "$mod_path" ] || return
496
497 # Extract last component of module path and check whether it is located
498 # outside of /lib/modules/*/misc.
499 mod_dir="$(dirname "$mod_path" | sed 's;^.*/;;')"
500 [ "$mod_dir" = "misc" ] || return
501
502 # In case if kernel configuration requires module signature, check if module is signed.
503 if test "$(kernel_requires_module_signature)" = "1"; then
504 [ "$(module_signed "$mod")" = "1" ] || return
505 fi
506
507 echo "1"
508}
509
510# Check if required modules are installed in the system and versions match.
511setup_complete()
512{
513 [ "$(module_available vboxdrv)" = "1" ] || return
514 [ "$(module_available vboxnetflt)" = "1" ] || return
515 [ "$(module_available vboxnetadp)" = "1" ] || return
516
517 # All modules are in place.
518 echo "1"
519}
520
521start()
522{
523 begin_msg "Starting VirtualBox services" console
524 if [ -d /proc/xen ]; then
525 failure "Running VirtualBox in a Xen environment is not supported"
526 fi
527 if test "$(kernel_requires_module_signature)" = "1" && test -z "$DEB_KEY_ENROLLED"; then
528 if test -n "$HAVE_DEB_KEY"; then
529 begin_msg "You must re-start your system to finish Debian secure boot set-up." console
530 else
531 begin_msg "You must sign these kernel modules before using VirtualBox:
532 $MODULE_LIST
533See the documentation for your Linux distribution." console
534 fi
535 fi
536
537 if ! running vboxdrv; then
538
539 # Check if system already has matching modules installed.
540 [ "$(setup_complete)" = "1" ] || setup
541
542 if ! rm -f $DEVICE; then
543 failure "Cannot remove $DEVICE"
544 fi
545 if ! $MODPROBE vboxdrv > /dev/null 2>&1; then
546 failure "modprobe vboxdrv failed. Please use 'dmesg' to find out why"
547 fi
548 sleep .2
549 fi
550 # ensure the character special exists
551 if [ ! -c $DEVICE ]; then
552 MAJOR=`sed -n 's;\([0-9]\+\) vboxdrv$;\1;p' /proc/devices`
553 if [ ! -z "$MAJOR" ]; then
554 MINOR=0
555 else
556 MINOR=`sed -n 's;\([0-9]\+\) vboxdrv$;\1;p' /proc/misc`
557 if [ ! -z "$MINOR" ]; then
558 MAJOR=10
559 fi
560 fi
561 if [ -z "$MAJOR" ]; then
562 rmmod vboxdrv 2>/dev/null
563 failure "Cannot locate the VirtualBox device"
564 fi
565 if ! mknod -m 0660 $DEVICE c $MAJOR $MINOR 2>/dev/null; then
566 rmmod vboxdrv 2>/dev/null
567 failure "Cannot create device $DEVICE with major $MAJOR and minor $MINOR"
568 fi
569 fi
570 # ensure permissions
571 if ! chown :"${GROUP}" $DEVICE 2>/dev/null; then
572 rmmod vboxpci 2>/dev/null
573 rmmod vboxnetadp 2>/dev/null
574 rmmod vboxnetflt 2>/dev/null
575 rmmod vboxdrv 2>/dev/null
576 failure "Cannot change group ${GROUP} for device $DEVICE"
577 fi
578 if ! $MODPROBE vboxnetflt > /dev/null 2>&1; then
579 failure "modprobe vboxnetflt failed. Please use 'dmesg' to find out why"
580 fi
581 if ! $MODPROBE vboxnetadp > /dev/null 2>&1; then
582 failure "modprobe vboxnetadp failed. Please use 'dmesg' to find out why"
583 fi
584 if test -e "${MODULE_SRC}/vboxpci" && ! $MODPROBE vboxpci > /dev/null 2>&1; then
585 failure "modprobe vboxpci failed. Please use 'dmesg' to find out why"
586 fi
587 # Create the /dev/vboxusb directory if the host supports that method
588 # of USB access. The USB code checks for the existence of that path.
589 if grep -q usb_device /proc/devices; then
590 mkdir -p -m 0750 /dev/vboxusb 2>/dev/null
591 chown root:vboxusers /dev/vboxusb 2>/dev/null
592 fi
593 # Remove any kernel modules left over from previously installed kernels.
594 cleanup only_old
595 succ_msg "VirtualBox services started"
596}
597
598stop()
599{
600 begin_msg "Stopping VirtualBox services" console
601
602 if running vboxpci; then
603 if ! rmmod vboxpci 2>/dev/null; then
604 failure "Cannot unload module vboxpci"
605 fi
606 fi
607 if running vboxnetadp; then
608 if ! rmmod vboxnetadp 2>/dev/null; then
609 failure "Cannot unload module vboxnetadp"
610 fi
611 fi
612 if running vboxdrv; then
613 if running vboxnetflt; then
614 if ! rmmod vboxnetflt 2>/dev/null; then
615 failure "Cannot unload module vboxnetflt"
616 fi
617 fi
618 if ! rmmod vboxdrv 2>/dev/null; then
619 failure "Cannot unload module vboxdrv"
620 fi
621 if ! rm -f $DEVICE; then
622 failure "Cannot unlink $DEVICE"
623 fi
624 fi
625 succ_msg "VirtualBox services stopped"
626}
627
628# enter the following variables in /etc/default/virtualbox:
629# SHUTDOWN_USERS="foo bar"
630# check for running VMs of user foo and user bar
631# SHUTDOWN=poweroff
632# SHUTDOWN=acpibutton
633# SHUTDOWN=savestate
634# select one of these shutdown methods for running VMs
635stop_vms()
636{
637 wait=0
638 for i in $SHUTDOWN_USERS; do
639 # don't create the ipcd directory with wrong permissions!
640 if [ -d /tmp/.vbox-$i-ipc ]; then
641 export VBOX_IPC_SOCKETID="$i"
642 VMS=`$VBOXMANAGE --nologo list runningvms | sed -e 's/^".*".*{\(.*\)}/\1/' 2>/dev/null`
643 if [ -n "$VMS" ]; then
644 if [ "$SHUTDOWN" = "poweroff" ]; then
645 begin_msg "Powering off remaining VMs"
646 for v in $VMS; do
647 $VBOXMANAGE --nologo controlvm $v poweroff
648 done
649 succ_msg "Remaining VMs powered off"
650 elif [ "$SHUTDOWN" = "acpibutton" ]; then
651 begin_msg "Sending ACPI power button event to remaining VMs"
652 for v in $VMS; do
653 $VBOXMANAGE --nologo controlvm $v acpipowerbutton
654 wait=30
655 done
656 succ_msg "ACPI power button event sent to remaining VMs"
657 elif [ "$SHUTDOWN" = "savestate" ]; then
658 begin_msg "Saving state of remaining VMs"
659 for v in $VMS; do
660 $VBOXMANAGE --nologo controlvm $v savestate
661 done
662 succ_msg "State of remaining VMs saved"
663 fi
664 fi
665 fi
666 done
667 # wait for some seconds when doing ACPI shutdown
668 if [ "$wait" -ne 0 ]; then
669 begin_msg "Waiting for $wait seconds for VM shutdown"
670 sleep $wait
671 succ_msg "Waited for $wait seconds for VM shutdown"
672 fi
673}
674
675cleanup()
676{
677 # If this is set, only remove kernel modules for no longer installed
678 # kernels. Note that only generated kernel modules should be placed
679 # in /lib/modules/*/misc. Anything that we should not remove automatically
680 # should go elsewhere.
681 only_old="${1}"
682 for i in /lib/modules/*; do
683 # Check whether we are only cleaning up for uninstalled kernels.
684 test -n "${only_old}" && test -e "${i}/kernel/drivers" && continue
685
686 unset do_update
687 for j in $MODULE_LIST; do
688 for mod_ext in ko ko.gz ko.xz ko.zst; do
689 test -f "${i}/misc/${j}.${mod_ext}" && do_update=1 && rm -f "${i}/misc/${j}.${mod_ext}"
690 done
691 done
692
693 # Trigger depmod(8) only in case if directory content was modified
694 # and save a bit of run time.
695 test -n "$do_update" && depmod -a "$(basename "$i")" && sync
696
697 # Remove the kernel version folder if it was empty except for us.
698 test "`echo ${i}/misc/* ${i}/misc/.?* ${i}/* ${i}/.?*`" \
699 = "${i}/misc/* ${i}/misc/.. ${i}/misc ${i}/.." &&
700 rmdir "${i}/misc" "${i}" # We used to leave empty folders.
701 done
702}
703
704# setup_script
705setup()
706{
707 begin_msg "Building VirtualBox kernel modules" console
708 log "Building the main VirtualBox module."
709
710 # Detect if kernel was built with clang.
711 unset LLVM
712 vbox_cc_is_clang=$(kernel_get_config_opt "CONFIG_CC_IS_CLANG")
713 if test "${vbox_cc_is_clang}" = "y"; then
714 log "Using clang compiler."
715 export LLVM=1
716 fi
717
718 if ! myerr=`$BUILDINTMP \
719 --save-module-symvers /tmp/vboxdrv-Module.symvers \
720 --module-source "$MODULE_SRC/vboxdrv" \
721 --no-print-directory install 2>&1`; then
722 "${INSTALL_DIR}/check_module_dependencies.sh" || exit 1
723 log "Error building the module:"
724 module_build_log "$myerr"
725 failure "Look at $LOG to find out what went wrong"
726 fi
727 log "Building the net filter module."
728 if ! myerr=`$BUILDINTMP \
729 --use-module-symvers /tmp/vboxdrv-Module.symvers \
730 --module-source "$MODULE_SRC/vboxnetflt" \
731 --no-print-directory install 2>&1`; then
732 log "Error building the module:"
733 module_build_log "$myerr"
734 failure "Look at $LOG to find out what went wrong"
735 fi
736 log "Building the net adapter module."
737 if ! myerr=`$BUILDINTMP \
738 --use-module-symvers /tmp/vboxdrv-Module.symvers \
739 --module-source "$MODULE_SRC/vboxnetadp" \
740 --no-print-directory install 2>&1`; then
741 log "Error building the module:"
742 module_build_log "$myerr"
743 failure "Look at $LOG to find out what went wrong"
744 fi
745 if test -e "$MODULE_SRC/vboxpci"; then
746 log "Building the PCI pass-through module."
747 if ! myerr=`$BUILDINTMP \
748 --use-module-symvers /tmp/vboxdrv-Module.symvers \
749 --module-source "$MODULE_SRC/vboxpci" \
750 --no-print-directory install 2>&1`; then
751 log "Error building the module:"
752 module_build_log "$myerr"
753 failure "Look at $LOG to find out what went wrong"
754 fi
755 fi
756 rm -f /etc/vbox/module_not_compiled
757 depmod -a
758 sync
759 succ_msg "VirtualBox kernel modules built"
760
761 # Sign kernel modules if kernel configuration requires it.
762 if test "$(kernel_requires_module_signature)" = "1"; then
763 begin_msg "Signing VirtualBox kernel modules" console
764
765 # Generate new signing key if needed.
766 [ -n "$HAVE_UPDATE_SECUREBOOT_POLICY_TOOL" ] && SHIM_NOTRIGGER=y update-secureboot-policy --new-key
767
768 # Check if signing keys are in place.
769 if test ! -f "$DEB_PUB_KEY" || ! test -f "$DEB_PRIV_KEY"; then
770 # update-secureboot-policy tool present in the system, but keys were not generated.
771 [ -n "$HAVE_UPDATE_SECUREBOOT_POLICY_TOOL" ] && fail_msg "
772
773update-secureboot-policy tool does not generate signing keys
774in your distribution, see below on how to generate them manually
775"
776
777 # update-secureboot-policy not present in the system, recommend generate keys manually.
778 failure "
779
780System is running in Secure Boot mode, however your distribution
781does not provide tools for automatic generation of keys needed for
782modules signing. Please consider to generate and enroll them manually:
783
784 sudo mkdir -p /var/lib/shim-signed/mok
785 sudo openssl req -nodes -new -x509 -newkey rsa:2048 -outform DER -addext \"extendedKeyUsage=codeSigning\" -keyout $DEB_PRIV_KEY -out $DEB_PUB_KEY
786 sudo mokutil --import $DEB_PUB_KEY
787 sudo reboot
788
789Restart \"rcvboxdrv setup\" after system is rebooted
790"
791 fi
792
793 # Check if signing tool is available.
794 [ -n "$SIGN_TOOL" ] || failure "Unable to find signing tool"
795
796 # Get kernel signature hash algorithm from kernel config and validate it.
797 sig_hashalgo=$(kernel_module_sig_hash)
798 [ "$(module_sig_hash_supported $sig_hashalgo)" = "1" ] \
799 || failure "Unsupported kernel signature hash algorithm $sig_hashalgo"
800
801 # Sign modules.
802 for i in $MODULE_LIST; do
803 "$SIGN_TOOL" "$sig_hashalgo" "$DEB_PRIV_KEY" "$DEB_PUB_KEY" \
804 /lib/modules/"$KERN_VER"/misc/"$i".ko 2>/dev/null || failure "Unable to sign $i.ko"
805 done
806
807 # Enroll signing key if needed.
808 if test -n "$HAVE_UPDATE_SECUREBOOT_POLICY_TOOL"; then
809 # update-secureboot-policy "expects" DKMS modules.
810 # Work around this and talk to the authors as soon
811 # as possible to fix it.
812 mkdir -p /var/lib/dkms/vbox-temp
813 update-secureboot-policy --enroll-key 2>/dev/null ||
814 begin_msg "Failed to enroll secure boot key." console
815 rmdir -p /var/lib/dkms/vbox-temp 2>/dev/null
816
817 # Indicate that key has been enrolled and reboot is needed.
818 HAVE_DEB_KEY=true
819 fi
820 succ_msg "Signing completed"
821 fi
822}
823
824dmnstatus()
825{
826 if running vboxdrv; then
827 str="vboxdrv"
828 if running vboxnetflt; then
829 str="$str, vboxnetflt"
830 if running vboxnetadp; then
831 str="$str, vboxnetadp"
832 fi
833 fi
834 if running vboxpci; then
835 str="$str, vboxpci"
836 fi
837 echo "VirtualBox kernel modules ($str) are loaded."
838 for i in $SHUTDOWN_USERS; do
839 # don't create the ipcd directory with wrong permissions!
840 if [ -d /tmp/.vbox-$i-ipc ]; then
841 export VBOX_IPC_SOCKETID="$i"
842 VMS=`$VBOXMANAGE --nologo list runningvms | sed -e 's/^".*".*{\(.*\)}/\1/' 2>/dev/null`
843 if [ -n "$VMS" ]; then
844 echo "The following VMs are currently running:"
845 for v in $VMS; do
846 echo " $v"
847 done
848 fi
849 fi
850 done
851 else
852 echo "VirtualBox kernel module is not loaded."
853 fi
854}
855
856case "$1" in
857start)
858 start
859 ;;
860stop)
861 stop_vms
862 stop
863 ;;
864stop_vms)
865 stop_vms
866 ;;
867restart)
868 stop && start
869 ;;
870setup)
871 test -n "${2}" && export KERN_VER="${2}"
872 # Create udev rule and USB device nodes.
873 ## todo Wouldn't it make more sense to install the rule to /lib/udev? This
874 ## is not a user-created configuration file after all.
875 ## todo Do we need a udev rule to create /dev/vboxdrv[u] at all? We have
876 ## working fall-back code here anyway, and the "right" code is more complex
877 ## than the fall-back. Unnecessary duplication?
878 stop && cleanup
879 setup_usb "$GROUP" "$DEVICE_MODE" "$INSTALL_DIR"
880 start
881 ;;
882cleanup)
883 stop && cleanup
884 cleanup_usb
885 ;;
886force-reload)
887 stop
888 start
889 ;;
890status)
891 dmnstatus
892 ;;
893*)
894 echo "Usage: $0 {start|stop|stop_vms|restart|setup|cleanup|force-reload|status}"
895 exit 1
896esac
897
898exit 0
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use