VirtualBox

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

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

Linux: rcvboxdrv, rcvboxadd: take into account CONFIG_LOCK_DOWN_KERNEL when detecting if kernel in lockdown mode, bugref:10287.

This option is in use by older kernels such as 4.18.0-147.el8.

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 30.7 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_LOCK_DOWN_KERNEL")" = "y" \
399 -o "$(kernel_get_config_opt "CONFIG_SECURITY_LOCKDOWN_LSM")" = "y" \
400 -o "$(kernel_get_config_opt "CONFIG_SECURITY_LOCKDOWN_LSM_EARLY")" = "y" ]; then
401
402 # Once lockdown level is set to something different than "none" (e.g., "integrity"
403 # or "confidentiality"), kernel will reject unsigned modules loading.
404 if [ -r "$vbox_sys_lockdown_path" ]; then
405 [ -n "$(cat "$vbox_sys_lockdown_path" | grep "\[integrity\]")" ] && requires="1"
406 [ -n "$(cat "$vbox_sys_lockdown_path" | grep "\[confidentiality\]")" ] && requires="1"
407 fi
408
409 # This configuration is used by a number of modern Linux distributions and restricts
410 # unsigned modules loading when Secure Boot mode is enabled.
411 [ "$(kernel_get_config_opt "CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT")" = "y" -a -n "$HAVE_SEC_BOOT" ] && requires="1"
412 fi
413 fi
414
415 [ -n "$requires" ] && echo "1"
416}
417
418# Returns "1" if module is signed and signature can be verified
419# with public key provided in DEB_PUB_KEY. Or empty string otherwise.
420module_signed()
421{
422 mod="$1"
423 [ -n "$mod" ] || return
424
425 # Be nice with distributions which do not provide tools which we
426 # use in order to verify module signature. This variable needs to
427 # be explicitly set by administrator. This script will look for it
428 # in /etc/vbox/vbox.cfg. Make sure that you know what you do!
429 if [ "$VBOX_BYPASS_MODULES_SIGNATURE_CHECK" = "1" ]; then
430 echo "1"
431 return
432 fi
433
434 extraction_tool=/lib/modules/"$(uname -r)"/build/scripts/extract-module-sig.pl
435 mod_path=$(module_path "$mod" 2>/dev/null)
436 openssl_tool=$(which openssl 2>/dev/null)
437 # Do not use built-in printf!
438 printf_tool=$(which printf 2>/dev/null)
439
440 # Make sure all the tools required for signature validation are available.
441 [ -x "$extraction_tool" ] || return
442 [ -n "$mod_path" ] || return
443 [ -n "$openssl_tool" ] || return
444 [ -n "$printf_tool" ] || return
445
446 # Make sure openssl can handle hash algorithm.
447 sig_hashalgo=$(modinfo -F sig_hashalgo "$mod" 2>/dev/null)
448 [ "$(module_sig_hash_supported $sig_hashalgo)" = "1" ] || return
449
450 # Generate file names for temporary stuff.
451 mod_pub_key=$(mktemp -u)
452 mod_signature=$(mktemp -u)
453 mod_unsigned=$(mktemp -u)
454
455 # Convert public key in DER format into X509 certificate form.
456 "$openssl_tool" x509 -pubkey -inform DER -in "$DEB_PUB_KEY" -out "$mod_pub_key" 2>/dev/null
457 # Extract raw module signature and convert it into binary format.
458 "$printf_tool" \\x$(modinfo -F signature "$mod" | sed -z 's/[ \t\n]//g' | sed -e "s/:/\\\x/g") 2>/dev/null > "$mod_signature"
459 # Extract unsigned module for further digest calculation.
460 "$extraction_tool" -0 "$mod_path" 2>/dev/null > "$mod_unsigned"
461
462 # Verify signature.
463 rc=""
464 "$openssl_tool" dgst "-$sig_hashalgo" -binary -verify "$mod_pub_key" -signature "$mod_signature" "$mod_unsigned" 2>&1 >/dev/null && rc="1"
465 # Clean up.
466 rm -f $mod_pub_key $mod_signature $mod_unsigned
467
468 # Check result.
469 [ "$rc" = "1" ] || return
470
471 echo "1"
472}
473
474# Returns "1" if externally built module is available in the system and its
475# version and revision number do match to current VirtualBox installation.
476# Or empty string otherwise.
477module_available()
478{
479 mod="$1"
480 [ -n "$mod" ] || return
481
482 [ "$VBOX_VERSION" = "$(module_version "$mod")" ] || return
483 [ "$VBOX_REVISION" = "$(module_revision "$mod")" ] || return
484
485 # Check if module belongs to VirtualBox installation.
486 #
487 # We have a convention that only modules from /lib/modules/*/misc
488 # belong to us. Modules from other locations are treated as
489 # externally built.
490 mod_path="$(module_path "$mod")"
491
492 # If module path points to a symbolic link, resolve actual file location.
493 [ -L "$mod_path" ] && mod_path="$(readlink -e -- "$mod_path")"
494
495 # File exists?
496 [ -f "$mod_path" ] || return
497
498 # Extract last component of module path and check whether it is located
499 # outside of /lib/modules/*/misc.
500 mod_dir="$(dirname "$mod_path" | sed 's;^.*/;;')"
501 [ "$mod_dir" = "misc" ] || return
502
503 # In case if kernel configuration requires module signature, check if module is signed.
504 if test "$(kernel_requires_module_signature)" = "1"; then
505 [ "$(module_signed "$mod")" = "1" ] || return
506 fi
507
508 echo "1"
509}
510
511# Check if required modules are installed in the system and versions match.
512setup_complete()
513{
514 [ "$(module_available vboxdrv)" = "1" ] || return
515 [ "$(module_available vboxnetflt)" = "1" ] || return
516 [ "$(module_available vboxnetadp)" = "1" ] || return
517
518 # All modules are in place.
519 echo "1"
520}
521
522start()
523{
524 begin_msg "Starting VirtualBox services" console
525 if [ -d /proc/xen ]; then
526 failure "Running VirtualBox in a Xen environment is not supported"
527 fi
528 if test "$(kernel_requires_module_signature)" = "1" && test -z "$DEB_KEY_ENROLLED"; then
529 if test -n "$HAVE_DEB_KEY"; then
530 begin_msg "You must re-start your system to finish Debian secure boot set-up." console
531 else
532 begin_msg "You must sign these kernel modules before using VirtualBox:
533 $MODULE_LIST
534See the documentation for your Linux distribution." console
535 fi
536 fi
537
538 if ! running vboxdrv; then
539
540 # Check if system already has matching modules installed.
541 [ "$(setup_complete)" = "1" ] || setup
542
543 if ! rm -f $DEVICE; then
544 failure "Cannot remove $DEVICE"
545 fi
546 if ! $MODPROBE vboxdrv > /dev/null 2>&1; then
547 failure "modprobe vboxdrv failed. Please use 'dmesg' to find out why"
548 fi
549 sleep .2
550 fi
551 # ensure the character special exists
552 if [ ! -c $DEVICE ]; then
553 MAJOR=`sed -n 's;\([0-9]\+\) vboxdrv$;\1;p' /proc/devices`
554 if [ ! -z "$MAJOR" ]; then
555 MINOR=0
556 else
557 MINOR=`sed -n 's;\([0-9]\+\) vboxdrv$;\1;p' /proc/misc`
558 if [ ! -z "$MINOR" ]; then
559 MAJOR=10
560 fi
561 fi
562 if [ -z "$MAJOR" ]; then
563 rmmod vboxdrv 2>/dev/null
564 failure "Cannot locate the VirtualBox device"
565 fi
566 if ! mknod -m 0660 $DEVICE c $MAJOR $MINOR 2>/dev/null; then
567 rmmod vboxdrv 2>/dev/null
568 failure "Cannot create device $DEVICE with major $MAJOR and minor $MINOR"
569 fi
570 fi
571 # ensure permissions
572 if ! chown :"${GROUP}" $DEVICE 2>/dev/null; then
573 rmmod vboxpci 2>/dev/null
574 rmmod vboxnetadp 2>/dev/null
575 rmmod vboxnetflt 2>/dev/null
576 rmmod vboxdrv 2>/dev/null
577 failure "Cannot change group ${GROUP} for device $DEVICE"
578 fi
579 if ! $MODPROBE vboxnetflt > /dev/null 2>&1; then
580 failure "modprobe vboxnetflt failed. Please use 'dmesg' to find out why"
581 fi
582 if ! $MODPROBE vboxnetadp > /dev/null 2>&1; then
583 failure "modprobe vboxnetadp failed. Please use 'dmesg' to find out why"
584 fi
585 if test -e "${MODULE_SRC}/vboxpci" && ! $MODPROBE vboxpci > /dev/null 2>&1; then
586 failure "modprobe vboxpci failed. Please use 'dmesg' to find out why"
587 fi
588 # Create the /dev/vboxusb directory if the host supports that method
589 # of USB access. The USB code checks for the existence of that path.
590 if grep -q usb_device /proc/devices; then
591 mkdir -p -m 0750 /dev/vboxusb 2>/dev/null
592 chown root:vboxusers /dev/vboxusb 2>/dev/null
593 fi
594 # Remove any kernel modules left over from previously installed kernels.
595 cleanup only_old
596 succ_msg "VirtualBox services started"
597}
598
599stop()
600{
601 begin_msg "Stopping VirtualBox services" console
602
603 if running vboxpci; then
604 if ! rmmod vboxpci 2>/dev/null; then
605 failure "Cannot unload module vboxpci"
606 fi
607 fi
608 if running vboxnetadp; then
609 if ! rmmod vboxnetadp 2>/dev/null; then
610 failure "Cannot unload module vboxnetadp"
611 fi
612 fi
613 if running vboxdrv; then
614 if running vboxnetflt; then
615 if ! rmmod vboxnetflt 2>/dev/null; then
616 failure "Cannot unload module vboxnetflt"
617 fi
618 fi
619 if ! rmmod vboxdrv 2>/dev/null; then
620 failure "Cannot unload module vboxdrv"
621 fi
622 if ! rm -f $DEVICE; then
623 failure "Cannot unlink $DEVICE"
624 fi
625 fi
626 succ_msg "VirtualBox services stopped"
627}
628
629# enter the following variables in /etc/default/virtualbox:
630# SHUTDOWN_USERS="foo bar"
631# check for running VMs of user foo and user bar
632# SHUTDOWN=poweroff
633# SHUTDOWN=acpibutton
634# SHUTDOWN=savestate
635# select one of these shutdown methods for running VMs
636stop_vms()
637{
638 wait=0
639 for i in $SHUTDOWN_USERS; do
640 # don't create the ipcd directory with wrong permissions!
641 if [ -d /tmp/.vbox-$i-ipc ]; then
642 export VBOX_IPC_SOCKETID="$i"
643 VMS=`$VBOXMANAGE --nologo list runningvms | sed -e 's/^".*".*{\(.*\)}/\1/' 2>/dev/null`
644 if [ -n "$VMS" ]; then
645 if [ "$SHUTDOWN" = "poweroff" ]; then
646 begin_msg "Powering off remaining VMs"
647 for v in $VMS; do
648 $VBOXMANAGE --nologo controlvm $v poweroff
649 done
650 succ_msg "Remaining VMs powered off"
651 elif [ "$SHUTDOWN" = "acpibutton" ]; then
652 begin_msg "Sending ACPI power button event to remaining VMs"
653 for v in $VMS; do
654 $VBOXMANAGE --nologo controlvm $v acpipowerbutton
655 wait=30
656 done
657 succ_msg "ACPI power button event sent to remaining VMs"
658 elif [ "$SHUTDOWN" = "savestate" ]; then
659 begin_msg "Saving state of remaining VMs"
660 for v in $VMS; do
661 $VBOXMANAGE --nologo controlvm $v savestate
662 done
663 succ_msg "State of remaining VMs saved"
664 fi
665 fi
666 fi
667 done
668 # wait for some seconds when doing ACPI shutdown
669 if [ "$wait" -ne 0 ]; then
670 begin_msg "Waiting for $wait seconds for VM shutdown"
671 sleep $wait
672 succ_msg "Waited for $wait seconds for VM shutdown"
673 fi
674}
675
676cleanup()
677{
678 # If this is set, only remove kernel modules for no longer installed
679 # kernels. Note that only generated kernel modules should be placed
680 # in /lib/modules/*/misc. Anything that we should not remove automatically
681 # should go elsewhere.
682 only_old="${1}"
683 for i in /lib/modules/*; do
684 # Check whether we are only cleaning up for uninstalled kernels.
685 test -n "${only_old}" && test -e "${i}/kernel/drivers" && continue
686
687 unset do_update
688 for j in $MODULE_LIST; do
689 for mod_ext in ko ko.gz ko.xz ko.zst; do
690 test -f "${i}/misc/${j}.${mod_ext}" && do_update=1 && rm -f "${i}/misc/${j}.${mod_ext}"
691 done
692 done
693
694 # Trigger depmod(8) only in case if directory content was modified
695 # and save a bit of run time.
696 test -n "$do_update" && depmod -a "$(basename "$i")" && sync
697
698 # Remove the kernel version folder if it was empty except for us.
699 test "`echo ${i}/misc/* ${i}/misc/.?* ${i}/* ${i}/.?*`" \
700 = "${i}/misc/* ${i}/misc/.. ${i}/misc ${i}/.." &&
701 rmdir "${i}/misc" "${i}" # We used to leave empty folders.
702 done
703}
704
705# setup_script
706setup()
707{
708 begin_msg "Building VirtualBox kernel modules" console
709 log "Building the main VirtualBox module."
710
711 # Detect if kernel was built with clang.
712 unset LLVM
713 vbox_cc_is_clang=$(kernel_get_config_opt "CONFIG_CC_IS_CLANG")
714 if test "${vbox_cc_is_clang}" = "y"; then
715 log "Using clang compiler."
716 export LLVM=1
717 fi
718
719 if ! myerr=`$BUILDINTMP \
720 --save-module-symvers /tmp/vboxdrv-Module.symvers \
721 --module-source "$MODULE_SRC/vboxdrv" \
722 --no-print-directory install 2>&1`; then
723 "${INSTALL_DIR}/check_module_dependencies.sh" || exit 1
724 log "Error building the module:"
725 module_build_log "$myerr"
726 failure "Look at $LOG to find out what went wrong"
727 fi
728 log "Building the net filter module."
729 if ! myerr=`$BUILDINTMP \
730 --use-module-symvers /tmp/vboxdrv-Module.symvers \
731 --module-source "$MODULE_SRC/vboxnetflt" \
732 --no-print-directory install 2>&1`; then
733 log "Error building the module:"
734 module_build_log "$myerr"
735 failure "Look at $LOG to find out what went wrong"
736 fi
737 log "Building the net adapter module."
738 if ! myerr=`$BUILDINTMP \
739 --use-module-symvers /tmp/vboxdrv-Module.symvers \
740 --module-source "$MODULE_SRC/vboxnetadp" \
741 --no-print-directory install 2>&1`; then
742 log "Error building the module:"
743 module_build_log "$myerr"
744 failure "Look at $LOG to find out what went wrong"
745 fi
746 if test -e "$MODULE_SRC/vboxpci"; then
747 log "Building the PCI pass-through module."
748 if ! myerr=`$BUILDINTMP \
749 --use-module-symvers /tmp/vboxdrv-Module.symvers \
750 --module-source "$MODULE_SRC/vboxpci" \
751 --no-print-directory install 2>&1`; then
752 log "Error building the module:"
753 module_build_log "$myerr"
754 failure "Look at $LOG to find out what went wrong"
755 fi
756 fi
757 rm -f /etc/vbox/module_not_compiled
758 depmod -a
759 sync
760 succ_msg "VirtualBox kernel modules built"
761
762 # Sign kernel modules if kernel configuration requires it.
763 if test "$(kernel_requires_module_signature)" = "1"; then
764 begin_msg "Signing VirtualBox kernel modules" console
765
766 # Generate new signing key if needed.
767 [ -n "$HAVE_UPDATE_SECUREBOOT_POLICY_TOOL" ] && SHIM_NOTRIGGER=y update-secureboot-policy --new-key
768
769 # Check if signing keys are in place.
770 if test ! -f "$DEB_PUB_KEY" || ! test -f "$DEB_PRIV_KEY"; then
771 # update-secureboot-policy tool present in the system, but keys were not generated.
772 [ -n "$HAVE_UPDATE_SECUREBOOT_POLICY_TOOL" ] && fail_msg "
773
774update-secureboot-policy tool does not generate signing keys
775in your distribution, see below on how to generate them manually
776"
777
778 # update-secureboot-policy not present in the system, recommend generate keys manually.
779 failure "
780
781System is running in Secure Boot mode, however your distribution
782does not provide tools for automatic generation of keys needed for
783modules signing. Please consider to generate and enroll them manually:
784
785 sudo mkdir -p /var/lib/shim-signed/mok
786 sudo openssl req -nodes -new -x509 -newkey rsa:2048 -outform DER -addext \"extendedKeyUsage=codeSigning\" -keyout $DEB_PRIV_KEY -out $DEB_PUB_KEY
787 sudo mokutil --import $DEB_PUB_KEY
788 sudo reboot
789
790Restart \"rcvboxdrv setup\" after system is rebooted
791"
792 fi
793
794 # Check if signing tool is available.
795 [ -n "$SIGN_TOOL" ] || failure "Unable to find signing tool"
796
797 # Get kernel signature hash algorithm from kernel config and validate it.
798 sig_hashalgo=$(kernel_module_sig_hash)
799 [ "$(module_sig_hash_supported $sig_hashalgo)" = "1" ] \
800 || failure "Unsupported kernel signature hash algorithm $sig_hashalgo"
801
802 # Sign modules.
803 for i in $MODULE_LIST; do
804 "$SIGN_TOOL" "$sig_hashalgo" "$DEB_PRIV_KEY" "$DEB_PUB_KEY" \
805 /lib/modules/"$KERN_VER"/misc/"$i".ko 2>/dev/null || failure "Unable to sign $i.ko"
806 done
807
808 # Enroll signing key if needed.
809 if test -n "$HAVE_UPDATE_SECUREBOOT_POLICY_TOOL"; then
810 # update-secureboot-policy "expects" DKMS modules.
811 # Work around this and talk to the authors as soon
812 # as possible to fix it.
813 mkdir -p /var/lib/dkms/vbox-temp
814 update-secureboot-policy --enroll-key 2>/dev/null ||
815 begin_msg "Failed to enroll secure boot key." console
816 rmdir -p /var/lib/dkms/vbox-temp 2>/dev/null
817
818 # Indicate that key has been enrolled and reboot is needed.
819 HAVE_DEB_KEY=true
820 fi
821 succ_msg "Signing completed"
822 fi
823}
824
825dmnstatus()
826{
827 if running vboxdrv; then
828 str="vboxdrv"
829 if running vboxnetflt; then
830 str="$str, vboxnetflt"
831 if running vboxnetadp; then
832 str="$str, vboxnetadp"
833 fi
834 fi
835 if running vboxpci; then
836 str="$str, vboxpci"
837 fi
838 echo "VirtualBox kernel modules ($str) are loaded."
839 for i in $SHUTDOWN_USERS; do
840 # don't create the ipcd directory with wrong permissions!
841 if [ -d /tmp/.vbox-$i-ipc ]; then
842 export VBOX_IPC_SOCKETID="$i"
843 VMS=`$VBOXMANAGE --nologo list runningvms | sed -e 's/^".*".*{\(.*\)}/\1/' 2>/dev/null`
844 if [ -n "$VMS" ]; then
845 echo "The following VMs are currently running:"
846 for v in $VMS; do
847 echo " $v"
848 done
849 fi
850 fi
851 done
852 else
853 echo "VirtualBox kernel module is not loaded."
854 fi
855}
856
857case "$1" in
858start)
859 start
860 ;;
861stop)
862 stop_vms
863 stop
864 ;;
865stop_vms)
866 stop_vms
867 ;;
868restart)
869 stop && start
870 ;;
871setup)
872 test -n "${2}" && export KERN_VER="${2}"
873 # Create udev rule and USB device nodes.
874 ## todo Wouldn't it make more sense to install the rule to /lib/udev? This
875 ## is not a user-created configuration file after all.
876 ## todo Do we need a udev rule to create /dev/vboxdrv[u] at all? We have
877 ## working fall-back code here anyway, and the "right" code is more complex
878 ## than the fall-back. Unnecessary duplication?
879 stop && cleanup
880 setup_usb "$GROUP" "$DEVICE_MODE" "$INSTALL_DIR"
881 start
882 ;;
883cleanup)
884 stop && cleanup
885 cleanup_usb
886 ;;
887force-reload)
888 stop
889 start
890 ;;
891status)
892 dmnstatus
893 ;;
894*)
895 echo "Usage: $0 {start|stop|stop_vms|restart|setup|cleanup|force-reload|status}"
896 exit 1
897esac
898
899exit 0
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use