VirtualBox

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

Last change on this file was 104246, checked in by vboxsync, 3 weeks ago

Installer/linux/vboxdrv.sh: VirtualBox was split a while back, so use VirtualBoxVM for testing for the set-uid-to-root/hardening stuff. bugref:10642

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

© 2023 Oracle
ContactPrivacy policyTerms of Use