VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/installer/vboxadd.sh@ 99511

Last change on this file since 99511 was 99511, checked in by vboxsync, 20 months ago

Additions: Linux: rcvboxadd: corrected path to rcvboxadd-service, bugref:10359.

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 39.2 KB
Line 
1#! /bin/sh
2# $Id: vboxadd.sh 99511 2023-04-21 18:12:13Z vboxsync $
3## @file
4# Linux Additions kernel module init script ($Revision: 99511 $)
5#
6
7#
8# Copyright (C) 2006-2023 Oracle and/or its affiliates.
9#
10# This file is part of VirtualBox base platform packages, as
11# available from https://www.virtualbox.org.
12#
13# This program is free software; you can redistribute it and/or
14# modify it under the terms of the GNU General Public License
15# as published by the Free Software Foundation, in version 3 of the
16# License.
17#
18# This program is distributed in the hope that it will be useful, but
19# WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21# General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, see <https://www.gnu.org/licenses>.
25#
26# SPDX-License-Identifier: GPL-3.0-only
27#
28
29# X-Start-Before is a Debian Addition which we use when converting to
30# a systemd unit. X-Service-Type is our own invention, also for systemd.
31
32# chkconfig: 345 10 90
33# description: VirtualBox Linux Additions kernel modules
34#
35### BEGIN INIT INFO
36# Provides: vboxadd
37# Required-Start:
38# Required-Stop:
39# Default-Start: 2 3 4 5
40# Default-Stop: 0 1 6
41# X-Start-Before: display-manager
42# X-Service-Type: oneshot
43# Description: VirtualBox Linux Additions kernel modules
44### END INIT INFO
45
46## @todo This file duplicates a lot of script with vboxdrv.sh. When making
47# changes please try to reduce differences between the two wherever possible.
48
49# Testing:
50# * Should fail if the configuration file is missing or missing INSTALL_DIR or
51# INSTALL_VER entries.
52# * vboxadd, vboxsf and vboxdrmipc user groups should be created if they do not exist - test
53# by removing them before installing.
54# * Shared folders can be mounted and auto-mounts accessible to vboxsf group,
55# including on recent Fedoras with SELinux.
56# * Setting INSTALL_NO_MODULE_BUILDS inhibits modules and module automatic
57# rebuild script creation; otherwise modules, user, group, rebuild script,
58# udev rule and shared folder mount helper should be created/set up.
59# * Setting INSTALL_NO_MODULE_BUILDS inhibits module load and unload on start
60# and stop.
61# * Uninstalling the Additions and re-installing them does not trigger warnings.
62
63export LC_ALL=C
64PATH=$PATH:/bin:/sbin:/usr/sbin
65PACKAGE=VBoxGuestAdditions
66MODPROBE=/sbin/modprobe
67OLDMODULES="vboxguest vboxadd vboxsf vboxvfs vboxvideo"
68SERVICE="VirtualBox Guest Additions"
69## systemd logs information about service status, otherwise do that ourselves.
70QUIET=
71test -z "${TARGET_VER}" && TARGET_VER=`uname -r`
72
73export VBOX_KBUILD_TYPE
74export USERNAME
75
76setup_log()
77{
78 test -z "${LOG}" || return 0
79 # Rotate log files
80 LOG="/var/log/vboxadd-setup.log"
81 mv -f "${LOG}.3" "${LOG}.4" 2>/dev/null
82 mv -f "${LOG}.2" "${LOG}.3" 2>/dev/null
83 mv -f "${LOG}.1" "${LOG}.2" 2>/dev/null
84 mv -f "${LOG}" "${LOG}.1" 2>/dev/null
85}
86
87if $MODPROBE -c 2>/dev/null | grep -q '^allow_unsupported_modules *0'; then
88 MODPROBE="$MODPROBE --allow-unsupported-modules"
89fi
90
91# Preamble for Gentoo
92if [ "`which $0`" = "/sbin/rc" ]; then
93 shift
94fi
95
96begin()
97{
98 test -n "${QUIET}" || echo "${SERVICE}: ${1}"
99}
100
101info()
102{
103 if test -z "${QUIET}"; then
104 echo "${SERVICE}: $1" | fold -s
105 else
106 echo "$1" | fold -s
107 fi
108}
109
110# When script is running as non-root, it does not have access to log
111# files in /var. In this case, lets print error message to stdout and
112# exit with bad status.
113early_fail()
114{
115 echo "$1" >&2
116 exit 1
117}
118
119fail()
120{
121 log "${1}"
122 echo "$1" >&2
123 echo "The log file $LOG may contain further information." >&2
124 exit 1
125}
126
127log()
128{
129 setup_log
130 echo "${1}" >> "${LOG}"
131}
132
133module_build_log()
134{
135 log "Error building the module. Build output follows."
136 echo ""
137 echo "${1}" >> "${LOG}"
138}
139
140dev=/dev/vboxguest
141userdev=/dev/vboxuser
142config=/var/lib/VBoxGuestAdditions/config
143user_config=/etc/virtualbox-guest-additions.conf
144owner=vboxadd
145group=1
146
147# Include custom user configuration file.
148[ -r "$user_config" ] && . "$user_config"
149
150if test -r $config; then
151 . $config
152else
153 fail "Configuration file $config not found"
154fi
155test -n "$INSTALL_DIR" -a -n "$INSTALL_VER" ||
156 fail "Configuration file $config not complete"
157MODULE_SRC="$INSTALL_DIR/src/vboxguest-$INSTALL_VER"
158BUILDINTMP="$MODULE_SRC/build_in_tmp"
159
160# Path to VBoxService control script.
161VBOX_SERVICE_SCRIPT="/sbin/rcvboxadd-service"
162
163# Attempt to detect VirtualBox Guest Additions version and revision information.
164VBOXCONTROL="${INSTALL_DIR}/bin/VBoxControl"
165VBOX_VERSION="`"$VBOXCONTROL" --version | cut -d r -f1`"
166[ -n "$VBOX_VERSION" ] || VBOX_VERSION='unknown'
167VBOX_REVISION="r`"$VBOXCONTROL" --version | cut -d r -f2`"
168[ "$VBOX_REVISION" != "r" ] || VBOX_REVISION='unknown'
169
170# Returns if the vboxguest module is running or not.
171#
172# Returns true if vboxguest module is running, false if not.
173running_vboxguest()
174{
175 lsmod | grep -q "vboxguest[^_-]"
176}
177
178# Returns if the vboxadd module is running or not.
179#
180# Returns true if vboxadd module is running, false if not.
181running_vboxadd()
182{
183 lsmod | grep -q "vboxadd[^_-]"
184}
185
186# Returns if the vboxsf module is running or not.
187#
188# Returns true if vboxsf module is running, false if not.
189running_vboxsf()
190{
191 lsmod | grep -q "vboxsf[^_-]"
192}
193
194# Returns if the vboxvideo module is running or not.
195#
196# Returns true if vboxvideo module is running, false if not.
197running_vboxvideo()
198{
199 lsmod | grep -q "vboxvideo[^_-]"
200}
201
202# Returns if a specific module is running or not.
203#
204# Input $1: Module name to check running status for.
205#
206# Returns true if the module is running, false if not.
207running_module()
208{
209 lsmod | grep -q "$1"
210}
211
212# Returns the version string of a currently running kernel module.
213#
214# Input $1: Module name to check.
215#
216# Returns the module version string if found, or none if not found.
217running_module_version()
218{
219 mod="$1"
220 version_string_path="/sys/module/"$mod"/version"
221
222 [ -n "$mod" ] || return
223 if [ -r "$version_string_path" ]; then
224 cat "$version_string_path"
225 else
226 echo "unknown"
227 fi
228}
229
230# Checks if a loaded kernel module version matches to the currently installed Guest Additions version and revision.
231#
232# Input $1: Module name to check.
233#
234# Returns "1" if the module matches the installed Guest Additions, or none if not.
235check_running_module_version()
236{
237 mod=$1
238 expected="$VBOX_VERSION $VBOX_REVISION"
239
240 [ -n "$mod" ] || return
241 [ -n "$expected" ] || return
242
243 [ "$expected" = "$(running_module_version "$mod")" ] || return
244}
245
246do_vboxguest_non_udev()
247{
248 if [ ! -c $dev ]; then
249 maj=`sed -n 's;\([0-9]\+\) vboxguest;\1;p' /proc/devices`
250 if [ ! -z "$maj" ]; then
251 min=0
252 else
253 min=`sed -n 's;\([0-9]\+\) vboxguest;\1;p' /proc/misc`
254 if [ ! -z "$min" ]; then
255 maj=10
256 fi
257 fi
258 test -n "$maj" || {
259 rmmod vboxguest 2>/dev/null
260 fail "Cannot locate the VirtualBox device"
261 }
262
263 mknod -m 0664 $dev c $maj $min || {
264 rmmod vboxguest 2>/dev/null
265 fail "Cannot create device $dev with major $maj and minor $min"
266 }
267 fi
268 chown $owner:$group $dev 2>/dev/null || {
269 rm -f $dev 2>/dev/null
270 rm -f $userdev 2>/dev/null
271 rmmod vboxguest 2>/dev/null
272 fail "Cannot change owner $owner:$group for device $dev"
273 }
274
275 if [ ! -c $userdev ]; then
276 maj=10
277 min=`sed -n 's;\([0-9]\+\) vboxuser;\1;p' /proc/misc`
278 if [ ! -z "$min" ]; then
279 mknod -m 0666 $userdev c $maj $min || {
280 rm -f $dev 2>/dev/null
281 rmmod vboxguest 2>/dev/null
282 fail "Cannot create device $userdev with major $maj and minor $min"
283 }
284 chown $owner:$group $userdev 2>/dev/null || {
285 rm -f $dev 2>/dev/null
286 rm -f $userdev 2>/dev/null
287 rmmod vboxguest 2>/dev/null
288 fail "Cannot change owner $owner:$group for device $userdev"
289 }
290 fi
291 fi
292}
293
294restart()
295{
296 stop && start
297 return 0
298}
299
300## Updates the initramfs. Debian and Ubuntu put the graphics driver in, and
301# need the touch(1) command below. Everyone else that I checked just need
302# the right module alias file from depmod(1) and only use the initramfs to
303# load the root filesystem, not the boot splash. update-initramfs works
304# for the first two and dracut for every one else I checked. We are only
305# interested in distributions recent enough to use the KMS vboxvideo driver.
306update_initramfs()
307{
308 ## kernel version to update for.
309 version="${1}"
310 depmod "${version}"
311 rm -f "/lib/modules/${version}/initrd/vboxvideo"
312 test ! -d "/lib/modules/${version}/initrd" ||
313 test ! -f "/lib/modules/${version}/misc/vboxvideo.ko" ||
314 touch "/lib/modules/${version}/initrd/vboxvideo"
315
316 # Systems without systemd-inhibit probably don't need their initramfs
317 # rebuild here anyway.
318 type systemd-inhibit >/dev/null 2>&1 || return
319 if type dracut >/dev/null 2>&1; then
320 systemd-inhibit --why="Installing VirtualBox Guest Additions" \
321 dracut -f --kver "${version}"
322 elif type update-initramfs >/dev/null 2>&1; then
323 systemd-inhibit --why="Installing VirtualBox Guest Additions" \
324 update-initramfs -u -k "${version}"
325 fi
326}
327
328# Removes any existing VirtualBox guest kernel modules from the disk, but not
329# from the kernel as they may still be in use
330cleanup_modules()
331{
332 # Needed for Ubuntu and Debian, see update_initramfs
333 rm -f /lib/modules/*/initrd/vboxvideo
334 for i in /lib/modules/*/misc; do
335 KERN_VER="${i%/misc}"
336 KERN_VER="${KERN_VER#/lib/modules/}"
337 unset do_update
338 for j in ${OLDMODULES}; do
339 for mod_ext in ko ko.gz ko.xz ko.zst; do
340 test -f "${i}/${j}.${mod_ext}" && do_update=1 && rm -f "${i}/${j}.${mod_ext}"
341 done
342 done
343 test -z "$do_update" || update_initramfs "$KERN_VER"
344 # Remove empty /lib/modules folders which may have been kept around
345 rmdir -p "${i}" 2>/dev/null || true
346 unset keep
347 for j in /lib/modules/"${KERN_VER}"/*; do
348 name="${j##*/}"
349 test -d "${name}" || test "${name%%.*}" != modules && keep=1
350 done
351 if test -z "${keep}"; then
352 rm -rf /lib/modules/"${KERN_VER}"
353 rm -f /boot/initrd.img-"${KERN_VER}"
354 fi
355 done
356 for i in ${OLDMODULES}; do
357 # We no longer support DKMS, remove any leftovers.
358 rm -rf "/var/lib/dkms/${i}"*
359 done
360 rm -f /etc/depmod.d/vboxvideo-upstream.conf
361}
362
363# Secure boot state.
364case "`mokutil --sb-state 2>/dev/null`" in
365 *"disabled in shim"*) unset HAVE_SEC_BOOT;;
366 *"SecureBoot enabled"*) HAVE_SEC_BOOT=true;;
367 *) unset HAVE_SEC_BOOT;;
368esac
369# So far we can only sign modules on Ubuntu and on Debian 10 and later.
370DEB_PUB_KEY=/var/lib/shim-signed/mok/MOK.der
371DEB_PRIV_KEY=/var/lib/shim-signed/mok/MOK.priv
372# Check if key already enrolled.
373unset HAVE_DEB_KEY
374case "`mokutil --test-key "$DEB_PUB_KEY" 2>/dev/null`" in
375 *"is already"*) DEB_KEY_ENROLLED=true;;
376 *) unset DEB_KEY_ENROLLED;;
377esac
378
379# Checks if update-secureboot-policy tool supports required commandline options.
380update_secureboot_policy_supports()
381{
382 opt_name="$1"
383 [ -n "$opt_name" ] || return
384
385 [ -z "$(update-secureboot-policy --help 2>&1 | grep "$opt_name")" ] && return
386 echo "1"
387}
388
389HAVE_UPDATE_SECUREBOOT_POLICY_TOOL=
390if type update-secureboot-policy >/dev/null 2>&1; then
391 [ "$(update_secureboot_policy_supports new-key)" = "1" -a "$(update_secureboot_policy_supports enroll-key)" = "1" ] && \
392 HAVE_UPDATE_SECUREBOOT_POLICY_TOOL=true
393fi
394
395# Reads kernel configuration option.
396kernel_get_config_opt()
397{
398 opt_name="$1"
399 [ -n "$opt_name" ] || return
400
401 # Check if there is a kernel tool which can extract config option.
402 if test -x /lib/modules/"$KERN_VER"/build/scripts/config; then
403 /lib/modules/"$KERN_VER"/build/scripts/config \
404 --file /lib/modules/"$KERN_VER"/build/.config \
405 --state "$opt_name" 2>/dev/null
406 elif test -f /lib/modules/"$KERN_VER"/build/.config; then
407 # Extract config option manually.
408 grep "$opt_name" /lib/modules/"$KERN_VER"/build/.config | sed -e "s/^$opt_name=//" -e "s/\"//g"
409 fi
410}
411
412# Reads CONFIG_MODULE_SIG_HASH from kernel config.
413kernel_module_sig_hash()
414{
415 kernel_get_config_opt "CONFIG_MODULE_SIG_HASH"
416}
417
418# Returns "1" if kernel module signature hash algorithm
419# is supported by us. Or empty string otherwise.
420module_sig_hash_supported()
421{
422 sig_hashalgo="$1"
423 [ -n "$sig_hashalgo" ] || return
424
425 # Go through supported list.
426 [ "$sig_hashalgo" = "sha1" \
427 -o "$sig_hashalgo" = "sha224" \
428 -o "$sig_hashalgo" = "sha256" \
429 -o "$sig_hashalgo" = "sha384" \
430 -o "$sig_hashalgo" = "sha512" ] || return
431
432 echo "1"
433}
434
435sign_modules()
436{
437 KERN_VER="$1"
438 test -n "$KERN_VER" || return 1
439
440 # Make list of mudules to sign.
441 MODULE_LIST="vboxguest vboxsf"
442 # vboxvideo might not present on for older kernels.
443 [ -f "/lib/modules/"$KERN_VER"/misc/vboxvideo.ko" ] && MODULE_LIST="$MODULE_LIST vboxvideo"
444
445 # Secure boot on Ubuntu, Debian and Oracle Linux.
446 if test -n "$HAVE_SEC_BOOT"; then
447 begin "Signing VirtualBox Guest Additions kernel modules"
448
449 # Generate new signing key if needed.
450 [ -n "$HAVE_UPDATE_SECUREBOOT_POLICY_TOOL" ] && SHIM_NOTRIGGER=y update-secureboot-policy --new-key
451
452 # Check if signing keys are in place.
453 if test ! -f "$DEB_PUB_KEY" || ! test -f "$DEB_PRIV_KEY"; then
454 # update-secureboot-policy tool present in the system, but keys were not generated.
455 [ -n "$HAVE_UPDATE_SECUREBOOT_POLICY_TOOL" ] && info "
456
457update-secureboot-policy tool does not generate signing keys
458in your distribution, see below on how to generate them manually."
459 # update-secureboot-policy not present in the system, recommend generate keys manually.
460 fail "
461
462System is running in Secure Boot mode, however your distribution
463does not provide tools for automatic generation of keys needed for
464modules signing. Please consider to generate and enroll them manually:
465
466 sudo mkdir -p /var/lib/shim-signed/mok
467 sudo openssl req -nodes -new -x509 -newkey rsa:2048 -outform DER -addext \"extendedKeyUsage=codeSigning\" -keyout $DEB_PRIV_KEY -out $DEB_PUB_KEY
468 sudo mokutil --import $DEB_PUB_KEY
469 sudo reboot
470
471Restart \"rcvboxadd setup\" after system is rebooted.
472"
473 fi
474
475 # Get kernel signature hash algorithm from kernel config and validate it.
476 sig_hashalgo=$(kernel_module_sig_hash)
477 [ "$(module_sig_hash_supported $sig_hashalgo)" = "1" ] \
478 || fail "Unsupported kernel signature hash algorithm $sig_hashalgo"
479
480 # Sign modules.
481 for i in $MODULE_LIST; do
482
483 # Try to find a tool for modules signing.
484 SIGN_TOOL=$(which kmodsign 2>/dev/null)
485 # Attempt to use in-kernel signing tool if kmodsign not found.
486 if test -z "$SIGN_TOOL"; then
487 if test -x "/lib/modules/$KERN_VER/build/scripts/sign-file"; then
488 SIGN_TOOL="/lib/modules/$KERN_VER/build/scripts/sign-file"
489 fi
490 fi
491
492 # Check if signing tool is available.
493 [ -n "$SIGN_TOOL" ] || fail "Unable to find signing tool"
494
495 "$SIGN_TOOL" "$sig_hashalgo" "$DEB_PRIV_KEY" "$DEB_PUB_KEY" \
496 /lib/modules/"$KERN_VER"/misc/"$i".ko || fail "Unable to sign $i.ko"
497 done
498 # Enroll signing key if needed.
499 if test -n "$HAVE_UPDATE_SECUREBOOT_POLICY_TOOL"; then
500 # update-secureboot-policy "expects" DKMS modules.
501 # Work around this and talk to the authors as soon
502 # as possible to fix it.
503 mkdir -p /var/lib/dkms/vbox-temp
504 update-secureboot-policy --enroll-key 2>/dev/null ||
505 fail "Failed to enroll secure boot key."
506 rmdir -p /var/lib/dkms/vbox-temp 2>/dev/null
507
508 # Indicate that key has been enrolled and reboot is needed.
509 HAVE_DEB_KEY=true
510 fi
511 fi
512}
513
514# Build and install the VirtualBox guest kernel modules
515setup_modules()
516{
517 KERN_VER="$1"
518 test -n "$KERN_VER" || return 1
519 # Match (at least): vboxguest.o; vboxguest.ko; vboxguest.ko.xz
520 set /lib/modules/"$KERN_VER"/misc/vboxguest.*o*
521 #test ! -f "$1" || return 0
522 test -d /lib/modules/"$KERN_VER"/build || return 0
523 export KERN_VER
524 info "Building the modules for kernel $KERN_VER."
525
526 # Prepend PATH for building UEK7 on OL8 distribution.
527 case "$KERN_VER" in
528 5.15.0-*.el8uek*) PATH="/opt/rh/gcc-toolset-11/root/usr/bin:$PATH";;
529 esac
530
531 # Detect if kernel was built with clang.
532 unset LLVM
533 vbox_cc_is_clang=$(kernel_get_config_opt "CONFIG_CC_IS_CLANG")
534 if test "${vbox_cc_is_clang}" = "y"; then
535 info "Using clang compiler."
536 export LLVM=1
537 fi
538
539 log "Building the main Guest Additions $INSTALL_VER module for kernel $KERN_VER."
540 if ! myerr=`$BUILDINTMP \
541 --save-module-symvers /tmp/vboxguest-Module.symvers \
542 --module-source $MODULE_SRC/vboxguest \
543 --no-print-directory install 2>&1`; then
544 # If check_module_dependencies.sh fails it prints a message itself.
545 module_build_log "$myerr"
546 "${INSTALL_DIR}"/other/check_module_dependencies.sh 2>&1 &&
547 info "Look at $LOG to find out what went wrong"
548 return 0
549 fi
550 log "Building the shared folder support module."
551 if ! myerr=`$BUILDINTMP \
552 --use-module-symvers /tmp/vboxguest-Module.symvers \
553 --module-source $MODULE_SRC/vboxsf \
554 --no-print-directory install 2>&1`; then
555 module_build_log "$myerr"
556 info "Look at $LOG to find out what went wrong"
557 return 0
558 fi
559 log "Building the graphics driver module."
560 if ! myerr=`$BUILDINTMP \
561 --use-module-symvers /tmp/vboxguest-Module.symvers \
562 --module-source $MODULE_SRC/vboxvideo \
563 --no-print-directory install 2>&1`; then
564 module_build_log "$myerr"
565 info "Look at $LOG to find out what went wrong"
566 fi
567 [ -d /etc/depmod.d ] || mkdir /etc/depmod.d
568 echo "override vboxguest * misc" > /etc/depmod.d/vboxvideo-upstream.conf
569 echo "override vboxsf * misc" >> /etc/depmod.d/vboxvideo-upstream.conf
570 echo "override vboxvideo * misc" >> /etc/depmod.d/vboxvideo-upstream.conf
571
572 sign_modules "${KERN_VER}"
573
574 update_initramfs "${KERN_VER}"
575
576 return 0
577}
578
579create_vbox_user()
580{
581 # This is the LSB version of useradd and should work on recent
582 # distributions
583 useradd -d /var/run/vboxadd -g 1 -r -s /bin/false vboxadd >/dev/null 2>&1 || true
584 # And for the others, we choose a UID ourselves
585 useradd -d /var/run/vboxadd -g 1 -u 501 -o -s /bin/false vboxadd >/dev/null 2>&1 || true
586
587}
588
589create_udev_rule()
590{
591 # Create udev description file
592 if [ -d /etc/udev/rules.d ]; then
593 udev_call=""
594 udev_app=`which udevadm 2> /dev/null`
595 if [ $? -eq 0 ]; then
596 udev_call="${udev_app} version 2> /dev/null"
597 else
598 udev_app=`which udevinfo 2> /dev/null`
599 if [ $? -eq 0 ]; then
600 udev_call="${udev_app} -V 2> /dev/null"
601 fi
602 fi
603 udev_fix="="
604 if [ "${udev_call}" != "" ]; then
605 udev_out=`${udev_call}`
606 udev_ver=`expr "$udev_out" : '[^0-9]*\([0-9]*\)'`
607 if [ "$udev_ver" = "" -o "$udev_ver" -lt 55 ]; then
608 udev_fix=""
609 fi
610 fi
611 ## @todo 60-vboxadd.rules -> 60-vboxguest.rules ?
612 echo "KERNEL=${udev_fix}\"vboxguest\", NAME=\"vboxguest\", OWNER=\"vboxadd\", MODE=\"0660\"" > /etc/udev/rules.d/60-vboxadd.rules
613 echo "KERNEL=${udev_fix}\"vboxuser\", NAME=\"vboxuser\", OWNER=\"vboxadd\", MODE=\"0666\"" >> /etc/udev/rules.d/60-vboxadd.rules
614 # Make sure the new rule is noticed.
615 udevadm control --reload >/dev/null 2>&1 || true
616 udevcontrol reload_rules >/dev/null 2>&1 || true
617 fi
618}
619
620create_module_rebuild_script()
621{
622 # And a post-installation script for rebuilding modules when a new kernel
623 # is installed.
624 mkdir -p /etc/kernel/postinst.d /etc/kernel/prerm.d
625 cat << EOF > /etc/kernel/postinst.d/vboxadd
626#!/bin/sh
627# This only works correctly on Debian derivatives - Red Hat calls it before
628# installing the right header files.
629/sbin/rcvboxadd quicksetup "\${1}"
630exit 0
631EOF
632 cat << EOF > /etc/kernel/prerm.d/vboxadd
633#!/bin/sh
634for i in ${OLDMODULES}; do rm -f /lib/modules/"\${1}"/misc/"\${i}".ko; done
635rmdir -p /lib/modules/"\$1"/misc 2>/dev/null || true
636exit 0
637EOF
638 chmod 0755 /etc/kernel/postinst.d/vboxadd /etc/kernel/prerm.d/vboxadd
639}
640
641shared_folder_setup()
642{
643 # Add a group "vboxsf" for Shared Folders access
644 # All users which want to access the auto-mounted Shared Folders have to
645 # be added to this group.
646 groupadd -r -f vboxsf >/dev/null 2>&1
647
648 # Put the mount.vboxsf mount helper in the right place.
649 ## @todo It would be nicer if the kernel module just parsed parameters
650 # itself instead of needing a separate binary to do that.
651 ln -sf "${INSTALL_DIR}/other/mount.vboxsf" /sbin
652 # SELinux security context for the mount helper.
653 if test -e /etc/selinux/config; then
654 # This is correct. semanage maps this to the real path, and it aborts
655 # with an error, telling you what you should have typed, if you specify
656 # the real path. The "chcon" is there as a back-up for old guests.
657 command -v semanage > /dev/null &&
658 semanage fcontext -a -t mount_exec_t "${INSTALL_DIR}/other/mount.vboxsf"
659 chcon -t mount_exec_t "${INSTALL_DIR}/other/mount.vboxsf" 2>/dev/null
660 fi
661}
662
663# Returns path to a module file as seen by modinfo(8), or none if not found.
664#
665# Input $1: Module name to get path for.
666#
667# Returns the module path as a string.
668module_path()
669{
670 mod="$1"
671 [ -n "$mod" ] || return
672
673 modinfo "$mod" 2>/dev/null | grep -e "^filename:" | tr -s ' ' | cut -d " " -f2
674}
675
676# Returns module version if module is available, or none if not found.
677#
678# Input $1: Module name to get version for.
679#
680# Returns the module version as a string.
681module_version()
682{
683 mod="$1"
684 [ -n "$mod" ] || return
685
686 modinfo "$mod" 2>/dev/null | grep -e "^version:" | tr -s ' ' | cut -d " " -f2
687}
688
689# Returns the module revision if module is available in the system, or none if not found.
690#
691# Input $1: Module name to get revision for.
692#
693# Returns the module revision as a string.
694module_revision()
695{
696 mod="$1"
697 [ -n "$mod" ] || return
698
699 modinfo "$mod" 2>/dev/null | grep -e "^version:" | tr -s ' ' | cut -d " " -f3
700}
701
702# Checks if a given kernel module is properly signed or not.
703#
704# Input $1: Module name to check.
705#
706# Returns "1" if module is signed and signature can be verified
707# with public key provided in DEB_PUB_KEY, or none otherwise.
708module_signed()
709{
710 mod="$1"
711 [ -n "$mod" ] || return
712
713 # Be nice with distributions which do not provide tools which we
714 # use in order to verify module signature. This variable needs to
715 # be explicitly set by administrator. This script will look for it
716 # in /etc/virtualbox-guest-additions.conf. Make sure that you know
717 # what you do!
718 if [ "$VBOX_BYPASS_MODULES_SIGNATURE_CHECK" = "1" ]; then
719 echo "1"
720 return
721 fi
722
723 extraction_tool=/lib/modules/"$(uname -r)"/build/scripts/extract-module-sig.pl
724 mod_path=$(module_path "$mod" 2>/dev/null)
725 openssl_tool=$(which openssl 2>/dev/null)
726 # Do not use built-in printf!
727 printf_tool=$(which printf 2>/dev/null)
728
729 # Make sure all the tools required for signature validation are available.
730 [ -x "$extraction_tool" ] || return
731 [ -n "$mod_path" ] || return
732 [ -n "$openssl_tool" ] || return
733 [ -n "$printf_tool" ] || return
734
735 # Make sure openssl can handle hash algorithm.
736 sig_hashalgo=$(modinfo -F sig_hashalgo "$mod" 2>/dev/null)
737 [ "$(module_sig_hash_supported $sig_hashalgo)" = "1" ] || return
738
739 # Generate file names for temporary stuff.
740 mod_pub_key=$(mktemp -u)
741 mod_signature=$(mktemp -u)
742 mod_unsigned=$(mktemp -u)
743
744 # Convert public key in DER format into X509 certificate form.
745 "$openssl_tool" x509 -pubkey -inform DER -in "$DEB_PUB_KEY" -out "$mod_pub_key" 2>/dev/null
746 # Extract raw module signature and convert it into binary format.
747 "$printf_tool" \\x$(modinfo -F signature "$mod" | sed -z 's/[ \t\n]//g' | sed -e "s/:/\\\x/g") 2>/dev/null > "$mod_signature"
748 # Extract unsigned module for further digest calculation.
749 "$extraction_tool" -0 "$mod_path" 2>/dev/null > "$mod_unsigned"
750
751 # Verify signature.
752 rc=""
753 "$openssl_tool" dgst "-$sig_hashalgo" -binary -verify "$mod_pub_key" -signature "$mod_signature" "$mod_unsigned" 2>&1 >/dev/null && rc="1"
754 # Clean up.
755 rm -f $mod_pub_key $mod_signature $mod_unsigned
756
757 # Check result.
758 [ "$rc" = "1" ] || return
759
760 echo "1"
761}
762
763# Checks if a given kernel module matches the installed VirtualBox Guest Additions version.
764#
765# Input $1: Module name to check.
766#
767# Returns "1" if externally built module is available in the system and its
768# version and revision number do match to current VirtualBox installation.
769# None otherwise.
770module_available()
771{
772 mod="$1"
773 [ -n "$mod" ] || return
774
775 [ "$VBOX_VERSION" = "$(module_version "$mod")" ] || return
776 [ "$VBOX_REVISION" = "$(module_revision "$mod")" ] || return
777
778 # Check if module belongs to VirtualBox installation.
779 #
780 # We have a convention that only modules from /lib/modules/*/misc
781 # belong to us. Modules from other locations are treated as
782 # externally built.
783 mod_path="$(module_path "$mod")"
784
785 # If module path points to a symbolic link, resolve actual file location.
786 [ -L "$mod_path" ] && mod_path="$(readlink -e -- "$mod_path")"
787
788 # File exists?
789 [ -f "$mod_path" ] || return
790
791 # Extract last component of module path and check whether it is located
792 # outside of /lib/modules/*/misc.
793 mod_dir="$(dirname "$mod_path" | sed 's;^.*/;;')"
794 [ "$mod_dir" = "misc" ] || return
795
796 # In case if system is running in Secure Boot mode, check if module is signed.
797 if test -n "$HAVE_SEC_BOOT"; then
798 [ "$(module_signed "$mod")" = "1" ] || return
799 fi
800
801 echo "1"
802}
803
804# Check if required modules are installed in the system and versions match.
805#
806# Returns "1" on success, none otherwise.
807setup_complete()
808{
809 [ "$(module_available vboxguest)" = "1" ] || return
810 [ "$(module_available vboxsf)" = "1" ] || return
811
812 # All modules are in place.
813 echo "1"
814}
815
816# setup_script
817setup()
818{
819 info "Setting up modules"
820
821 # chcon is needed on old Fedora/Redhat systems. No one remembers which.
822 test ! -e /etc/selinux/config ||
823 chcon -t bin_t "$BUILDINTMP" 2>/dev/null
824
825 if test -z "$INSTALL_NO_MODULE_BUILDS"; then
826 # Check whether modules setup is already complete for currently running kernel.
827 # Prevent unnecessary rebuilding in order to speed up booting process.
828 if test "$(setup_complete)" = "1"; then
829 info "VirtualBox Guest Additions kernel modules $VBOX_VERSION $VBOX_REVISION are \
830already available for kernel $TARGET_VER and do not require to be rebuilt."
831 else
832 info "Building the VirtualBox Guest Additions kernel modules. This may take a while."
833 info "To build modules for other installed kernels, run"
834 info " /sbin/rcvboxadd quicksetup <version>"
835 info "or"
836 info " /sbin/rcvboxadd quicksetup all"
837 if test -d /lib/modules/"$TARGET_VER"/build; then
838 setup_modules "$TARGET_VER"
839 depmod
840 else
841 info "Kernel headers not found for target kernel $TARGET_VER. \
842Please install them and execute
843 /sbin/rcvboxadd setup"
844 fi
845 fi
846 fi
847 create_vbox_user
848 create_udev_rule
849 test -n "${INSTALL_NO_MODULE_BUILDS}" || create_module_rebuild_script
850 shared_folder_setup
851 # Create user group which will have permissive access to DRP IPC server socket.
852 groupadd -r -f vboxdrmipc >/dev/null 2>&1
853
854 if running_vboxguest || running_vboxadd; then
855 # Only warn user if currently loaded modules version do not match Guest Additions Installation.
856 check_running_module_version "vboxguest" || info "Running kernel modules will not be replaced until the system is restarted or 'rcvboxadd reload' triggered"
857 fi
858
859 # Put the X.Org driver in place. This is harmless if it is not needed.
860 # Also set up the OpenGL library.
861 myerr=`"${INSTALL_DIR}/init/vboxadd-x11" setup 2>&1`
862 test -z "${myerr}" || log "${myerr}"
863
864 return 0
865}
866
867# cleanup_script
868cleanup()
869{
870 if test -z "${INSTALL_NO_MODULE_BUILDS}"; then
871 # Delete old versions of VBox modules.
872 cleanup_modules
873 depmod
874
875 # Remove old module sources
876 for i in $OLDMODULES; do
877 rm -rf /usr/src/$i-*
878 done
879 fi
880
881 # Clean-up X11-related bits
882 "${INSTALL_DIR}/init/vboxadd-x11" cleanup
883
884 # Remove other files
885 if test -z "${INSTALL_NO_MODULE_BUILDS}"; then
886 rm -f /etc/kernel/postinst.d/vboxadd /etc/kernel/prerm.d/vboxadd
887 rmdir -p /etc/kernel/postinst.d /etc/kernel/prerm.d 2>/dev/null || true
888 fi
889 rm -f /sbin/mount.vboxsf 2>/dev/null
890 rm -f /etc/udev/rules.d/60-vboxadd.rules 2>/dev/null
891 udevadm control --reload >/dev/null 2>&1 || true
892 udevcontrol reload_rules >/dev/null 2>&1 || true
893}
894
895start()
896{
897 begin "Starting."
898
899 # Check if kernel modules for currently running kernel are ready
900 # and rebuild them if needed.
901 test "$(setup_complete)" = "1" || setup
902
903 # Warn if Secure Boot setup not yet complete.
904 if test -n "$HAVE_SEC_BOOT" && test -z "$DEB_KEY_ENROLLED"; then
905 if test -n "$HAVE_DEB_KEY"; then
906 info "You must re-start your system to finish secure boot set-up."
907 else
908 info "You must sign vboxguest, vboxsf and
909vboxvideo (if present) kernel modules before using
910VirtualBox Guest Additions. See the documentation
911for your Linux distribution."
912 fi
913 fi
914
915 if test -z "${INSTALL_NO_MODULE_BUILDS}"; then
916 test -d /sys &&
917 ps -A -o comm | grep -q '/*udevd$' 2>/dev/null ||
918 no_udev=1
919 check_running_module_version "vboxguest" || {
920 rm -f $dev || {
921 fail "Cannot remove $dev"
922 }
923 rm -f $userdev || {
924 fail "Cannot remove $userdev"
925 }
926 # Assuming modules were just (re-)built, try to reload everything.
927 reload
928 }
929 case "$no_udev" in 1)
930 do_vboxguest_non_udev;;
931 esac
932 fi # INSTALL_NO_MODULE_BUILDS
933
934 return 0
935}
936
937stop()
938{
939 begin "Stopping."
940
941 if test -r /etc/ld.so.conf.d/00vboxvideo.conf; then
942 rm /etc/ld.so.conf.d/00vboxvideo.conf
943 ldconfig
944 fi
945 if ! umount -a -t vboxsf 2>/dev/null; then
946 # Make sure we only fail, if there are truly no more vboxsf
947 # mounts in the system.
948 [ -n "$(findmnt -t vboxsf)" ] && fail "Cannot unmount vboxsf folders"
949 fi
950 test -n "${INSTALL_NO_MODULE_BUILDS}" ||
951 info "You may need to restart your guest system to finish removing guest drivers or consider running 'rcvboxadd reload'."
952 return 0
953}
954
955check_root()
956{
957 # Check if script is running with root privileges and exit if it does not.
958 [ `id -u` -eq 0 ] || early_fail "root privileges are required"
959}
960
961# Check if process with this PID is running.
962check_pid()
963{
964 pid=$1
965
966 test -n "$pid" -a -d "/proc/$pid"
967}
968
969# A wrapper for check_running_module_version.
970# Go through the list of Guest Additions' modules and
971# verify if they are loaded and running version matches
972# to current installation version. Skip vboxvideo since
973# it is not loaded for old guests.
974check_status_kernel()
975{
976 for mod in vboxguest vboxsf; do
977
978 for attempt in 1 2 3 4 5; do
979
980 # Wait before the next attempt.
981 [ $? -ne 0 ] && sleep 1
982
983 running_module "$mod"
984 if [ $? -eq 0 ]; then
985 mod_is_running="1"
986 check_running_module_version "$mod"
987 [ $? -eq 0 ] && break
988 else
989 mod_is_running=""
990 false
991 fi
992
993 done
994
995 # In case of error, try to print out proper reason of failure.
996 if [ $? -ne 0 ]; then
997 # Was module loaded?
998 [ -n "$mod_is_running" ] || fail "module $mod is not loaded"
999 # If module was loaded it means that it has incorrect version.
1000 fail "currently loaded module $mod version ($(running_module_version "$mod")) does not match to VirtualBox Guest Additions installation version ($VBOX_VERSION $VBOX_REVISION)"
1001 fi
1002
1003 done
1004}
1005
1006# Check whether user-land processes are running.
1007# Currently only check for VBoxService.
1008check_status_user()
1009{
1010 check_pid "$(cat /var/run/vboxadd-service.sh)" >/dev/null 2>&1
1011}
1012
1013send_sig_usr1_by_pidfile()
1014{
1015 pidfile=$1
1016
1017 if [ -f "$pidfile" ]; then
1018 check_pid $(cat "$pidfile")
1019 if [ $? -eq 0 ]; then
1020 kill -USR1 $(cat "$pidfile") >/dev/null 2>&1
1021 else
1022 # Do not spoil $?.
1023 true
1024 fi
1025 else
1026 # Do not spoil $?.
1027 true
1028 fi
1029}
1030
1031# SIGUSR1 is used in order to notify VBoxClient processes that system
1032# update is started or kernel modules are going to be reloaded,
1033# so VBoxClient can release vboxguest.ko resources and then restart itself.
1034send_sig_usr1()
1035{
1036 # Specify whether we sending signal to VBoxClient parent (control)
1037 # process or a child (actual service) process.
1038 process_type="$1"
1039
1040 pidfile_postfix=""
1041 [ -z "$process_type" ] || pidfile_postfix="-$process_type"
1042
1043 for user_home in $(getent passwd | cut -d ':' -f 6); do
1044 if [ -d "$user_home" ]; then
1045
1046 for pid_file in "$user_home"/.vboxclient-*"$pidfile_postfix".pid; do
1047
1048 # If process type was not specified, we assume that signal supposed
1049 # to be sent to legacy VBoxClient processes which have different
1050 # pidfile name pattern (it does not contain "control" or "service").
1051 # Skip those pidfiles who has.
1052 [ -z "$process_type" -a -n "$(echo "$pid_file" | grep "control")" ] && continue
1053 [ -z "$process_type" -a -n "$(echo "$pid_file" | grep "service")" ] && continue
1054
1055 send_sig_usr1_by_pidfile "$pid_file"
1056 done
1057
1058 fi
1059 done
1060}
1061
1062reload()
1063{
1064 begin "reloading kernel modules and services"
1065
1066 # Stop VBoxService if running.
1067 $VBOX_SERVICE_SCRIPT status >/dev/null 2>&1
1068 if [ $? -eq 0 ]; then
1069 $VBOX_SERVICE_SCRIPT stop >/dev/null 2>&1 || fail "unable to stop VBoxService"
1070 fi
1071
1072 # Unmount Shared Folders.
1073 umount -a -t vboxsf >/dev/null 2>&1 || fail "unable to unmount shared folders"
1074
1075 # Stop VBoxDRMClient.
1076 send_sig_usr1_by_pidfile "/var/run/VBoxDRMClient" || fail "unable to stop VBoxDRMClient"
1077
1078 if [ $? -eq 0 ]; then
1079 # Tell legacy VBoxClient processes to release vboxguest.ko references.
1080 send_sig_usr1 ""
1081
1082 # Tell compatible VBoxClient processes to release vboxguest.ko references.
1083 send_sig_usr1 "service"
1084
1085 # Try unload.
1086 for attempt in 1 2 3 4 5; do
1087
1088 # Give VBoxClient processes some time to close reference to vboxguest module.
1089 [ $? -ne 0 ] && sleep 1
1090
1091 # Try unload drivers unconditionally (ignore previous command exit code).
1092 # If final goal of unloading vboxguest.ko won't be met, we will fail on
1093 # the next step anyway.
1094 running_vboxvideo && modprobe -r vboxvideo >/dev/null 2>&1
1095 running_vboxsf && modprobe -r vboxsf >/dev/null 2>&1
1096 running_vboxguest
1097 if [ $? -eq 0 ]; then
1098 modprobe -r vboxguest >/dev/null 2>&1
1099 [ $? -eq 0 ] && break
1100 else
1101 # Do not spoil $?.
1102 true
1103 fi
1104 done
1105
1106 # Check if we succeeded with unloading vboxguest after several attempts.
1107 running_vboxguest
1108 if [ $? -eq 0 ]; then
1109 fail "Cannot reload kernel modules: one or more module(s) is still in use"
1110 else
1111 # Do not spoil $?.
1112 true
1113 fi
1114
1115 # Load drivers (skip vboxvideo since it is not loaded for very old guests).
1116 [ $? -eq 0 ] && modprobe vboxguest >/dev/null 2>&1
1117 [ $? -eq 0 ] && modprobe vboxsf >/dev/null 2>&1
1118
1119 # Start VBoxService and VBoxDRMClient (systemctl start vboxadd-service.service).
1120 [ $? -eq 0 ] && $VBOX_SERVICE_SCRIPT start >/dev/null 2>&1
1121
1122 # Reload VBoxClient processes.
1123 [ $? -eq 0 ] && send_sig_usr1 "control"
1124
1125 if [ $? -eq 0 ]; then
1126
1127 # Check if we just loaded modules of correct version.
1128 check_status_kernel
1129
1130 # Check if user-land processes were restarted as well.
1131 check_status_user
1132
1133 # Take reported version of running Guest Additions from running vboxguest module (as a paranoia check).
1134 info "kernel modules and services $(running_module_version "vboxguest") reloaded"
1135 info "NOTE: you may still consider to re-login if some user session specific services (Shared Clipboard, Drag and Drop, Seamless or Guest Screen Resize) were not restarted automatically"
1136 else
1137 fail "cannot verify if kernel modules and services were reloaded"
1138 fi
1139 else
1140 fail "cannot stop user services"
1141 fi
1142}
1143
1144dmnstatus()
1145{
1146 if running_vboxguest; then
1147 echo "The VirtualBox Additions are currently running."
1148 else
1149 echo "The VirtualBox Additions are not currently running."
1150 fi
1151}
1152
1153for i; do
1154 case "$i" in quiet) QUIET=yes;; esac
1155done
1156case "$1" in
1157# Does setup without clean-up first and marks all kernels currently found on the
1158# system so that we can see later if any were added.
1159start)
1160 check_root
1161 start
1162 ;;
1163# Tries to build kernel modules for kernels added since start. Tries to unmount
1164# shared folders. Uninstalls our Chromium 3D libraries since we can't always do
1165# this fast enough at start time if we discover we do not want to use them.
1166stop)
1167 check_root
1168 stop
1169 ;;
1170restart)
1171 check_root
1172 restart
1173 ;;
1174# Tries to reload kernel modules and restart user processes.
1175reload)
1176 check_root
1177 reload
1178 ;;
1179# Setup does a clean-up (see below) and re-does all Additions-specific
1180# configuration of the guest system, including building kernel modules for the
1181# current kernel.
1182setup)
1183 check_root
1184 cleanup && start
1185 ;;
1186# Builds kernel modules for the specified kernels if they are not already built.
1187quicksetup)
1188 check_root
1189 if test x"$2" = xall; then
1190 for topi in /lib/modules/*; do
1191 KERN_VER="${topi%/misc}"
1192 KERN_VER="${KERN_VER#/lib/modules/}"
1193 setup_modules "$KERN_VER"
1194 done
1195 elif test -n "$2"; then
1196 setup_modules "$2"
1197 else
1198 setup_modules "$TARGET_VER"
1199 fi
1200 ;;
1201# Clean-up removes all Additions-specific configuration of the guest system,
1202# including all kernel modules.
1203cleanup)
1204 check_root
1205 cleanup
1206 ;;
1207status)
1208 dmnstatus
1209 ;;
1210status-kernel)
1211 check_root
1212 check_status_kernel && info "Kernel modules are loaded"
1213 ;;
1214status-user)
1215 check_root
1216 check_status_user
1217 if [ $? -eq 0 ]; then
1218 info "User-land services are running"
1219 else
1220 fail "User-land services are not running"
1221 fi
1222 ;;
1223*)
1224 echo "Usage: $0 {start|stop|restart|reload|status|status-kernel|status-user|setup|quicksetup|cleanup} [quiet]"
1225 exit 1
1226esac
1227
1228exit
Note: See TracBrowser for help on using the repository browser.

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