From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- src/VBox/Additions/linux/installer/.scm-settings | 30 + src/VBox/Additions/linux/installer/autorun.sh | 204 +++ src/VBox/Additions/linux/installer/deffiles | 80 ++ src/VBox/Additions/linux/installer/install.sh.in | 640 ++++++++++ .../Additions/linux/installer/module-autologon.sh | 182 +++ .../Additions/linux/installer/vboxadd-service.sh | 171 +++ src/VBox/Additions/linux/installer/vboxadd-x11.sh | 625 +++++++++ src/VBox/Additions/linux/installer/vboxadd.sh | 1325 ++++++++++++++++++++ 8 files changed, 3257 insertions(+) create mode 100644 src/VBox/Additions/linux/installer/.scm-settings create mode 100755 src/VBox/Additions/linux/installer/autorun.sh create mode 100644 src/VBox/Additions/linux/installer/deffiles create mode 100755 src/VBox/Additions/linux/installer/install.sh.in create mode 100644 src/VBox/Additions/linux/installer/module-autologon.sh create mode 100755 src/VBox/Additions/linux/installer/vboxadd-service.sh create mode 100755 src/VBox/Additions/linux/installer/vboxadd-x11.sh create mode 100755 src/VBox/Additions/linux/installer/vboxadd.sh (limited to 'src/VBox/Additions/linux/installer') diff --git a/src/VBox/Additions/linux/installer/.scm-settings b/src/VBox/Additions/linux/installer/.scm-settings new file mode 100644 index 00000000..cd5b9eba --- /dev/null +++ b/src/VBox/Additions/linux/installer/.scm-settings @@ -0,0 +1,30 @@ +# $Id: .scm-settings $ +## @file +# Source code massager settings for linux guest additions installer. +# + +# +# Copyright (C) 2010-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# SPDX-License-Identifier: GPL-3.0-only +# + + +/install.sh.in: --treat-as .sh +/deffiles: --treat-as files_ diff --git a/src/VBox/Additions/linux/installer/autorun.sh b/src/VBox/Additions/linux/installer/autorun.sh new file mode 100755 index 00000000..146cb46b --- /dev/null +++ b/src/VBox/Additions/linux/installer/autorun.sh @@ -0,0 +1,204 @@ +#!/bin/sh +# $Id: autorun.sh $ +## @file +# VirtualBox Guest Additions installation script for *nix guests +# + +# +# Copyright (C) 2009-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# SPDX-License-Identifier: GPL-3.0-only +# + +PATH=$PATH:/bin:/sbin:/usr/sbin + +# Deal with differing "which" semantics +mywhich() { + which "$1" 2>/dev/null | grep -v "no $1" +} + +# Get the name and execute switch for a useful terminal emulator +# +# Sets $gxtpath to the emulator path or empty +# Sets $gxttitle to the "title" switch for that emulator +# Sets $gxtexec to the "execute" switch for that emulator +# May clobber $gtx* +# Calls mywhich +getxterm() { + # gnome-terminal and mate-terminal use -e differently to other emulators + for gxti in "konsole --title -e" "gnome-terminal --title -x" "mate-terminal --title -x" "xterm -T -e"; do + set $gxti + gxtpath="`mywhich $1`" + case "$gxtpath" in ?*) + gxttitle=$2 + gxtexec=$3 + return + ;; + esac + done +} + +# Quotes its argument by inserting '\' in front of every character save +# for 'A-Za-z0-9/'. Prints the result to stdout. +quotify() { + echo "$1" | sed -e 's/\([^a-zA-Z0-9/]\)/\\\1/g' +} + +ostype=`uname -s` +if test "$ostype" != "Linux" && test "$ostype" != "SunOS" ; then + echo "Linux/Solaris not detected." + exit 1 +fi + +# The below is GNU-specific. See VBox.sh for the longer Solaris/OS X version. +TARGET=`readlink -e -- "${0}"` || exit 1 +path="${TARGET%/[!/]*}" +# 32-bit or 64-bit? +case `uname -m` in + i[3456789]86|x86|i86pc) + arch='x86' + ;; + x86_64|amd64|AMD64) + arch='amd64' + ;; + *) + echo "Unknown architecture `uname -m`." + exit 1 + ;; +esac + +# execute the installer +if test "$ostype" = "Linux"; then + for i in "$path/VBoxLinuxAdditions.run" \ + "$path/VBoxLinuxAdditions-$arch.run"; do + if test -f "$i"; then + getxterm + case "$gxtpath" in ?*) + TITLE="VirtualBox Guest Additions installation" + BINARY="`quotify "$i"`" + exec "$gxtpath" "$gxttitle" "$TITLE" "$gxtexec" /bin/sh "$path/runasroot.sh" --has-terminal "$TITLE" "/bin/sh $BINARY --xwin" "Please try running "\""$i"\"" manually." + exit + ;; + *) + echo "Unable to start installation process with elevated privileges automatically. Please try running "\""$i"\"" manually." + exit + ;; + esac + fi + done + + # else: unknown failure + echo "Linux guest additions installer not found -- try to start it manually." + exit 1 + +elif test "$ostype" = "SunOS"; then + + # check for combined package + installfile="$path/VBoxSolarisAdditions.pkg" + if test -f "$installfile"; then + + # check for pkgadd bin + pkgaddbin=pkgadd + found=`which pkgadd | grep "no pkgadd"` + if test ! -z "$found"; then + if test -f "/usr/sbin/pkgadd"; then + pkgaddbin=/usr/sbin/pkgadd + else + echo "Could not find pkgadd." + exit 1 + fi + fi + + # check for pfexec + pfexecbin=pfexec + found=`which pfexec | grep "no pfexec"` + if test ! -z "$found"; then + # Use su and prompt for password + echo "Could not find pfexec." + subin=`which su` + else + idbin=/usr/xpg4/bin/id + if test ! -x "$idbin"; then + found=`which id 2> /dev/null` + if test ! -x "$found"; then + echo "Failed to find a suitable user id executable." + exit 1 + else + idbin=$found + fi + fi + + # check if pfexec can get the job done + if test "$idbin" = "/usr/xpg4/bin/id"; then + userid=`$pfexecbin $idbin -u` + else + userid=`$pfexecbin $idbin | cut -f1 -d'(' | cut -f2 -d'='` + fi + if test $userid != "0"; then + # pfexec exists but user has no pfexec privileges, switch to using su and prompting password + subin=`which su` + fi + fi + + # create temporary admin file for autoinstall + TMPFILE=`mktemp -q /tmp/vbox.XXXXXX` + if [ -z $TMPFILE ]; then + echo "Unable to create a temporary file" + exit 1 + fi + echo "basedir=default +runlevel=nocheck +conflict=quit +setuid=nocheck +action=nocheck +partial=quit +instance=unique +idepend=quit +rdepend=quit +space=quit +mail= +" > $TMPFILE + + # check gnome-terminal, use it if it exists. + if test -f "/usr/bin/gnome-terminal"; then + # use su/pfexec + if test -z "$subin"; then + /usr/bin/gnome-terminal --title "Installing VirtualBox Additions" --command "/bin/sh -c '$pfexecbin $pkgaddbin -G -d $installfile -n -a $TMPFILE SUNWvboxguest; /bin/echo press ENTER to close this window; /bin/read'" + else + /usr/bin/gnome-terminal --title "Installing VirtualBox Additions: Root password required." --command "/bin/sh -c '$subin - root -c \"$pkgaddbin -G -d $installfile -n -a $TMPFILE SUNWvboxguest\"; /bin/echo press ENTER to close this window; /bin/read'" + fi + elif test -f "/usr/X11/bin/xterm"; then + # use xterm + if test -z "$subin"; then + /usr/X11/bin/xterm -title "Installing VirtualBox Additions" -e "$pfexecbin $pkgaddbin -G -d $installfile -n -a $TMPFILE SUNWvboxguest; /bin/echo press ENTER to close this window; /bin/read" + else + /usr/X11/bin/xterm -title "Installing VirtualBox Additions: Root password required." -e "$subin - root -c \"$pkgaddbin -G -d $installfile -n -a $TMPFILE SUNWvboxguest\"; /bin/echo press ENTER to close this window; /bin/read" + fi + else + echo "No suitable terminal not found. -- install additions using pkgadd -d." + fi + rm -r $TMPFILE + + exit 0 + fi + + echo "Solaris guest additions installer not found -- try to start them manually." + exit 1 +fi + diff --git a/src/VBox/Additions/linux/installer/deffiles b/src/VBox/Additions/linux/installer/deffiles new file mode 100644 index 00000000..79fa03dd --- /dev/null +++ b/src/VBox/Additions/linux/installer/deffiles @@ -0,0 +1,80 @@ +# $Id: deffiles $ +## @file +# VirtualBox linux Guest Additions default files list +# + +# +# Copyright (C) 2009-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# SPDX-License-Identifier: GPL-3.0-only +# + +# This file contains the names of all files that the Guest Additions for +# Linux guests have ever installed into the main filesystem tree (/usr and +# /sbin). No entries should ever be removed from this file, as it is used +# for uninstalling old installations of VirtualBox which did not keep track +# of the names of their files, or damaged installations which lost track of +# them. + +DEFAULT_FILE_NAMES=" \ + /usr/bin/vboxadd-xclient \ + /usr/bin/VBoxAudioTest \ + /usr/bin/VBoxClient \ + /usr/bin/VBoxControl \ + /usr/sbin/vbox-greeter \ + /usr/sbin/vboxadd-timesync \ + /usr/sbin/vboxadd-service \ + /usr/sbin/VBoxService \ + /sbin/mount.vboxsf \ + /usr/share/xgreeters/vbox-greeter.desktop \ + /etc/X11/Xsession.d/98vboxadd-xclient \ + /etc/X11/xinit.d/98vboxadd-xclient \ + /etc/X11/xinit/xinitrc.d/98vboxadd-xclient.sh \ + /usr/bin/VBoxRandR \ + /usr/bin/VBoxClient-all \ + /etc/xdg/autostart/vboxclient.desktop \ + /usr/share/autostart/vboxclient.desktop \ + /etc/udev/rules.d/60-vboxadd.rules \ + /usr/share/xserver-xorg/pci/vboxvideo.ids \ + /etc/hal/fdi/policy/90-vboxguest.fdi \ + /etc/udev/rules.d/70-xorg-vboxmouse.rules \ + /usr/share/hal/fdi/policy/20thirdparty/90-vboxguest.fdi \ + /usr/lib/X11/xorg.conf.d/50-vboxmouse.conf \ + /usr/share/X11/xorg.conf.d/50-vboxmouse.conf \ + /usr/lib/dri/vboxvideo_dri.so \ + /usr/lib64/dri/vboxvideo_dri.so \ + /usr/lib64/xorg/modules/drivers/vboxvideo_drv.so \ + /usr/lib/xorg/modules/drivers/vboxvideo_drv.so \ + /usr/X11R6/lib64/modules/drivers/vboxvideo_drv.so \ + /usr/X11R6/lib/modules/drivers/vboxvideo_drv.so \ + /usr/X11R6/lib/X11/modules/drivers/vboxvideo_drv.so \ + /usr/lib64/xorg/modules/input/vboxmouse_drv.so \ + /usr/lib/xorg/modules/input/vboxmouse_drv.so \ + /usr/X11R6/lib64/modules/input/vboxmouse_drv.so \ + /usr/X11R6/lib/modules/input/vboxmouse_drv.so \ + /usr/X11R6/lib/X11/modules/input/vboxmouse_drv.so +" + +DEFAULT_VERSIONED_FILE_NAMES=" \ + /usr/src/vboxadd \ + /usr/src/vboxguest \ + /usr/src/vboxvfs \ + /usr/src/vboxsf \ + /usr/src/vboxvideo \ +" diff --git a/src/VBox/Additions/linux/installer/install.sh.in b/src/VBox/Additions/linux/installer/install.sh.in new file mode 100755 index 00000000..a3c6329a --- /dev/null +++ b/src/VBox/Additions/linux/installer/install.sh.in @@ -0,0 +1,640 @@ +#!/bin/sh +# +# Oracle VM VirtualBox +# VirtualBox Makeself installation starter script +# for Linux Guest Additions + +# +# Copyright (C) 2006-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# SPDX-License-Identifier: GPL-3.0-only +# + +# Testing: +# * After successful installation, 0 is returned if the vboxguest module version +# built matches the one loaded and 2 is returned otherwise. E.g. VBoxClient +# running will prevent vboxguest reloading. +# * If the kernel modules cannot be built (run the installer with KERN_VER=none) +# or loaded (run with KERN_VER=) then 1 is +# returned. + +PATH=$PATH:/bin:/sbin:/usr/sbin + +# Note: These variable names must *not* clash with variables in $CONFIG_DIR/$CONFIG! +PACKAGE="VBoxGuestAdditions" +PACKAGE_NAME="VirtualBox Guest Additions" +UNINSTALL="uninstall.sh" +PUBLIC_UNINSTALL_HOOK="/usr/sbin/vbox-uninstall-guest-additions" +ROUTINES="routines.sh" +INSTALLATION_VER="_VERSION_" +BUILD_VBOX_KBUILD_TYPE="_BUILDTYPE_" +BUILD_USERNAME="_USERNAME_" +UNINSTALL_SCRIPTS="vboxadd-x11 vboxvfs vboxadd-timesync vboxadd-service vboxadd" + +INSTALLATION_DIR="/opt/$PACKAGE-$INSTALLATION_VER" +CONFIG_DIR="/var/lib/$PACKAGE" +CONFIG="config" +CONFIG_FILES="filelist" +SELF=$1 +LOGFILE="/var/log/vboxadd-install.log" + +## Were we able to stop any previously running Additions kernel modules? +MODULES_STOPPED=1 + +. "./$ROUTINES" + +check_root + +check_deps bzip2 tar + +create_log "$LOGFILE" + +usage() +{ + catinfo << EOF + +Usage: $SELF install [] + [--with-] + [--package-base | + uninstall + [--force] [--no-setup] + +Options: + --package-base For use when building distribution packages. + Installs relative to instead of to "/", + does not run setup, installs to "/usr/lib" + instead of to "/opt" and does not create uninstall. + --force Forces an upgrade. Not recommended. + +Example: +$SELF install +EOF + exit 1 +} + +# Create a symlink in the filesystem and add it to the list of package files +add_symlink() +{ + self=add_symlink + ## Parameters: + # The file the link should point to + target="$1" + # The name of the actual symlink file. Must be an absolute path to a + # non-existing file in an existing directory. + link="$2" + link_dir="`dirname "$link"`" + test -n "$target" || + { echo 1>&2 "$self: no target specified"; return 1; } + test -d "$link_dir" || + { echo 1>&2 "$self: link directory $link_dir does not exist"; return 1; } + expr "$link" : "/.*" > /dev/null || + { echo 1>&2 "$self: link file name is not absolute"; return 1; } + rm -f "$link" + ln -s "$target" "$link" + echo "$link" >> "$CONFIG_DIR/$CONFIG_FILES" +} + +# Create symbolic links targeting all files in a directory in another +# directory in the filesystem +link_into_fs() +{ + ## Parameters: + # Directory containing the link target files + target_branch="$1" + # Directory to create the link files in + directory="$2" + for i in "$INSTALLATION_DIR/$target_branch"/*; do + test -e "$i" && + add_symlink "$i" "$directory/`basename $i`" + done +} + +# Look for broken installations or installations without a known uninstaller +# and try to clean them up, asking the user first. +def_uninstall() +{ + ## Parameters: + # Whether to force cleanup without asking the user + force="$1" + + . ./deffiles + found=0 + for i in "/opt/$PACKAGE-"*; do + test -e "$i" && found=1 + done + for i in $DEFAULT_FILE_NAMES; do + test "$found" = 0 && test -e "$i" && found=1 + done + test "$found" = 0 && + for i in $DEFAULT_VERSIONED_FILE_NAMES; do + for j in $i-*; do + test "$found" = 0 && test -e "$j" && found=1 + done + done + test "$found" = 0 && return 0 + if ! test "$1" = "force" ; then + # Try to make the promised notification appear on next start. + VBoxControl guestproperty delete \ + /VirtualBox/GuestAdd/HostVerLastChecked 2>&1 > /dev/null + cat 1>&2 << EOF +This system appears to have a version of the VirtualBox Guest Additions +already installed. If it is part of the operating system and kept up-to-date, +there is most likely no need to replace it. If it is not up-to-date, you +should get a notification when you start the system. If you wish to replace +it with this version, please do not continue with this installation now, but +instead remove the current version first, following the instructions for the +operating system. + +If your system simply has the remains of a version of the Additions you could +not remove you should probably continue now, and these will be removed during +installation. + +Do you wish to continue? [yes or no] +EOF + read reply dummy + if ! expr "$reply" : [yY] > /dev/null && + ! expr "$reply" : [yY][eE][sS] > /dev/null + then + info + info "Cancelling installation." + return 1 + fi + fi + # Inhibit rebuilding of any installed kernels. + for i in /lib/modules/*; do + ver="${i##*/}" + test ! -d "$i"/build || touch /var/lib/VBoxGuestAdditions/skip-"$ver" + done + # Stop what we can in the way of services and remove them from the + # system + for i in $UNINSTALL_SCRIPTS; do + stop_init_script "$i" 2>> "${LOGFILE}" + test -z "$NO_CLEANUP" && test -x "./$i" && "./$i" cleanup 1>&2 2>> "$LOGFILE" + delrunlevel "$i" 2>> "${LOGFILE}" + remove_init_script "$i" 2>> "${LOGFILE}" + done + for i in "/opt/$PACKAGE-"*/init; do + for j in $UNINSTALL_SCRIPTS; do + script="${i}/${j}" + test -x "${script}" && test -z "$NO_CLEANUP" && + grep -q '^# *cleanup_script *$' "${script}" && + "${script}" cleanup 1>&2 2>> "$LOGFILE" + done + done + + # Get rid of any remaining files + for i in $DEFAULT_FILE_NAMES; do + rm -f "$i" 2> /dev/null + done + for i in $DEFAULT_VERSIONED_FILE_NAMES; do + rm -f "$i-"* 2> /dev/null + done + rm -f "/usr/lib/$PACKAGE" "/usr/lib64/$PACKAGE" "/usr/share/$PACKAGE" \ + "/usr/lib/i386-linux-gnu/$PACKAGE" "/usr/lib/x86_64-linux-gnu/$PACKAGE" + + # And any packages left under /opt + for i in "/opt/$PACKAGE-"*; do + test -d "$i" && rm -rf "$i" + done + return 0 +} + +info "$PACKAGE_NAME installer" + +# Sensible default actions +ACTION="install" +NO_CLEANUP="" +FORCE_UPGRADE="" +PACKAGE_BASE="" + +while [ $# -ge 2 ]; +do + ARG=$2 + shift + + if [ -z "$MY_END_OF_OPTIONS" ]; then + case "$ARG" in + + install) + ACTION="install" + ;; + + uninstall) + ACTION="uninstall" + ;; + + package) + ACTION="package" + INSTALLATION_DIR=/usr/lib + PACKAGE_BASE="$2" + shift + if test ! -d "${PACKAGE_BASE}"; then + info "Package base directory not found." + usage + fi + ;; + + ## @todo Add per-module options handling, e.g. --lightdm-greeter-dir + # or --lightdm-config + + ## @todo Add listing all available modules (+ their options, e.g. + # with callback mod_mymod_show_options?) + + --with-*) + MODULE_CUR=`expr "$ARG" : '--with-\(.*\)'` + # Check if corresponding module in installer/module-$1 exists. + # Note: Module names may not contain spaces or other funny things. + if [ ! -f "./installer/module-${MODULE_CUR}" ]; then + info "Error: Module \"${MODULE_CUR}\" does not exist." + usage + fi + # Give the module the chance of doing initialization work / checks. + . "./installer/module-${MODULE_CUR}" + mod_${MODULE_CUR}_init + if test $? -ne 0; then + echo 1>&2 "Module '${MODULE_CUR}' failed to initialize" + if ! test "$FORCE_UPGRADE" = "force"; then + return 1 + fi + # Continue initialization. + fi + # Add module to the list of modules to handle later. + if test -z "${INSTALLATION_MODULES_LIST}"; then + INSTALLATION_MODULES_LIST="${MODULE_CUR}" + else + INSTALLATION_MODULES_LIST="${INSTALLATION_MODULES_LIST} ${MODULE_CUR}" + fi + shift + ;; + + --force|force) # Keep "force" for backwards compatibility. + FORCE_UPGRADE="force" + ;; + + --no-setup|no_setup) + # Deprecated; keep this setting for backwards compatibility. + ;; + + --no-cleanup|no_cleanup) # Keep "no_cleanup" for backwards compatibility. + # Do not do cleanup of old modules when removing them. For + # testing purposes only. + NO_CLEANUP="no_cleanup" + ;; + + --) + MY_END_OF_OPTIONS="1" + ;; + + *) + if [ "`echo $1|cut -c1`" != "/" ]; then + info "Please specify an absolute path" + usage + fi + INSTALLATION_DIR="$1" + shift + ;; + esac + fi +done + +# Check architecture +cpu=`uname -m`; +case "$cpu" in + i[3456789]86|x86) + cpu="x86" + lib_candidates="/usr/lib/i386-linux-gnu /usr/lib /lib" + ;; + x86_64|amd64) + cpu="amd64" + lib_candidates="/usr/lib/x86_64-linux-gnu /usr/lib64 /usr/lib /lib64 /lib" + ;; + *) + cpu="unknown" +esac +ARCH_PACKAGE="$PACKAGE-$cpu.tar.bz2" +if [ ! -r "$ARCH_PACKAGE" ]; then + info "Detected unsupported $cpu machine type." + exit 1 +fi +# Find the most appropriate libary folder by seeing which of the candidate paths +# are actually in the shared linker path list and choosing the first. We look +# for Debian-specific paths first, then LSB ones, then the new RedHat ones. +libs=`ldconfig -v 2>/dev/null | grep -v ^$'\t'` +for i in $lib_candidates; do + if echo $libs | grep -q $i; then + lib_path=$i + break + fi +done +if [ ! -x "$lib_path" ]; then + info "Unable to determine correct library path." + exit 1 +fi + +# uninstall any previous installation +# If the currently installed Additions have provided an uninstallation hook, try +# that first. +if test -x "${PUBLIC_UNINSTALL_HOOK}"; then + "${PUBLIC_UNINSTALL_HOOK}" 1>&2 || + abort "Failed to remove existing installation. Aborting..." +fi + +INSTALL_DIR="" +uninstalled=0 +test -r "$CONFIG_DIR/$CONFIG" && . "$CONFIG_DIR/$CONFIG" +if test -n "$INSTALL_DIR" && test -n "$UNINSTALLER" && + test -x "$INSTALL_DIR/$UNINSTALLER"; then + "$INSTALL_DIR/$UNINSTALLER" $NO_CLEANUP 1>&2 || + abort "Failed to remove existing installation. Aborting..." + uninstalled=1 +fi +test "$uninstalled" = 0 && def_uninstall "$FORCE_UPGRADE" && uninstalled=1 +test "$uninstalled" = 0 && exit 1 +rm -f "$CONFIG_DIR/$CONFIG" +rm -f "$CONFIG_DIR/$CONFIG_FILES" +rmdir "$CONFIG_DIR" 2>/dev/null || true +test "$ACTION" = "install" || exit 0 + +# Now check whether the kernel modules were stopped. +lsmod | grep -q vboxguest && MODULES_STOPPED= + +# Choose a proper umask +umask 022 + +# Set installer modules directory +INSTALLATION_MODULES_DIR="$INSTALLATION_DIR/installer/" + +# install the new version +mkdir -p -m 755 "$CONFIG_DIR" +test ! -d "$INSTALLATION_DIR" && REMOVE_INSTALLATION_DIR=1 +mkdir -p -m 755 "$INSTALLATION_DIR" + +# install and load installer modules +if [ -d installer ]; then + info "Copying additional installer modules ..." + mkdir -p -m 755 "$INSTALLATION_MODULES_DIR" + for CUR_FILE in `ls installer/*`; do + install -p -m 755 "$CUR_FILE" "$INSTALLATION_MODULES_DIR" + if [ $? -ne 0 ]; then + info "Error: Failed to copy installer module \"$CUR_FILE\"" + if ! test "$FORCE_UPGRADE" = "force"; then + exit 1 + fi + fi + done +fi + +# Create a list of the files in the archive, skipping any directories which +# already exist in the filesystem. +bzip2 -d -c "$ARCH_PACKAGE" | tar -tf - | + while read name; do + fullname="$INSTALLATION_DIR/$name" + case "$fullname" in + */) + test ! -d "$fullname" && + echo "$fullname" >> "$CONFIG_DIR/$CONFIG_FILES" + ;; + *) + echo "$fullname" >> "$CONFIG_DIR/$CONFIG_FILES" + ;; + esac + done +bzip2 -d -c "$ARCH_PACKAGE" | tar -xf - -C "$INSTALLATION_DIR" || exit 1 + +# Set symlinks into /usr and /sbin +link_into_fs "bin" "${PACKAGE_BASE}/usr/bin" +link_into_fs "sbin" "${PACKAGE_BASE}/usr/sbin" +link_into_fs "lib" "$lib_path" +link_into_fs "src" "${PACKAGE_BASE}/usr/src" + +if [ -d "$INSTALLATION_MODULES_DIR" ]; then + info "Installing additional modules ..." + for CUR_MODULE in `find "$INSTALLATION_MODULES_DIR" 2>/dev/null` + do + echo "$CUR_MODULE" >> "$CONFIG_DIR/$CONFIG_FILES" + done +fi + +for CUR_MODULE in ${INSTALLATION_MODULES_LIST} +do + mod_${CUR_MODULE}_install + if [ $? -ne 0 ]; then + info "Error: Failed to install module \"$CUR_MODULE\"" + if ! test "$FORCE_UPGRADE" = "force"; then + exit 1 + fi + fi +done + +# Remember our installation configuration before we call any init scripts +cat > "$CONFIG_DIR/$CONFIG" << EOF +# $PACKAGE installation record. +# Package installation directory +INSTALL_DIR='$INSTALLATION_DIR' +# Additional installation modules +INSTALL_MODULES_DIR='$INSTALLATION_MODULES_DIR' +INSTALL_MODULES_LIST='$INSTALLATION_MODULES_LIST' +# Package uninstaller. If you repackage this software, please make sure +# that this prints a message and returns an error so that the default +# uninstaller does not attempt to delete the files installed by your +# package. +UNINSTALLER='$UNINSTALL' +# Package version +INSTALL_VER='$INSTALLATION_VER' +# Build type and user name for logging purposes +BUILD_VBOX_KBUILD_TYPE='$BUILD_BUILDTYPE' +BUILD_USERNAME='$USERNAME' +EOF + +# Give the modules the chance to write their stuff +# to the installation config as well. +if [ -n "${INSTALLATION_MODULES_LIST}" ]; then + info "Saving modules configuration ..." + for CUR_MODULE in ${INSTALLATION_MODULES_LIST} + do + echo "`mod_${CUR_MODULE}_config_save`" >> "$CONFIG_DIR/$CONFIG" + done +fi + +# Install, set up and start init scripts +install_init_script "$INSTALLATION_DIR"/init/vboxadd vboxadd 2>> "$LOGFILE" +install_init_script "$INSTALLATION_DIR"/init/vboxadd-service vboxadd-service \ + 2>> "$LOGFILE" +finish_init_script_install +addrunlevel vboxadd 2>> "$LOGFILE" +addrunlevel vboxadd-service 2>> "$LOGFILE" +"$INSTALLATION_DIR"/init/vboxadd setup 2>&1 | tee -a "$LOGFILE" +start_init_script vboxadd 2>> "$LOGFILE" +start_init_script vboxadd-service 2>> "$LOGFILE" + +cp $ROUTINES $INSTALLATION_DIR +echo $INSTALLATION_DIR/$ROUTINES >> "$CONFIG_DIR/$CONFIG_FILES" +cat > $INSTALLATION_DIR/$UNINSTALL << EOF +#!/bin/sh +# Auto-generated uninstallation file + +PATH=\$PATH:/bin:/sbin:/usr/sbin +LOGFILE="/var/log/vboxadd-uninstall.log" + +# Read routines.sh +if ! test -r "$INSTALLATION_DIR/$ROUTINES"; then + echo 1>&2 "Required file $ROUTINES not found. Aborting..." + return 1 +fi +. "$INSTALLATION_DIR/$ROUTINES" + +# We need to be run as root +check_root + +create_log "\$LOGFILE" + +echo 1>&2 "Removing installed version $INSTALLATION_VER of $PACKAGE_NAME..." + +NO_CLEANUP="" +if test "\$1" = "no_cleanup"; then + shift + NO_CLEANUP="no_cleanup" +fi + +test -r "$CONFIG_DIR/$CONFIG_FILES" || abort "Required file $CONFIG_FILES not found. Aborting..." + +# Stop and clean up all services +if test -r "$INSTALLATION_DIR"/init/vboxadd-service; then + stop_init_script vboxadd-service 2>> "\$LOGFILE" + delrunlevel vboxadd-service 2>> "\$LOGFILE" + remove_init_script vboxadd-service 2>> "\$LOGFILE" +fi +if test -r "$INSTALLATION_DIR"/init/vboxadd; then + stop_init_script vboxadd 2>> "\$LOGFILE" + test -n "\$NO_CLEANUP" || "$INSTALLATION_DIR"/init/vboxadd cleanup 2>> "\$LOGFILE" + delrunlevel vboxadd 2>> "\$LOGFILE" + remove_init_script vboxadd 2>> "\$LOGFILE" +fi +finish_init_script_install + +# Load all modules +# Important: This needs to be done before loading the configuration +# value below to not override values which are set to a default +# value in the modules itself. +for CUR_MODULE in `find "$INSTALLATION_MODULES_DIR" -name "module-*" 2>/dev/null` + do + . "\$CUR_MODULE" + done + +# Load configuration values +test -r "$CONFIG_DIR/$CONFIG" && . "$CONFIG_DIR/$CONFIG" + +# Call uninstallation initialization of all modules +for CUR_MODULE in "$INSTALLATION_MODULES_LIST" + do + if test -z "\$CUR_MODULE"; then + continue + fi + mod_\${CUR_MODULE}_pre_uninstall + if [ $? -ne 0 ]; then + echo 1>&2 "Module \"\$CUR_MODULE\" failed to initialize uninstallation" + # Continue initialization. + fi + done + +# Call uninstallation of all modules +for CUR_MODULE in "$INSTALLATION_MODULES_LIST" + do + if test -z "\$CUR_MODULE"; then + continue + fi + mod_\${CUR_MODULE}_uninstall + if [ $? -ne 0 ]; then + echo 1>&2 "Module \"\$CUR_MODULE\" failed to uninstall" + # Continue uninstallation. + fi + done + +# And remove all files and empty installation directories +# Remove any non-directory entries +cat "$CONFIG_DIR/$CONFIG_FILES" | xargs rm 2>/dev/null +# Remove any empty (of files) directories in the file list +cat "$CONFIG_DIR/$CONFIG_FILES" | + while read file; do + case "\$file" in + */) + test -d "\$file" && + find "\$file" -depth -type d -exec rmdir '{}' ';' 2>/dev/null + ;; + esac + done + +# Remove configuration files +rm "$CONFIG_DIR/$CONFIG_FILES" 2>/dev/null +rm "$CONFIG_DIR/$CONFIG" 2>/dev/null +rmdir "$CONFIG_DIR" 2>/dev/null +exit 0 +EOF +chmod 0755 $INSTALLATION_DIR/$UNINSTALL +echo $INSTALLATION_DIR/$UNINSTALL >> "$CONFIG_DIR/$CONFIG_FILES" +test -n "$REMOVE_INSTALLATION_DIR" && + echo "$INSTALLATION_DIR/" >> "$CONFIG_DIR/$CONFIG_FILES" + +cat > "${PUBLIC_UNINSTALL_HOOK}" << EOF +#!/bin/sh +# This executable provides a well-known way to uninstall VirtualBox Guest +# Additions in order to re-install them from a different source. A common case +# is uninstalling distribution-provide Additions to install the version provided +# by VirtualBox. Distributions should put the right command in here to do the +# removal, e.g. "dnf remove VirtualBox-guest-additions". Leaving kernel modules +# provided by the distribution kernel package in place is acceptable if the +# location does not clash with the VirtualBox-provided module location (misc). +$INSTALLATION_DIR/$UNINSTALL +EOF +chmod 0755 "${PUBLIC_UNINSTALL_HOOK}" +echo "$PUBLIC_UNINSTALL_HOOK" >> "$CONFIG_DIR/$CONFIG_FILES" + +# Test for a problem with old Mesa versions which stopped our 3D libraries +# from working. Known to affect Debian 7.11, probably OL/RHEL 5. +# The problem was that the system Mesa library had an ABI note, which caused +# ldconfig to always prefer it to ours. +if ldconfig -p | grep -q "libGL.so.1.*Linux 2.4"; then + gl_with_abi=`ldconfig -p | grep "libGL.so.1.*Linux 2.4" | sed 's/.*=> //'` + cat >&2 << EOF +This system appears to be running a version of Mesa with a known problem +which will prevent VirtualBox 3D pass-through from working. See + https://bugs.freedesktop.org/show_bug.cgi?id=26663 +The following, run as root should fix this, though you will have to run it +again if the system version of Mesa is updated: +EOF + for i in ${gl_with_abi}; do + echo >&2 " strip -R .note.ABI-tag ${i}" + done + echo >&2 " ldconfig" +fi + +# setuid bit of our drm client as drm ioctl calls +# need to be done by elevated privileges +chmod 4755 "$INSTALLATION_DIR"/bin/VBoxDRMClient + +# And do a final test as to whether the kernel modules were properly created +# and loaded. Return 0 if both are true, 1 if the modules could not be built +# or loaded (except due to already running older modules) and 2 if already +# running modules probably prevented new ones from loading. vboxvideo is +# currently not tested. +# Assume that we have already printed enough messages by now and stay silent. +modinfo vboxguest >/dev/null 2>&1 || exit 1 +lsmod | grep -q vboxguest || exit 1 +test -n "${MODULES_STOPPED}" || exit 2 +exit 0 diff --git a/src/VBox/Additions/linux/installer/module-autologon.sh b/src/VBox/Additions/linux/installer/module-autologon.sh new file mode 100644 index 00000000..5685bed4 --- /dev/null +++ b/src/VBox/Additions/linux/installer/module-autologon.sh @@ -0,0 +1,182 @@ +# Oracle VM VirtualBox +# $Id: module-autologon.sh $ +## @file +# VirtualBox Linux Guest Additions installer - autologon module +# + +# +# Copyright (C) 2012-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# SPDX-License-Identifier: GPL-3.0-only +# + +# @todo Document functions and their usage! + +MOD_AUTOLOGON_DEFAULT_LIGHTDM_CONFIG="/etc/lightdm/lightdm.conf" +MOD_AUTOLOGON_DEFAULT_LIGHTDM_GREETER_DIR="/usr/share/xgreeters" + +mod_autologon_init() +{ + echo "Initializing auto-logon support ..." + return 0 +} + +mod_autologon_install_ex() +{ + info "Installing auto-logon support ..." + + ## Parameters: + # Greeter directory. Defaults to /usr/share/xgreeters. + greeter_dir="$1" + # LightDM config. Defaults to /etc/lightdm/lightdm.conf. + lightdm_config="$2" + # Whether to force installation if non-compatible distribution + # is detected. + force="$3" + + # Check for Ubuntu and derivates. @todo Debian? + distros="Ubuntu UbuntuStudio Edubuntu Kubuntu Lubuntu Mythbuntu Xubuntu" + ## @todo Map Linux Mint versions to Ubuntu ones. + + ## @todo Move the distro check to a routine / globals as soon as + ## we have other distribution-dependent stuff. + which lsb_release &>/dev/null + if test "$?" -ne "0"; then + info "Error: lsb_release not found (path set?), skipping auto-logon installation" + return 1 + fi + distro_name=$(lsb_release -si) + distro_ver=$(lsb_release -sr) + + for distro_cur in ${distros}; do + if test "$distro_name" = "$distro_cur"; then + distro_found="true" + break + fi + done + + if test -z "$distro_found"; then + if ! test "$force" = "force"; then + info "Error: Unsupported distribution \"$distro_name\" found, skipping auto-logon installation" + return 1 + fi + info "Warning: Unsupported distribution \"$distro_name\" found" + else + # Do we have Ubuntu 11.10 or greater? + # Use AWK for comparison since we run on plan sh. + echo | awk 'END { exit ( !('"$distro_ver >= 11.10"') ); }' + if test "$?" -ne "0"; then + if ! test "$force" = "force"; then + info "Error: Version $distro_ver of \"$distro_name\" not supported, skipping auto-logon installation" + return 1 + fi + info "Warning: Unsupported \"$distro_name\" version $distro_ver found" + fi + fi + + # Install dependencies (lightdm and FLTK 1.3+) using apt-get. + which apt-get &>/dev/null + if test "$?" -ne "0"; then + info "Error: apt-get not found (path set?), skipping auto-logon installation" + return 1 + fi + info "Checking and installing necessary dependencies ..." + apt-get -qqq -y install libfltk1.3 libfltk-images1.3 || return 1 + apt-get -qqq -y install lightdm || return 1 + + # Check for LightDM config. + if ! test -f "$lightdm_config"; then + info "Error: LightDM config \"$lightdm_config\" not found (LightDM installed?), skipping auto-logon installation" + return 1 + fi + + # Check for /usr/share/xgreeters. + if ! test -d "$greeter_dir"; then + if ! test "$force" = "force"; then + info "Error: Directory \"$greeter_dir\" does not exist, skipping auto-logon installation" + return 1 + fi + info "Warning: Directory \"$greeter_dir\" does not exist, creating it" + mkdir -p -m 755 "$greeter_dir" || return 1 + fi + + # Link to required greeter files into $greeter_dir. + add_symlink "$INSTALLATION_DIR/other/vbox-greeter.desktop" "$greeter_dir/vbox-greeter.desktop" + + # Backup and activate greeter config. + if ! test -f "$lightdm_config.vbox-backup"; then + info "Backing up LightDM configuration file ..." + cp "$lightdm_config" "$lightdm_config.vbox-backup" || return 1 + chmod 644 "$lightdm_config.vbox-backup" || return 1 + fi + sed -i -e 's/^\s*greeter-session\s*=.*/greeter-session=vbox-greeter/g' "$lightdm_config" || return 1 + chmod 644 "$lightdm_config" || return 1 + + info "Auto-logon installation successful" + return 0 +} + +mod_autologon_install() +{ + if [ -z "$MOD_AUTOLOGON_LIGHTDM_GREETER_DIR" ]; then + MOD_AUTOLOGON_LIGHTDM_GREETER_DIR=$MOD_AUTOLOGON_DEFAULT_LIGHTDM_GREETER_DIR + fi + if [ -z "$MOD_AUTOLOGON_LIGHTDM_CONFIG" ]; then + MOD_AUTOLOGON_LIGHTDM_CONFIG=$MOD_AUTOLOGON_DEFAULT_LIGHTDM_CONFIG + fi + + mod_autologon_install_ex "$MOD_AUTOLOGON_LIGHTDM_GREETER_DIR" "$MOD_AUTOLOGON_LIGHTDM_CONFIG" "$MOD_AUTOLOGON_FORCE" + return $? +} + +mod_autologon_pre_uninstall() +{ + echo "Preparing to uninstall auto-logon support ..." + return 0 +} + +mod_autologon_uninstall() +{ + if test -z "$MOD_AUTOLOGON_LIGHTDM_CONFIG"; then + return 0 + fi + info "Un-installing auto-logon support ..." + + # Switch back to original greeter. + if test -f "$MOD_AUTOLOGON_LIGHTDM_CONFIG.vbox-backup"; then + mv "$MOD_AUTOLOGON_LIGHTDM_CONFIG.vbox-backup" "$MOD_AUTOLOGON_LIGHTDM_CONFIG" + if test "$?" -ne "0"; then + info "Warning: Could not restore original LightDM config \"$MOD_AUTOLOGON_LIGHTDM_CONFIG\"" + fi + fi + + # Remove greeter directory (if not empty). + rm "$MOD_AUTOLOGON_LIGHTDM_GREETER_DIR" 2>/dev/null + + info "Auto-logon uninstallation successful" + return 0 +} + +mod_autologon_config_save() +{ + echo " +MOD_AUTOLOGON_LIGHTDM_CONFIG='$MOD_AUTOLOGON_LIGHTDM_CONFIG' +MOD_AUTOLOGON_LIGHTDM_GREETER_DIR='$MOD_AUTOLOGON_LIGHTDM_GREETER_DIR'" +} + diff --git a/src/VBox/Additions/linux/installer/vboxadd-service.sh b/src/VBox/Additions/linux/installer/vboxadd-service.sh new file mode 100755 index 00000000..d3ea8ebe --- /dev/null +++ b/src/VBox/Additions/linux/installer/vboxadd-service.sh @@ -0,0 +1,171 @@ +#!/bin/sh +# $Id: vboxadd-service.sh $ +## @file +# Linux Additions Guest Additions service daemon init script. +# + +# +# Copyright (C) 2006-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# SPDX-License-Identifier: GPL-3.0-only +# + +# X-Conflicts-With is our own invention, which we use when converting to +# a systemd unit. + +# chkconfig: 345 35 65 +# description: VirtualBox Additions service +# +### BEGIN INIT INFO +# Provides: vboxadd-service +# Required-Start: vboxadd +# Required-Stop: vboxadd +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# X-Conflicts-With: systemd-timesyncd.service +# Description: VirtualBox Additions Service +### END INIT INFO + +PATH=$PATH:/bin:/sbin:/usr/sbin +SCRIPTNAME=vboxadd-service.sh + +PIDFILE="/var/run/${SCRIPTNAME}" + +# Preamble for Gentoo +if [ "`which $0`" = "/sbin/rc" ]; then + shift +fi + +begin() +{ + test -n "${2}" && echo "${SCRIPTNAME}: ${1}." + logger -t "${SCRIPTNAME}" "${1}." +} + +succ_msg() +{ + logger -t "${SCRIPTNAME}" "${1}." +} + +fail_msg() +{ + echo "${SCRIPTNAME}: ${1}." >&2 + logger -t "${SCRIPTNAME}" "${1}." +} + +daemon() { + $1 $2 $3 +} + +killproc() { + killall $1 + rm -f $PIDFILE +} + +if which start-stop-daemon >/dev/null 2>&1; then + daemon() { + start-stop-daemon --start --exec $1 -- $2 $3 + } + + killproc() { + start-stop-daemon --stop --retry 2 --exec $@ + } +fi + +binary=/usr/sbin/VBoxService + +testbinary() { + test -x "$binary" || { + echo "Cannot run $binary" + exit 1 + } +} + +vboxaddrunning() { + lsmod | grep -q "vboxguest[^_-]" +} + +start() { + if ! test -f $PIDFILE; then + begin "Starting VirtualBox Guest Addition service" console; + vboxaddrunning || { + echo "VirtualBox Additions module not loaded!" + exit 1 + } + testbinary + daemon $binary --pidfile $PIDFILE > /dev/null + RETVAL=$? + succ_msg "VirtualBox Guest Addition service started" + fi + return $RETVAL +} + +stop() { + if test -f $PIDFILE; then + begin "Stopping VirtualBox Guest Addition service" console; + killproc $binary + RETVAL=$? + if ! pidof VBoxService > /dev/null 2>&1; then + rm -f $PIDFILE + succ_msg "VirtualBox Guest Addition service stopped" + else + fail_msg "VirtualBox Guest Addition service failed to stop" + fi + fi + return $RETVAL +} + +restart() { + stop && start +} + +status() { + echo -n "Checking for VBoxService" + if [ -f $PIDFILE ]; then + echo " ...running" + RETVAL=0 + else + echo " ...not running" + RETVAL=1 + fi + + return $RETVAL +} + +case "$1" in +start) + start + ;; +stop) + stop + ;; +restart) + restart + ;; +status) + status + ;; +setup) + ;; +cleanup) + ;; +*) + echo "Usage: $0 {start|stop|restart|status}" + exit 1 +esac diff --git a/src/VBox/Additions/linux/installer/vboxadd-x11.sh b/src/VBox/Additions/linux/installer/vboxadd-x11.sh new file mode 100755 index 00000000..fd265d34 --- /dev/null +++ b/src/VBox/Additions/linux/installer/vboxadd-x11.sh @@ -0,0 +1,625 @@ +#! /bin/sh +# $Id: vboxadd-x11.sh $ +## @file +# Linux Additions X11 setup init script ($Revision: 155244 $) +# + +# +# Copyright (C) 2006-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# SPDX-License-Identifier: GPL-3.0-only +# + + +# chkconfig: 35 30 70 +# description: VirtualBox Linux Additions kernel modules +# +### BEGIN INIT INFO +# Provides: vboxadd-x11 +# Required-Start: +# Required-Stop: +# Default-Start: +# Default-Stop: +# Description: VirtualBox Linux Additions X11 setup +### END INIT INFO + +PATH=$PATH:/bin:/sbin:/usr/sbin +CONFIG_DIR="/var/lib/VBoxGuestAdditions" +CONFIG="${CONFIG_DIR}/config" +MODPROBE=/sbin/modprobe + +if $MODPROBE -c 2>/dev/null | grep -q '^allow_unsupported_modules *0'; then + MODPROBE="$MODPROBE --allow-unsupported-modules" +fi + +# Find the version of X installed +# The last of the three is for the X.org 6.7 included in Fedora Core 2 +xver=`X -version 2>&1` +x_version=`echo "$xver" | sed -n 's/^X Window System Version \([0-9.]\+\)/\1/p'``echo "$xver" | sed -n 's/^XFree86 Version \([0-9.]\+\)/\1/p'``echo "$xver" | sed -n 's/^X Protocol Version 11, Revision 0, Release \([0-9.]\+\)/\1/p'``echo "$xver" | sed -n 's/^X.Org X Server \([0-9.]\+\)/\1/p'` +x_version_short=`echo "${x_version}" | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/'` +# Version of Redhat or Fedora installed. Needed for setting up selinux policy. +redhat_release=`cat /etc/redhat-release 2> /dev/null` +# Version of OL installed. Needed for blacklisting vboxvideo. +oracle_release=`cat /etc/oracle-release 2> /dev/null` +# All the different possible locations for XFree86/X.Org configuration files +# - how many of these have ever been used? +x11conf_files="/etc/X11/xorg.conf /etc/X11/xorg.conf-4 /etc/X11/.xorg.conf \ + /etc/xorg.conf /usr/etc/X11/xorg.conf-4 /usr/etc/X11/xorg.conf \ + /usr/lib/X11/xorg.conf-4 /usr/lib/X11/xorg.conf /etc/X11/XF86Config-4 \ + /etc/X11/XF86Config /etc/XF86Config /usr/X11R6/etc/X11/XF86Config-4 \ + /usr/X11R6/etc/X11/XF86Config /usr/X11R6/lib/X11/XF86Config-4 \ + /usr/X11R6/lib/X11/XF86Config" + +# Preamble for Gentoo +if [ "`which $0`" = "/sbin/rc" ]; then + shift +fi + +dev=/dev/vboxguest +userdev=/dev/vboxuser +owner=vboxadd +group=1 + +fail() +{ + echo "${1}" >&2 + exit 1 +} + +# Install an X11 desktop startup application. The application should be a shell script. +# Its name should be purely alphanumeric and should start with a two digit number (preferably +# 98 or thereabouts) to indicate its place in the Debian Xsession startup order. +# +# syntax: install_x11_startup_app app desktop service_name +install_x11_startup_app() { + self="install_x11_startup_app" + app_src=$1 + desktop_src=$2 + service_name=$3 + alt_command=$4 + test -r "$app_src" || fail "$self: no script given" + test -r "$desktop_src" || fail "$self: no desktop file given" + test -n "$service_name" || fail "$self: no service given" + test -n "$alt_command" || fail "$self: no service given" + app_dest=`basename $app_src sh` + app_dest_sh=`basename $app_src sh`.sh + desktop_dest=`basename $desktop_src` + found=0 + x11_autostart="/etc/xdg/autostart" + kde_autostart="/usr/share/autostart" + redhat_dir=/etc/X11/Xsession.d + mandriva_dir=/etc/X11/xinit.d + debian_dir=/etc/X11/xinit/xinitrc.d + if [ -d "$mandriva_dir" -a -w "$mandriva_dir" -a -x "$mandriva_dir" ] + then + install -m 0644 $app_src "$mandriva_dir/$app_dest" + found=1 + fi + if [ -d "$x11_autostart" -a -w "$x11_autostart" -a -x "$x11_autostart" ] + then + install -m 0644 $desktop_src "$x11_autostart/$desktop_dest" + found=1 + fi + if [ -d "$kde_autostart" -a -w "$kde_autostart" -a -x "$kde_autostart" ] + then + install -m 0644 $desktop_src "$kde_autostart/$desktop_dest" + found=1 + fi + if [ -d "$redhat_dir" -a -w "$redhat_dir" -a -x "$redhat_dir" ] + then + install -m 0644 $app_src "$redhat_dir/$app_dest" + found=1 + fi + if [ -d "$debian_dir" -a -w "$debian_dir" -a -x "$debian_dir" ] + then + install -m 0755 $app_src "$debian_dir/$app_dest_sh" + found=1 + fi + if [ $found -eq 1 ]; then + return 0 + fi + cat >&2 << EOF +Could not set up the $service_name desktop service. +To start it at log-in for a given user, add the command $alt_command +to the file .xinitrc in their home directory. +EOF + return 1 +} + + +start() +{ + # Todo: check configuration and correct it if necessary + return 0 +} + +stop() +{ + return 0 +} + +restart() +{ + stop && start + return 0 +} + +setup_opengl() +{ + # Install the guest OpenGL drivers. For now we don't support + # multi-architecture installations + rm -f /etc/ld.so.conf.d/00vboxvideo.conf + rm -Rf /var/lib/VBoxGuestAdditions/lib + if /usr/bin/VBoxClient --check3d 2>/dev/null; then + mkdir -p /var/lib/VBoxGuestAdditions/lib + ln -sf "${INSTALL_DIR}/lib/VBoxOGL.so" /var/lib/VBoxGuestAdditions/lib/libGL.so.1 + # SELinux for the OpenGL libraries, so that gdm can load them during the + # acceleration support check. This prevents an "Oh no, something has gone + # wrong!" error when starting EL7 guests. + if test -e /etc/selinux/config; then + if command -v semanage > /dev/null; then + semanage fcontext -a -t lib_t "/var/lib/VBoxGuestAdditions/lib/libGL.so.1" + fi + # This is needed on old Fedora/Redhat systems. No one remembers which. + chcon -h -t lib_t "/var/lib/VBoxGuestAdditions/lib/libGL.so.1" 2>/dev/null + fi + echo "/var/lib/VBoxGuestAdditions/lib" > /etc/ld.so.conf.d/00vboxvideo.conf + fi + ldconfig +} + +setup() +{ + if test -r "${CONFIG}"; then + . "${CONFIG}" + else + fail "Configuration file ${CONFIG} not found" + fi + test -n "$INSTALL_DIR" -a -n "$INSTALL_VER" || + fail "Configuration file ${CONFIG} not complete" + lib_dir="${INSTALL_DIR}/other" + test -x "${lib_dir}" || + fail "Invalid Guest Additions configuration found." + # By default we want to configure X + dox11config="true" + # By default, we want to run our xorg.conf setup script + setupxorgconf="true" + # All but the oldest supported X servers can automatically set up the + # keyboard driver. + autokeyboard="--autoKeyboard" + # On more recent servers our kernel mouse driver will be used + # automatically + automouse="--autoMouse" + # We need to tell our xorg.conf hacking script whether /dev/psaux exists + nopsaux="--nopsaux" + case "`uname -r`" in 2.4.*) + test -c /dev/psaux && nopsaux="";; + esac + # Should we use the VMSVGA driver instead of VBoxVideo? + if grep 80eebeef /proc/bus/pci/devices > /dev/null; then + vmsvga="" + elif grep 15ad0405 /proc/bus/pci/devices > /dev/null; then + vmsvga="--vmsvga" + else + dox11config="" + fi + # The video driver to install for X.Org 6.9+ + vboxvideo_src= + # The mouse driver to install for X.Org 6.9+ + vboxmouse_src= + # The driver extension + driver_ext=".so" + # The configuration file we generate if no original was found but we need + # one. + main_cfg="/etc/X11/xorg.conf" + + modules_dir=`X -showDefaultModulePath 2>&1` || modules_dir= + if [ -z "$modules_dir" ]; then + for dir in /usr/lib64/xorg/modules /usr/lib/xorg/modules /usr/X11R6/lib64/modules /usr/X11R6/lib/modules /usr/X11R6/lib/X11/modules; do + if [ -d $dir ]; then + modules_dir=$dir + break + fi + done + fi + + case "${x_version}" in + 4.* | 6.* | 7.* | 1.?.* | 1.1[0-6].* ) + blacklist_vboxvideo="yes" + ;; + esac + case "$oracle_release" in + Oracle*release\ 6.* ) + # relevant for OL6/UEK4 but cannot hurt for other kernels + blacklist_vboxvideo="yes" + esac + if test -n "${blacklist_vboxvideo}"; then + test -d /etc/modprobe.d && + echo "blacklist vboxvideo" > /etc/modprobe.d/blacklist-vboxvideo.conf + else + test -f /etc/modprobe.d/blacklist-vboxvideo.conf && + rm -f /etc/modprobe.d/blacklist-vboxvideo.conf + # We do not want to load the driver if X.Org Server is already + # running, as without a driver the server will touch the hardware + # directly, causing problems. + ps -Af | grep -q '[X]org' || ${MODPROBE} -q vboxvideo + fi + + test -z "$x_version" -o -z "$modules_dir" && + { + echo "Could not find the X.Org or XFree86 Window System, skipping." >&2 + exit 0 + } + + # openSUSE 10.3 shipped X.Org 7.2 with X.Org Server 1.3, but didn't + # advertise the fact. + if grep -q '10\.3' /etc/SuSE-release 2>/dev/null; then + case $x_version in 7.2.*) + x_version=1.3.0;; + esac + fi + case $x_version in + 1.*.99.* ) + echo "Warning: unsupported pre-release version of X.Org Server installed. Not installing the X.Org drivers." >&2 + dox11config="" + ;; + 1.11.* ) + xserver_version="X.Org Server 1.11" + vboxvideo_src=vboxvideo_drv_111.so + test "$system" = "redhat" && test -z "${vmsvga}" || setupxorgconf="" + ;; + 1.10.* ) + xserver_version="X.Org Server 1.10" + vboxvideo_src=vboxvideo_drv_110.so + test "$system" = "redhat" && test -z "${vmsvga}" || setupxorgconf="" + ;; + 1.9.* ) + xserver_version="X.Org Server 1.9" + vboxvideo_src=vboxvideo_drv_19.so + # Fedora 14 to 16 patched out vboxvideo detection + test "$system" = "redhat" && test -z "${vmsvga}" || setupxorgconf="" + ;; + 1.8.* ) + xserver_version="X.Org Server 1.8" + vboxvideo_src=vboxvideo_drv_18.so + # Fedora 13 shipped without vboxvideo detection + test "$system" = "redhat" && test -z "${vmsvga}" || setupxorgconf="" + ;; + 1.7.* ) + xserver_version="X.Org Server 1.7" + vboxvideo_src=vboxvideo_drv_17.so + setupxorgconf="" + ;; + 1.6.* ) + xserver_version="X.Org Server 1.6" + vboxvideo_src=vboxvideo_drv_16.so + vboxmouse_src=vboxmouse_drv_16.so + # SUSE SLE* with X.Org 1.6 does not do input autodetection; + # openSUSE does. + if grep -q -E '^SLE[^ ]' /etc/SuSE-brand 2>/dev/null; then + automouse="" + else + test "$system" = "suse" && setupxorgconf="" + fi + ;; + 1.5.* ) + xserver_version="X.Org Server 1.5" + vboxvideo_src=vboxvideo_drv_15.so + vboxmouse_src=vboxmouse_drv_15.so + # Historical note: SUSE with X.Org Server 1.5 disabled automatic + # mouse configuration and was handled specially. However since our + # kernel driver seems to have problems with X.Org Server 1.5 anyway + # we just create an X.Org configuration file and use the user space + # one generally, no longer just for SUSE. + automouse="" + ;; + 1.4.* ) + xserver_version="X.Org Server 1.4" + vboxvideo_src=vboxvideo_drv_14.so + vboxmouse_src=vboxmouse_drv_14.so + automouse="" + ;; + 1.3.* ) + # This was the first release which gave the server version number + # rather than the X11 release version when you did 'X -version'. + xserver_version="X.Org Server 1.3" + vboxvideo_src=vboxvideo_drv_13.so + vboxmouse_src=vboxmouse_drv_13.so + automouse="" + ;; + 7.1.* | 7.2.* ) + xserver_version="X.Org 7.1" + vboxvideo_src=vboxvideo_drv_71.so + vboxmouse_src=vboxmouse_drv_71.so + automouse="" + ;; + 6.9.* | 7.0.* ) + xserver_version="X.Org 6.9/7.0" + vboxvideo_src=vboxvideo_drv_70.so + vboxmouse_src=vboxmouse_drv_70.so + automouse="" + ;; + 6.7* | 6.8.* | 4.2.* | 4.3.* ) + # As the module binaries are the same we use one text for these + # four server versions. + xserver_version="XFree86 4.2/4.3 and X.Org 6.7/6.8" + driver_ext=.o + vboxvideo_src=vboxvideo_drv.o + vboxmouse_src=vboxmouse_drv.o + automouse="" + autokeyboard="" + case $x_version in + 6.8.* ) + autokeyboard="--autoKeyboard" + ;; + 4.2.* | 4.3.* ) + main_cfg="/etc/X11/XF86Config" + ;; + esac + ;; + 1.12.* | 1.13.* | 1.14.* | 1.15.* | 1.16.* | 1.17.* | 1.18.* ) + xserver_version="X.Org Server ${x_version_short}" + vboxvideo_src=vboxvideo_drv_`echo ${x_version_short} | sed 's/\.//'`.so + setupxorgconf="" + test -f "${lib_dir}/${vboxvideo_src}" || + { + echo "Warning: unknown version of the X Window System installed. Not installing X Window System drivers." >&2 + dox11config="" + vboxvideo_src="" + } + ;; + * ) + # For anything else, assume kernel drivers. + dox11config="" + ;; + esac + test -n "${dox11config}" && + echo "Installing $xserver_version modules" >&2 + case "$vboxvideo_src" in + ?*) + ln -s "${lib_dir}/$vboxvideo_src" "$modules_dir/drivers/vboxvideo_drv$driver_ext.new" && + mv "$modules_dir/drivers/vboxvideo_drv$driver_ext.new" "$modules_dir/drivers/vboxvideo_drv$driver_ext";; + *) + rm "$modules_dir/drivers/vboxvideo_drv$driver_ext" 2>/dev/null + esac + case "$vboxmouse_src" in + ?*) + ln -s "${lib_dir}/$vboxmouse_src" "$modules_dir/input/vboxmouse_drv$driver_ext.new" && + mv "$modules_dir/input/vboxmouse_drv$driver_ext.new" "$modules_dir/input/vboxmouse_drv$driver_ext";; + *) + rm "$modules_dir/input/vboxmouse_drv$driver_ext" 2>/dev/null + esac + + if test -n "$dox11config"; then + # Certain Ubuntu/Debian versions use a special PCI-id file to identify + # video drivers. Some versions have the directory and don't use it. + # Those versions can autoload vboxvideo though, so we don't need to + # hack the configuration file for them. + test "$system" = "debian" -a -d /usr/share/xserver-xorg/pci && + { + rm -f "/usr/share/xserver-xorg/pci/vboxvideo.ids" + ln -s "${lib_dir}/vboxvideo.ids" /usr/share/xserver-xorg/pci 2>/dev/null + test -n "$automouse" && setupxorgconf="" + } + + # Do the XF86Config/xorg.conf hack for those versions that require it + configured="" + generated="" + if test -n "$setupxorgconf"; then + for i in $x11conf_files; do + if test -r "$i"; then + if grep -q "VirtualBox generated" "$i"; then + generated="$generated `printf "$i\n"`" + else + "${lib_dir}/x11config.sh" $autokeyboard $automouse $nopsaux $vmsvga "$i" + fi + configured="true" + fi + # Timestamp, so that we can see if the config file is changed + # by someone else later + test -r "$i.vbox" && touch "$i.vbox" + done + # X.Org Server 1.5 and 1.6 can detect hardware they know, but they + # need a configuration file for VBoxVideo. + nobak_cfg="`expr "${main_cfg}" : '\([^.]*\)'`.vbox.nobak" + if test -z "$configured"; then + touch "$main_cfg" + "${lib_dir}/x11config.sh" $autokeyboard $automouse $nopsaux $vmsvga --noBak "$main_cfg" + touch "${nobak_cfg}" + fi + fi + test -n "$generated" && + cat >&2 << EOF +The following X.Org/XFree86 configuration files were originally generated by +the VirtualBox Guest Additions and were not modified: + +$generated + +EOF + tty >/dev/null && cat << EOF +You may need to restart the Window System (or just restart the guest system) +to enable the Guest Additions. + +EOF + fi + + case "$redhat_release" in + # Install selinux policy for Fedora 7 and 8 to allow the X server to + # open device files + Fedora\ release\ 7* | Fedora\ release\ 8* ) + semodule -i "${lib_dir}/vbox_x11.pp" > /dev/null 2>&1 + ;; + # Similar for the accelerated graphics check on Fedora 15 + Fedora\ release\ 15* ) + semodule -i "${lib_dir}/vbox_accel.pp" > /dev/null 2>&1 + ;; + esac + + # Install selinux policy for Fedora 8 to allow the X server to + # open our drivers + case "$redhat_release" in + Fedora\ release\ 8* ) + chcon -u system_u -t lib_t "${lib_dir}"/*.so 2>/dev/null + ;; + esac + + # Our logging code generates some glue code on 32-bit systems. At least F10 + # needs a rule to allow this. Send all output to /dev/null in case this is + # completely irrelevant on the target system. + # chcon is needed on old Fedora/Redhat systems. No one remembers which. + chcon -t unconfined_execmem_exec_t '/usr/bin/VBoxClient' > /dev/null 2>&1 + semanage fcontext -a -t unconfined_execmem_exec_t '/usr/bin/VBoxClient' > /dev/null 2>&1 + + # And set up VBoxClient to start when the X session does + install_x11_startup_app "${lib_dir}/98vboxadd-xclient" "${lib_dir}/vboxclient.desktop" VBoxClient VBoxClient-all || + fail "Failed to set up VBoxClient to start automatically." + ln -s "${lib_dir}/98vboxadd-xclient" /usr/bin/VBoxClient-all 2>/dev/null + case "${x_version}" in 4.* | 6.* | 7.* | 1.?.* | 1.1* ) + setup_opengl + esac + # Try enabling VMSVGA drm device resizing. + #VBoxClient --vmsvga +} + +cleanup() +{ + # Restore xorg.conf files as far as possible + # List of generated files which have been changed since we generated them + newer="" + # Are we dealing with a legacy information which didn't support + # uninstallation? + legacy="" + # Do any of the restored configuration files still reference our drivers? + failed="" + # Have we encountered a "nobak" configuration file which means that there + # is no original file to restore? + nobak="" + test -r "$CONFIG_DIR/$CONFIG" || legacy="true" + for main_cfg in "/etc/X11/xorg.conf" "/etc/X11/XF86Config"; do + nobak_cfg="`expr "${main_cfg}" : '\([^.]*\)'`.vbox.nobak" + if test -r "${nobak_cfg}"; then + test -r "${main_cfg}" && + if test -n "${legacy}" -o ! "${nobak_cfg}" -ot "${main_cfg}"; then + rm -f "${nobak_cfg}" "${main_cfg}" + else + newer="${newer}`printf " ${main_cfg} (no original)\n"`" + fi + nobak="true" + fi + done + if test -z "${nobak}"; then + for i in $x11conf_files; do + if test -r "$i.vbox"; then + if test ! "$i" -nt "$i.vbox" -o -n "$legacy"; then + mv -f "$i.vbox" "$i" + grep -q -E 'vboxvideo|vboxmouse' "$i" && + failed="$failed`printf " $i\n"`" + else + newer="$newer`printf " $i ($i.vbox)\n"`" + fi + fi + done + fi + test -n "$newer" && cat >&2 << EOF + +The following X.Org/XFree86 configuration files were not restored, as they may +have been changed since they were generated by the VirtualBox Guest Additions. +You may wish to restore these manually. The file name in brackets is the +original version. + +$newer + +EOF + test -n "$failed" && cat >&2 << EOF + +The following X.Org/XFree86 configuration files were restored, but still +contain references to the Guest Additions drivers. You may wish to check and +possibly correct the restored configuration files to be sure that the server +will continue to work after it is restarted. + +$failed + +EOF + + # Remove X.Org drivers + modules_dir=`X -showDefaultModulePath 2>&1` || modules_dir= + if [ -z "$modules_dir" ]; then + for dir in /usr/lib64/xorg/modules /usr/lib/xorg/modules /usr/X11R6/lib64/modules /usr/X11R6/lib/modules /usr/X11R6/lib/X11/modules; do + if [ -d $dir ]; then + modules_dir=$dir + break + fi + done + fi + rm -f "$modules_dir/drivers/vboxvideo_drv"* 2>/dev/null + rm -f "$modules_dir/input/vboxmouse_drv"* 2>/dev/null + + # Remove the link to vboxvideo_dri.so + for dir in /usr/lib/dri /usr/lib32/dri /usr/lib64/dri \ + /usr/lib/xorg/modules/dri /usr/lib32/xorg/modules/dri \ + /usr/lib64/xorg/modules/dri /usr/lib/i386-linux-gnu/dri \ + /usr/lib/x86_64-linux-gnu/dri; do + if [ -d $dir ]; then + rm -f "$dir/vboxvideo_dri.so" 2>/dev/null + fi + done + + # Remove VBoxClient autostart files + rm /etc/X11/Xsession.d/98vboxadd-xclient 2>/dev/null + rm /etc/X11/xinit.d/98vboxadd-xclient 2>/dev/null + rm /etc/X11/xinit/xinitrc.d/98vboxadd-xclient.sh 2>/dev/null + rm /etc/xdg/autostart/vboxclient.desktop 2>/dev/null + rm /usr/share/autostart/vboxclient.desktop 2>/dev/null + rm /usr/bin/VBoxClient-all 2>/dev/null + + # Remove other files + rm /usr/share/xserver-xorg/pci/vboxvideo.ids 2>/dev/null + return 0 +} + +dmnstatus() +{ + /bin/true +} + +case "$1" in +start) + start + ;; +stop) + stop + ;; +restart) + restart + ;; +setup) + setup + ;; +cleanup) + cleanup + ;; +status) + dmnstatus + ;; +*) + echo "Usage: $0 {start|stop|restart|status}" + exit 1 +esac + +exit diff --git a/src/VBox/Additions/linux/installer/vboxadd.sh b/src/VBox/Additions/linux/installer/vboxadd.sh new file mode 100755 index 00000000..b6ca1a4f --- /dev/null +++ b/src/VBox/Additions/linux/installer/vboxadd.sh @@ -0,0 +1,1325 @@ +#! /bin/sh +# $Id: vboxadd.sh $ +## @file +# Linux Additions kernel module init script ($Revision: 158810 $) +# + +# +# Copyright (C) 2006-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# SPDX-License-Identifier: GPL-3.0-only +# + +# X-Start-Before is a Debian Addition which we use when converting to +# a systemd unit. X-Service-Type is our own invention, also for systemd. + +# chkconfig: 345 10 90 +# description: VirtualBox Linux Additions kernel modules +# +### BEGIN INIT INFO +# Provides: vboxadd +# Required-Start: +# Required-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# X-Start-Before: display-manager +# X-Service-Type: oneshot +# Description: VirtualBox Linux Additions kernel modules +### END INIT INFO + +## @todo This file duplicates a lot of script with vboxdrv.sh. When making +# changes please try to reduce differences between the two wherever possible. + +# Testing: +# * Should fail if the configuration file is missing or missing INSTALL_DIR or +# INSTALL_VER entries. +# * vboxadd, vboxsf and vboxdrmipc user groups should be created if they do not exist - test +# by removing them before installing. +# * Shared folders can be mounted and auto-mounts accessible to vboxsf group, +# including on recent Fedoras with SELinux. +# * Setting INSTALL_NO_MODULE_BUILDS inhibits modules and module automatic +# rebuild script creation; otherwise modules, user, group, rebuild script, +# udev rule and shared folder mount helper should be created/set up. +# * Setting INSTALL_NO_MODULE_BUILDS inhibits module load and unload on start +# and stop. +# * Uninstalling the Additions and re-installing them does not trigger warnings. + +export LC_ALL=C +PATH=$PATH:/bin:/sbin:/usr/sbin +PACKAGE=VBoxGuestAdditions +MODPROBE=/sbin/modprobe +OLDMODULES="vboxguest vboxadd vboxsf vboxvfs vboxvideo" +SERVICE="VirtualBox Guest Additions" +VBOXSERVICE_PIDFILE="/var/run/vboxadd-service.sh" +## systemd logs information about service status, otherwise do that ourselves. +QUIET= +test -z "${TARGET_VER}" && TARGET_VER=`uname -r` + +export VBOX_KBUILD_TYPE +export USERNAME + +setup_log() +{ + test -z "${LOG}" || return 0 + # Rotate log files + LOG="/var/log/vboxadd-setup.log" + mv -f "${LOG}.3" "${LOG}.4" 2>/dev/null + mv -f "${LOG}.2" "${LOG}.3" 2>/dev/null + mv -f "${LOG}.1" "${LOG}.2" 2>/dev/null + mv -f "${LOG}" "${LOG}.1" 2>/dev/null +} + +if $MODPROBE -c 2>/dev/null | grep -q '^allow_unsupported_modules *0'; then + MODPROBE="$MODPROBE --allow-unsupported-modules" +fi + +# Preamble for Gentoo +if [ "`which $0`" = "/sbin/rc" ]; then + shift +fi + +begin() +{ + test -n "${QUIET}" || echo "${SERVICE}: ${1}" +} + +info() +{ + if test -z "${QUIET}"; then + echo "${SERVICE}: $1" | fold -s + else + echo "$1" | fold -s + fi +} + +# When script is running as non-root, it does not have access to log +# files in /var. In this case, lets print error message to stdout and +# exit with bad status. +early_fail() +{ + echo "$1" >&2 + exit 1 +} + +fail() +{ + log "${1}" + echo "${SERVICE}: $1" >&2 + echo "The log file $LOG may contain further information." >&2 + exit 1 +} + +log() +{ + setup_log + echo "${1}" >> "${LOG}" +} + +module_build_log() +{ + log "Error building the module. Build output follows." + echo "" + echo "${1}" >> "${LOG}" +} + +dev=/dev/vboxguest +userdev=/dev/vboxuser +config=/var/lib/VBoxGuestAdditions/config +user_config=/etc/virtualbox-guest-additions.conf +owner=vboxadd +group=1 + +# Include custom user configuration file. +[ -r "$user_config" ] && . "$user_config" + +if test -r $config; then + . $config +else + fail "Configuration file $config not found" +fi +test -n "$INSTALL_DIR" -a -n "$INSTALL_VER" || + fail "Configuration file $config not complete" +MODULE_SRC="$INSTALL_DIR/src/vboxguest-$INSTALL_VER" +BUILDINTMP="$MODULE_SRC/build_in_tmp" + +# Path to VBoxService control script. +VBOX_SERVICE_SCRIPT="/sbin/rcvboxadd-service" + +# Attempt to detect VirtualBox Guest Additions version and revision information. +VBOXCONTROL="${INSTALL_DIR}/bin/VBoxControl" +VBOX_VERSION="`"$VBOXCONTROL" --version | cut -d r -f1`" +[ -n "$VBOX_VERSION" ] || VBOX_VERSION='unknown' +VBOX_REVISION="r`"$VBOXCONTROL" --version | cut -d r -f2`" +[ "$VBOX_REVISION" != "r" ] || VBOX_REVISION='unknown' + +# Returns if the vboxguest module is running or not. +# +# Returns true if vboxguest module is running, false if not. +running_vboxguest() +{ + lsmod | grep -q "vboxguest[^_-]" +} + +# Returns if the vboxadd module is running or not. +# +# Returns true if vboxadd module is running, false if not. +running_vboxadd() +{ + lsmod | grep -q "vboxadd[^_-]" +} + +# Returns if the vboxsf module is running or not. +# +# Returns true if vboxsf module is running, false if not. +running_vboxsf() +{ + lsmod | grep -q "vboxsf[^_-]" +} + +# Returns if the vboxvideo module is running or not. +# +# Returns true if vboxvideo module is running, false if not. +running_vboxvideo() +{ + lsmod | grep -q "vboxvideo[^_-]" +} + +# Returns if a specific module is running or not. +# +# Input $1: Module name to check running status for. +# +# Returns true if the module is running, false if not. +running_module() +{ + lsmod | grep -q "$1" +} + +# Returns the version string of a currently running kernel module. +# +# Input $1: Module name to check. +# +# Returns the module version string if found, or none if not found. +running_module_version() +{ + mod="$1" + version_string_path="/sys/module/"$mod"/version" + + [ -n "$mod" ] || return + if [ -r "$version_string_path" ]; then + cat "$version_string_path" + else + echo "unknown" + fi +} + +# Checks if a loaded kernel module version matches to the currently installed Guest Additions version and revision. +# +# Input $1: Module name to check. +# +# Returns "1" if the module matches the installed Guest Additions, or none if not. +check_running_module_version() +{ + mod=$1 + expected="$VBOX_VERSION $VBOX_REVISION" + + [ -n "$mod" ] || return + [ -n "$expected" ] || return + + [ "$expected" = "$(running_module_version "$mod")" ] || return +} + +do_vboxguest_non_udev() +{ + if [ ! -c $dev ]; then + maj=`sed -n 's;\([0-9]\+\) vboxguest;\1;p' /proc/devices` + if [ ! -z "$maj" ]; then + min=0 + else + min=`sed -n 's;\([0-9]\+\) vboxguest;\1;p' /proc/misc` + if [ ! -z "$min" ]; then + maj=10 + fi + fi + test -n "$maj" || { + rmmod vboxguest 2>/dev/null + fail "Cannot locate the VirtualBox device" + } + + mknod -m 0664 $dev c $maj $min || { + rmmod vboxguest 2>/dev/null + fail "Cannot create device $dev with major $maj and minor $min" + } + fi + chown $owner:$group $dev 2>/dev/null || { + rm -f $dev 2>/dev/null + rm -f $userdev 2>/dev/null + rmmod vboxguest 2>/dev/null + fail "Cannot change owner $owner:$group for device $dev" + } + + if [ ! -c $userdev ]; then + maj=10 + min=`sed -n 's;\([0-9]\+\) vboxuser;\1;p' /proc/misc` + if [ ! -z "$min" ]; then + mknod -m 0666 $userdev c $maj $min || { + rm -f $dev 2>/dev/null + rmmod vboxguest 2>/dev/null + fail "Cannot create device $userdev with major $maj and minor $min" + } + chown $owner:$group $userdev 2>/dev/null || { + rm -f $dev 2>/dev/null + rm -f $userdev 2>/dev/null + rmmod vboxguest 2>/dev/null + fail "Cannot change owner $owner:$group for device $userdev" + } + fi + fi +} + +restart() +{ + stop && start + return 0 +} + +## Updates the initramfs. Debian and Ubuntu put the graphics driver in, and +# need the touch(1) command below. Everyone else that I checked just need +# the right module alias file from depmod(1) and only use the initramfs to +# load the root filesystem, not the boot splash. update-initramfs works +# for the first two and dracut for every one else I checked. We are only +# interested in distributions recent enough to use the KMS vboxvideo driver. +update_initramfs() +{ + ## kernel version to update for. + version="${1}" + depmod "${version}" + rm -f "/lib/modules/${version}/initrd/vboxvideo" + test ! -d "/lib/modules/${version}/initrd" || + test ! -f "/lib/modules/${version}/misc/vboxvideo.ko" || + touch "/lib/modules/${version}/initrd/vboxvideo" + + # Systems without systemd-inhibit probably don't need their initramfs + # rebuild here anyway. + type systemd-inhibit >/dev/null 2>&1 || return + if type dracut >/dev/null 2>&1; then + systemd-inhibit --why="Installing VirtualBox Guest Additions" \ + dracut -f --kver "${version}" + elif type update-initramfs >/dev/null 2>&1; then + systemd-inhibit --why="Installing VirtualBox Guest Additions" \ + update-initramfs -u -k "${version}" + fi +} + +# Removes any existing VirtualBox guest kernel modules from the disk, but not +# from the kernel as they may still be in use +cleanup_modules() +{ + # Needed for Ubuntu and Debian, see update_initramfs + rm -f /lib/modules/*/initrd/vboxvideo + for i in /lib/modules/*/misc; do + KERN_VER="${i%/misc}" + KERN_VER="${KERN_VER#/lib/modules/}" + unset do_update + for j in ${OLDMODULES}; do + for mod_ext in ko ko.gz ko.xz ko.zst; do + test -f "${i}/${j}.${mod_ext}" && do_update=1 && rm -f "${i}/${j}.${mod_ext}" + done + done + test -z "$do_update" || update_initramfs "$KERN_VER" + # Remove empty /lib/modules folders which may have been kept around + rmdir -p "${i}" 2>/dev/null || true + unset keep + for j in /lib/modules/"${KERN_VER}"/*; do + name="${j##*/}" + test -d "${name}" || test "${name%%.*}" != modules && keep=1 + done + if test -z "${keep}"; then + rm -rf /lib/modules/"${KERN_VER}" + rm -f /boot/initrd.img-"${KERN_VER}" + fi + done + for i in ${OLDMODULES}; do + # We no longer support DKMS, remove any leftovers. + rm -rf "/var/lib/dkms/${i}"* + done + rm -f /etc/depmod.d/vboxvideo-upstream.conf +} + +# Secure boot state. +case "`mokutil --sb-state 2>/dev/null`" in + *"disabled in shim"*) unset HAVE_SEC_BOOT;; + *"SecureBoot enabled"*) HAVE_SEC_BOOT=true;; + *) unset HAVE_SEC_BOOT;; +esac +# So far we can only sign modules on Ubuntu and on Debian 10 and later. +DEB_PUB_KEY=/var/lib/shim-signed/mok/MOK.der +DEB_PRIV_KEY=/var/lib/shim-signed/mok/MOK.priv +# Check if key already enrolled. +unset HAVE_DEB_KEY +case "`mokutil --test-key "$DEB_PUB_KEY" 2>/dev/null`" in + *"is already"*) DEB_KEY_ENROLLED=true;; + *) unset DEB_KEY_ENROLLED;; +esac + +# Checks if update-secureboot-policy tool supports required commandline options. +update_secureboot_policy_supports() +{ + opt_name="$1" + [ -n "$opt_name" ] || return + + [ -z "$(update-secureboot-policy --help 2>&1 | grep "$opt_name")" ] && return + echo "1" +} + +HAVE_UPDATE_SECUREBOOT_POLICY_TOOL= +if type update-secureboot-policy >/dev/null 2>&1; then + [ "$(update_secureboot_policy_supports new-key)" = "1" -a "$(update_secureboot_policy_supports enroll-key)" = "1" ] && \ + HAVE_UPDATE_SECUREBOOT_POLICY_TOOL=true +fi + +# Reads kernel configuration option. +kernel_get_config_opt() +{ + kern_ver="$1" + opt_name="$2" + + [ -n "$kern_ver" ] || return + [ -n "$opt_name" ] || return + + # Check if there is a kernel tool which can extract config option. + if test -x /lib/modules/"$kern_ver"/build/scripts/config; then + /lib/modules/"$kern_ver"/build/scripts/config \ + --file /lib/modules/"$kern_ver"/build/.config \ + --state "$opt_name" 2>/dev/null + elif test -f /lib/modules/"$kern_ver"/build/.config; then + # Extract config option manually. + grep "$opt_name=" /lib/modules/"$kern_ver"/build/.config | sed -e "s/^$opt_name=//" -e "s/\"//g" + fi +} + +# Reads CONFIG_MODULE_SIG_HASH from kernel config. +kernel_module_sig_hash() +{ + kern_ver="$1" + [ -n "$kern_ver" ] || return + + kernel_get_config_opt "$kern_ver" "CONFIG_MODULE_SIG_HASH" +} + +# Returns "1" if kernel module signature hash algorithm +# is supported by us. Or empty string otherwise. +module_sig_hash_supported() +{ + sig_hashalgo="$1" + [ -n "$sig_hashalgo" ] || return + + # Go through supported list. + [ "$sig_hashalgo" = "sha1" \ + -o "$sig_hashalgo" = "sha224" \ + -o "$sig_hashalgo" = "sha256" \ + -o "$sig_hashalgo" = "sha384" \ + -o "$sig_hashalgo" = "sha512" ] || return + + echo "1" +} + +# Check if kernel configuration requires modules signature. +kernel_requires_module_signature() +{ + kern_ver="$1" + vbox_sys_lockdown_path="/sys/kernel/security/lockdown" + + [ -n "$kern_ver" ] || return + + requires="" + # We consider that if kernel is running in the following configurations, + # it will require modules to be signed. + if [ "$(kernel_get_config_opt "$kern_ver" "CONFIG_MODULE_SIG")" = "y" ]; then + + # Modules signature verification is hardcoded in kernel config. + [ "$(kernel_get_config_opt "$kern_ver" "CONFIG_MODULE_SIG_FORCE")" = "y" ] && requires="1" + + # Unsigned modules loading is restricted by "lockdown" feature in runtime. + if [ "$(kernel_get_config_opt "$kern_ver" "CONFIG_LOCK_DOWN_KERNEL")" = "y" \ + -o "$(kernel_get_config_opt "$kern_ver" "CONFIG_SECURITY_LOCKDOWN_LSM")" = "y" \ + -o "$(kernel_get_config_opt "$kern_ver" "CONFIG_SECURITY_LOCKDOWN_LSM_EARLY")" = "y" ]; then + + # Once lockdown level is set to something different from "none" (e.g., "integrity" + # or "confidentiality"), kernel will reject unsigned modules loading. + if [ -r "$vbox_sys_lockdown_path" ]; then + [ -n "$(cat "$vbox_sys_lockdown_path" | grep "\[integrity\]")" ] && requires="1" + [ -n "$(cat "$vbox_sys_lockdown_path" | grep "\[confidentiality\]")" ] && requires="1" + fi + + # This configuration is used by a number of modern Linux distributions and restricts + # unsigned modules loading when Secure Boot mode is enabled. + [ "$(kernel_get_config_opt "$kern_ver" "CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT")" = "y" -a -n "$HAVE_SEC_BOOT" ] && requires="1" + fi + fi + + [ -n "$requires" ] && echo "1" +} + +sign_modules() +{ + KERN_VER="$1" + test -n "$KERN_VER" || return 1 + + # Make list of mudules to sign. + MODULE_LIST="vboxguest vboxsf" + # vboxvideo might not present on for older kernels. + [ -f "/lib/modules/"$KERN_VER"/misc/vboxvideo.ko" ] && MODULE_LIST="$MODULE_LIST vboxvideo" + + # Sign kernel modules if kernel configuration requires it. + if test "$(kernel_requires_module_signature $KERN_VER)" = "1"; then + begin "Signing VirtualBox Guest Additions kernel modules" + + # Generate new signing key if needed. + [ -n "$HAVE_UPDATE_SECUREBOOT_POLICY_TOOL" ] && SHIM_NOTRIGGER=y update-secureboot-policy --new-key + + # Check if signing keys are in place. + if test ! -f "$DEB_PUB_KEY" || ! test -f "$DEB_PRIV_KEY"; then + # update-secureboot-policy tool present in the system, but keys were not generated. + [ -n "$HAVE_UPDATE_SECUREBOOT_POLICY_TOOL" ] && info " + +update-secureboot-policy tool does not generate signing keys +in your distribution, see below on how to generate them manually." + # update-secureboot-policy not present in the system, recommend generate keys manually. + fail " + +System is running in Secure Boot mode, however your distribution +does not provide tools for automatic generation of keys needed for +modules signing. Please consider to generate and enroll them manually: + + sudo mkdir -p /var/lib/shim-signed/mok + sudo openssl req -nodes -new -x509 -newkey rsa:2048 -outform DER -addext \"extendedKeyUsage=codeSigning\" -keyout $DEB_PRIV_KEY -out $DEB_PUB_KEY + sudo mokutil --import $DEB_PUB_KEY + sudo reboot + +Restart \"rcvboxadd setup\" after system is rebooted. +" + fi + + # Get kernel signature hash algorithm from kernel config and validate it. + sig_hashalgo=$(kernel_module_sig_hash "$KERN_VER") + [ "$(module_sig_hash_supported $sig_hashalgo)" = "1" ] \ + || fail "Unsupported kernel signature hash algorithm $sig_hashalgo" + + # Sign modules. + for i in $MODULE_LIST; do + + # Try to find a tool for modules signing. + SIGN_TOOL=$(which kmodsign 2>/dev/null) + # Attempt to use in-kernel signing tool if kmodsign not found. + if test -z "$SIGN_TOOL"; then + if test -x "/lib/modules/$KERN_VER/build/scripts/sign-file"; then + SIGN_TOOL="/lib/modules/$KERN_VER/build/scripts/sign-file" + fi + fi + + # Check if signing tool is available. + [ -n "$SIGN_TOOL" ] || fail "Unable to find signing tool" + + "$SIGN_TOOL" "$sig_hashalgo" "$DEB_PRIV_KEY" "$DEB_PUB_KEY" \ + /lib/modules/"$KERN_VER"/misc/"$i".ko || fail "Unable to sign $i.ko" + done + # Enroll signing key if needed. + if test -n "$HAVE_UPDATE_SECUREBOOT_POLICY_TOOL"; then + # update-secureboot-policy "expects" DKMS modules. + # Work around this and talk to the authors as soon + # as possible to fix it. + mkdir -p /var/lib/dkms/vbox-temp + update-secureboot-policy --enroll-key 2>/dev/null || + fail "Failed to enroll secure boot key." + rmdir -p /var/lib/dkms/vbox-temp 2>/dev/null + + # Indicate that key has been enrolled and reboot is needed. + HAVE_DEB_KEY=true + fi + fi +} + +# Build and install the VirtualBox guest kernel modules +setup_modules() +{ + KERN_VER="$1" + test -n "$KERN_VER" || return 1 + # Match (at least): vboxguest.o; vboxguest.ko; vboxguest.ko.xz + set /lib/modules/"$KERN_VER"/misc/vboxguest.*o* + #test ! -f "$1" || return 0 + test -d /lib/modules/"$KERN_VER"/build || return 0 + export KERN_VER + info "Building the modules for kernel $KERN_VER." + + # Prepend PATH for building UEK7 on OL8 distribution. + case "$KERN_VER" in + 5.15.0-*.el8uek*) PATH="/opt/rh/gcc-toolset-11/root/usr/bin:$PATH";; + esac + + # Detect if kernel was built with clang. + unset LLVM + vbox_cc_is_clang=$(kernel_get_config_opt "$KERN_VER" "CONFIG_CC_IS_CLANG") + if test "${vbox_cc_is_clang}" = "y"; then + info "Using clang compiler." + export LLVM=1 + fi + + log "Building the main Guest Additions $INSTALL_VER module for kernel $KERN_VER." + if ! myerr=`$BUILDINTMP \ + --save-module-symvers /tmp/vboxguest-Module.symvers \ + --module-source $MODULE_SRC/vboxguest \ + --no-print-directory install 2>&1`; then + # If check_module_dependencies.sh fails it prints a message itself. + module_build_log "$myerr" + "${INSTALL_DIR}"/other/check_module_dependencies.sh 2>&1 && + info "Look at $LOG to find out what went wrong" + return 0 + fi + log "Building the shared folder support module." + if ! myerr=`$BUILDINTMP \ + --use-module-symvers /tmp/vboxguest-Module.symvers \ + --module-source $MODULE_SRC/vboxsf \ + --no-print-directory install 2>&1`; then + module_build_log "$myerr" + info "Look at $LOG to find out what went wrong" + return 0 + fi + log "Building the graphics driver module." + if ! myerr=`$BUILDINTMP \ + --use-module-symvers /tmp/vboxguest-Module.symvers \ + --module-source $MODULE_SRC/vboxvideo \ + --no-print-directory install 2>&1`; then + module_build_log "$myerr" + info "Look at $LOG to find out what went wrong" + fi + [ -d /etc/depmod.d ] || mkdir /etc/depmod.d + echo "override vboxguest * misc" > /etc/depmod.d/vboxvideo-upstream.conf + echo "override vboxsf * misc" >> /etc/depmod.d/vboxvideo-upstream.conf + echo "override vboxvideo * misc" >> /etc/depmod.d/vboxvideo-upstream.conf + + sign_modules "${KERN_VER}" + + update_initramfs "${KERN_VER}" + + return 0 +} + +create_vbox_user() +{ + # This is the LSB version of useradd and should work on recent + # distributions + useradd -d /var/run/vboxadd -g 1 -r -s /bin/false vboxadd >/dev/null 2>&1 || true + # And for the others, we choose a UID ourselves + useradd -d /var/run/vboxadd -g 1 -u 501 -o -s /bin/false vboxadd >/dev/null 2>&1 || true + +} + +create_udev_rule() +{ + # Create udev description file + if [ -d /etc/udev/rules.d ]; then + udev_call="" + udev_app=`which udevadm 2> /dev/null` + if [ $? -eq 0 ]; then + udev_call="${udev_app} version 2> /dev/null" + else + udev_app=`which udevinfo 2> /dev/null` + if [ $? -eq 0 ]; then + udev_call="${udev_app} -V 2> /dev/null" + fi + fi + udev_fix="=" + if [ "${udev_call}" != "" ]; then + udev_out=`${udev_call}` + udev_ver=`expr "$udev_out" : '[^0-9]*\([0-9]*\)'` + if [ "$udev_ver" = "" -o "$udev_ver" -lt 55 ]; then + udev_fix="" + fi + fi + ## @todo 60-vboxadd.rules -> 60-vboxguest.rules ? + echo "KERNEL=${udev_fix}\"vboxguest\", NAME=\"vboxguest\", OWNER=\"vboxadd\", MODE=\"0660\"" > /etc/udev/rules.d/60-vboxadd.rules + echo "KERNEL=${udev_fix}\"vboxuser\", NAME=\"vboxuser\", OWNER=\"vboxadd\", MODE=\"0666\"" >> /etc/udev/rules.d/60-vboxadd.rules + # Make sure the new rule is noticed. + udevadm control --reload >/dev/null 2>&1 || true + udevcontrol reload_rules >/dev/null 2>&1 || true + fi +} + +create_module_rebuild_script() +{ + # And a post-installation script for rebuilding modules when a new kernel + # is installed. + mkdir -p /etc/kernel/postinst.d /etc/kernel/prerm.d + cat << EOF > /etc/kernel/postinst.d/vboxadd +#!/bin/sh +# This only works correctly on Debian derivatives - Red Hat calls it before +# installing the right header files. +/sbin/rcvboxadd quicksetup "\${1}" +exit 0 +EOF + cat << EOF > /etc/kernel/prerm.d/vboxadd +#!/bin/sh +for i in ${OLDMODULES}; do rm -f /lib/modules/"\${1}"/misc/"\${i}".ko; done +rmdir -p /lib/modules/"\$1"/misc 2>/dev/null || true +exit 0 +EOF + chmod 0755 /etc/kernel/postinst.d/vboxadd /etc/kernel/prerm.d/vboxadd +} + +shared_folder_setup() +{ + # Add a group "vboxsf" for Shared Folders access + # All users which want to access the auto-mounted Shared Folders have to + # be added to this group. + groupadd -r -f vboxsf >/dev/null 2>&1 + + # Put the mount.vboxsf mount helper in the right place. + ## @todo It would be nicer if the kernel module just parsed parameters + # itself instead of needing a separate binary to do that. + ln -sf "${INSTALL_DIR}/other/mount.vboxsf" /sbin + # SELinux security context for the mount helper. + if test -e /etc/selinux/config; then + # This is correct. semanage maps this to the real path, and it aborts + # with an error, telling you what you should have typed, if you specify + # the real path. The "chcon" is there as a back-up for old guests. + command -v semanage > /dev/null && + semanage fcontext -a -t mount_exec_t "${INSTALL_DIR}/other/mount.vboxsf" + chcon -t mount_exec_t "${INSTALL_DIR}/other/mount.vboxsf" 2>/dev/null + fi +} + +# Returns path to a module file as seen by modinfo(8), or none if not found. +# +# Input $1: Module name to get path for. +# +# Returns the module path as a string. +module_path() +{ + mod="$1" + [ -n "$mod" ] || return + + modinfo "$mod" 2>/dev/null | grep -e "^filename:" | tr -s ' ' | cut -d " " -f2 +} + +# Returns module version if module is available, or none if not found. +# +# Input $1: Module name to get version for. +# +# Returns the module version as a string. +module_version() +{ + mod="$1" + [ -n "$mod" ] || return + + modinfo "$mod" 2>/dev/null | grep -e "^version:" | tr -s ' ' | cut -d " " -f2 +} + +# Returns the module revision if module is available in the system, or none if not found. +# +# Input $1: Module name to get revision for. +# +# Returns the module revision as a string. +module_revision() +{ + mod="$1" + [ -n "$mod" ] || return + + modinfo "$mod" 2>/dev/null | grep -e "^version:" | tr -s ' ' | cut -d " " -f3 +} + +# Checks if a given kernel module is properly signed or not. +# +# Input $1: Module name to check. +# +# Returns "1" if module is signed and signature can be verified +# with public key provided in DEB_PUB_KEY, or none otherwise. +module_signed() +{ + mod="$1" + [ -n "$mod" ] || return + + # Be nice with distributions which do not provide tools which we + # use in order to verify module signature. This variable needs to + # be explicitly set by administrator. This script will look for it + # in /etc/virtualbox-guest-additions.conf. Make sure that you know + # what you do! + if [ "$VBOX_BYPASS_MODULES_SIGNATURE_CHECK" = "1" ]; then + echo "1" + return + fi + + extraction_tool=/lib/modules/"$(uname -r)"/build/scripts/extract-module-sig.pl + mod_path=$(module_path "$mod" 2>/dev/null) + openssl_tool=$(which openssl 2>/dev/null) + # Do not use built-in printf! + printf_tool=$(which printf 2>/dev/null) + + # Make sure all the tools required for signature validation are available. + [ -x "$extraction_tool" ] || return + [ -n "$mod_path" ] || return + [ -n "$openssl_tool" ] || return + [ -n "$printf_tool" ] || return + + # Make sure openssl can handle hash algorithm. + sig_hashalgo=$(modinfo -F sig_hashalgo "$mod" 2>/dev/null) + [ "$(module_sig_hash_supported $sig_hashalgo)" = "1" ] || return + + # Generate file names for temporary stuff. + mod_pub_key=$(mktemp -u) + mod_signature=$(mktemp -u) + mod_unsigned=$(mktemp -u) + + # Convert public key in DER format into X509 certificate form. + "$openssl_tool" x509 -pubkey -inform DER -in "$DEB_PUB_KEY" -out "$mod_pub_key" 2>/dev/null + # Extract raw module signature and convert it into binary format. + "$printf_tool" \\x$(modinfo -F signature "$mod" | sed -z 's/[ \t\n]//g' | sed -e "s/:/\\\x/g") 2>/dev/null > "$mod_signature" + # Extract unsigned module for further digest calculation. + "$extraction_tool" -0 "$mod_path" 2>/dev/null > "$mod_unsigned" + + # Verify signature. + rc="" + "$openssl_tool" dgst "-$sig_hashalgo" -binary -verify "$mod_pub_key" -signature "$mod_signature" "$mod_unsigned" 2>&1 >/dev/null && rc="1" + # Clean up. + rm -f $mod_pub_key $mod_signature $mod_unsigned + + # Check result. + [ "$rc" = "1" ] || return + + echo "1" +} + +# Checks if a given kernel module matches the installed VirtualBox Guest Additions version. +# +# Input $1: Module name to check. +# +# Returns "1" if externally built module is available in the system and its +# version and revision number do match to current VirtualBox installation. +# None otherwise. +module_available() +{ + mod="$1" + [ -n "$mod" ] || return + + [ "$VBOX_VERSION" = "$(module_version "$mod")" ] || return + [ "$VBOX_REVISION" = "$(module_revision "$mod")" ] || return + + # Check if module belongs to VirtualBox installation. + # + # We have a convention that only modules from /lib/modules/*/misc + # belong to us. Modules from other locations are treated as + # externally built. + mod_path="$(module_path "$mod")" + + # If module path points to a symbolic link, resolve actual file location. + [ -L "$mod_path" ] && mod_path="$(readlink -e -- "$mod_path")" + + # File exists? + [ -f "$mod_path" ] || return + + # Extract last component of module path and check whether it is located + # outside of /lib/modules/*/misc. + mod_dir="$(dirname "$mod_path" | sed 's;^.*/;;')" + [ "$mod_dir" = "misc" ] || return + + # In case if kernel configuration (for currently loaded kernel) requires + # module signature, check if module is signed. + if test "$(kernel_requires_module_signature $(uname -r))" = "1"; then + [ "$(module_signed "$mod")" = "1" ] || return + fi + + echo "1" +} + +# Check if required modules are installed in the system and versions match. +# +# Returns "1" on success, none otherwise. +setup_complete() +{ + [ "$(module_available vboxguest)" = "1" ] || return + [ "$(module_available vboxsf)" = "1" ] || return + + # All modules are in place. + echo "1" +} + +# setup_script +setup() +{ + info "Setting up modules" + + # chcon is needed on old Fedora/Redhat systems. No one remembers which. + test ! -e /etc/selinux/config || + chcon -t bin_t "$BUILDINTMP" 2>/dev/null + + if test -z "$INSTALL_NO_MODULE_BUILDS"; then + # Check whether modules setup is already complete for currently running kernel. + # Prevent unnecessary rebuilding in order to speed up booting process. + if test "$(setup_complete)" = "1"; then + info "VirtualBox Guest Additions kernel modules $VBOX_VERSION $VBOX_REVISION are \ +already available for kernel $TARGET_VER and do not require to be rebuilt." + else + info "Building the VirtualBox Guest Additions kernel modules. This may take a while." + info "To build modules for other installed kernels, run" + info " /sbin/rcvboxadd quicksetup " + info "or" + info " /sbin/rcvboxadd quicksetup all" + if test -d /lib/modules/"$TARGET_VER"/build; then + setup_modules "$TARGET_VER" + depmod + else + info "Kernel headers not found for target kernel $TARGET_VER. \ +Please install them and execute + /sbin/rcvboxadd setup" + fi + fi + fi + create_vbox_user + create_udev_rule + test -n "${INSTALL_NO_MODULE_BUILDS}" || create_module_rebuild_script + shared_folder_setup + # Create user group which will have permissive access to DRP IPC server socket. + groupadd -r -f vboxdrmipc >/dev/null 2>&1 + + if running_vboxguest || running_vboxadd; then + # Only warn user if currently loaded modules version do not match Guest Additions Installation. + check_running_module_version "vboxguest" || info "Running kernel modules will not be replaced until the system is restarted or 'rcvboxadd reload' triggered" + fi + + # Put the X.Org driver in place. This is harmless if it is not needed. + # Also set up the OpenGL library. + myerr=`"${INSTALL_DIR}/init/vboxadd-x11" setup 2>&1` + test -z "${myerr}" || log "${myerr}" + + return 0 +} + +# cleanup_script +cleanup() +{ + if test -z "${INSTALL_NO_MODULE_BUILDS}"; then + # Delete old versions of VBox modules. + cleanup_modules + depmod + + # Remove old module sources + for i in $OLDMODULES; do + rm -rf /usr/src/$i-* + done + fi + + # Clean-up X11-related bits + "${INSTALL_DIR}/init/vboxadd-x11" cleanup + + # Remove other files + if test -z "${INSTALL_NO_MODULE_BUILDS}"; then + rm -f /etc/kernel/postinst.d/vboxadd /etc/kernel/prerm.d/vboxadd + rmdir -p /etc/kernel/postinst.d /etc/kernel/prerm.d 2>/dev/null || true + fi + rm -f /sbin/mount.vboxsf 2>/dev/null + rm -f /etc/udev/rules.d/60-vboxadd.rules 2>/dev/null + udevadm control --reload >/dev/null 2>&1 || true + udevcontrol reload_rules >/dev/null 2>&1 || true +} + +start() +{ + begin "Starting." + + # Check if kernel modules for currently running kernel are ready + # and rebuild them if needed. + test "$(setup_complete)" = "1" || setup + + # Warn if Secure Boot setup not yet complete. + if test "$(kernel_requires_module_signature)" = "1" && test -z "$DEB_KEY_ENROLLED"; then + if test -n "$HAVE_DEB_KEY"; then + info "You must re-start your system to finish secure boot set-up." + else + info "You must sign vboxguest, vboxsf and +vboxvideo (if present) kernel modules before using +VirtualBox Guest Additions. See the documentation +for your Linux distribution." + fi + fi + + if test -z "${INSTALL_NO_MODULE_BUILDS}"; then + test -d /sys && + ps -A -o comm | grep -q '/*udevd$' 2>/dev/null || + no_udev=1 + check_running_module_version "vboxguest" || { + rm -f $dev || { + fail "Cannot remove $dev" + } + rm -f $userdev || { + fail "Cannot remove $userdev" + } + # Assuming modules were just (re-)built, try to reload everything. + reload + } + case "$no_udev" in 1) + do_vboxguest_non_udev;; + esac + fi # INSTALL_NO_MODULE_BUILDS + + return 0 +} + +stop() +{ + begin "Stopping." + + if test -r /etc/ld.so.conf.d/00vboxvideo.conf; then + rm /etc/ld.so.conf.d/00vboxvideo.conf + ldconfig + fi + if ! umount -a -t vboxsf 2>/dev/null; then + # Make sure we only fail, if there are truly no more vboxsf + # mounts in the system. + [ -n "$(findmnt -t vboxsf)" ] && fail "Cannot unmount vboxsf folders" + fi + test -n "${INSTALL_NO_MODULE_BUILDS}" || + info "You may need to restart your guest system to finish removing guest drivers or consider running 'rcvboxadd reload'." + return 0 +} + +check_root() +{ + # Check if script is running with root privileges and exit if it does not. + [ `id -u` -eq 0 ] || early_fail "root privileges are required" +} + +# Check if process with this PID is running. +check_pid() +{ + pid="$1" + + test -n "$pid" -a -d "/proc/$pid" +} + +# A wrapper for check_running_module_version. +# Go through the list of Guest Additions' modules and +# verify if they are loaded and running version matches +# to current installation version. Skip vboxvideo since +# it is not loaded for old guests. +check_status_kernel() +{ + for mod in vboxguest vboxsf; do + + for attempt in 1 2 3 4 5; do + + # Wait before the next attempt. + [ $? -ne 0 ] && sleep 1 + + running_module "$mod" + if [ $? -eq 0 ]; then + mod_is_running="1" + check_running_module_version "$mod" + [ $? -eq 0 ] && break + else + mod_is_running="" + false + fi + + done + + # In case of error, try to print out proper reason of failure. + if [ $? -ne 0 ]; then + # Was module loaded? + if [ -z "$mod_is_running" ]; then + info "module $mod is not loaded" + else + # If module was loaded it means that it has incorrect version. + info "currently loaded module $mod version ($(running_module_version "$mod")) does not match to VirtualBox Guest Additions installation version ($VBOX_VERSION $VBOX_REVISION)" + fi + + # Set "bad" rc. + false + fi + + done +} + +# Check whether user-land processes are running. +# Currently only check for VBoxService. +check_status_user() +{ + [ -r "$VBOXSERVICE_PIDFILE" ] && check_pid "$(cat $VBOXSERVICE_PIDFILE)" >/dev/null 2>&1 +} + +send_signal_by_pidfile() +{ + sig="$1" + pidfile="$2" + + if [ -f "$pidfile" ]; then + check_pid $(cat "$pidfile") + if [ $? -eq 0 ]; then + kill "$sig" $(cat "$pidfile") >/dev/null 2>&1 + else + # Do not spoil $?. + true + fi + else + # Do not spoil $?. + true + fi +} + +# SIGUSR1 is used in order to notify VBoxClient processes that system +# update is started or kernel modules are going to be reloaded, +# so VBoxClient can release vboxguest.ko resources and then restart itself. +send_signal() +{ + sig="$1" + # Specify whether we sending signal to VBoxClient parent (control) + # process or a child (actual service) process. + process_type="$2" + + pidfile_postfix="" + [ -z "$process_type" ] || pidfile_postfix="-$process_type" + + for user_name in $(getent passwd | cut -d ':' -f 1); do + + # Filter out empty login names (paranoia). + [ -n "$user_name" ] || continue + + user_shell=$(getent passwd "$user_name" | cut -d ':' -f 7) + + # Filter out login names with not specified shells (paranoia). + [ -n "$user_shell" ] || continue + + # Filter out know non-login account names. + case "$user_shell" in + *nologin) skip_user_home="1";; + *sync) skip_user_home="1";; + *shutdown) skip_user_home="1";; + *halt) skip_user_home="1";; + *) skip_user_home="" + esac + [ -z "$skip_user_home" ] || continue; + + user_home=$(getent passwd "$user_name" | cut -d ':' -f 6) + + for pid_file in "$user_home"/.vboxclient-*"$pidfile_postfix".pid; do + + [ -r "$pid_file" ] || continue + + # If process type was not specified, we assume that signal supposed + # to be sent to legacy VBoxClient processes which have different + # pidfile name pattern (it does not contain "control" or "service"). + # Skip those pidfiles who has. + [ -z "$process_type" -a -n "$(echo "$pid_file" | grep "control")" ] && continue + [ -z "$process_type" -a -n "$(echo "$pid_file" | grep "service")" ] && continue + + send_signal_by_pidfile -USR1 "$pid_file" + + done + done +} + +# Helper function which executes a command, prints error message if command fails, +# and preserves command execution status for further processing. +try_load_preserve_rc() +{ + cmd="$1" + msg="$2" + + $cmd >/dev/null 2>&1 + + rc=$? + [ $rc -eq 0 ] || info "$msg" + + return $rc +} + +reload() +{ + begin "reloading kernel modules and services" + + # Stop VBoxService if running. + $VBOX_SERVICE_SCRIPT status >/dev/null 2>&1 + if [ $? -eq 0 ]; then + $VBOX_SERVICE_SCRIPT stop >/dev/null 2>&1 || fail "unable to stop VBoxService" + fi + + # Unmount Shared Folders. + umount -a -t vboxsf >/dev/null 2>&1 || fail "unable to unmount shared folders, mount point(s) might be still in use" + + # Stop VBoxDRMClient. + send_signal_by_pidfile "-USR1" "/var/run/VBoxDRMClient" || fail "unable to stop VBoxDRMClient" + + if [ $? -eq 0 ]; then + # Tell legacy VBoxClient processes to release vboxguest.ko references. + send_signal "-USR1" "" + + # Tell compatible VBoxClient processes to release vboxguest.ko references. + send_signal "-USR1" "service" + + # Try unload. + for attempt in 1 2 3 4 5; do + + # Give VBoxClient processes some time to close reference to vboxguest module. + [ $? -ne 0 ] && sleep 1 + + # Try unload drivers unconditionally (ignore previous command exit code). + # If final goal of unloading vboxguest.ko won't be met, we will fail on + # the next step anyway. + running_vboxsf && modprobe -r vboxsf >/dev/null 2>&1 + running_vboxguest + if [ $? -eq 0 ]; then + modprobe -r vboxguest >/dev/null 2>&1 + [ $? -eq 0 ] && break + else + # Do not spoil $?. + true + fi + done + + # Check if we succeeded with unloading vboxguest after several attempts. + running_vboxguest + if [ $? -eq 0 ]; then + info "cannot reload kernel modules: one or more module(s) is still in use" + false + else + # Do not spoil $?. + true + fi + + # Load drivers (skip vboxvideo since it is not loaded for very old guests). + [ $? -eq 0 ] && try_load_preserve_rc "modprobe vboxguest" "unable to load vboxguest kernel module, see dmesg" + [ $? -eq 0 ] && try_load_preserve_rc "modprobe vboxsf" "unable to load vboxsf kernel module, see dmesg" + + # Start VBoxService and VBoxDRMClient. + [ $? -eq 0 ] && try_load_preserve_rc "$VBOX_SERVICE_SCRIPT start" "unable to start VBoxService" + + # Reload VBoxClient processes. + [ $? -eq 0 ] && try_load_preserve_rc "send_signal -USR1 control" "unable to reload user session services" + + # Check if we just loaded modules of correct version. + [ $? -eq 0 ] && try_load_preserve_rc "check_status_kernel" "kernel modules were not reloaded" + + # Check if user-land processes were restarted as well. + [ $? -eq 0 ] && try_load_preserve_rc "check_status_user" "user-land services were not started" + + if [ $? -eq 0 ]; then + # Take reported version of running Guest Additions from running vboxguest module (as a paranoia check). + info "kernel modules and services $(running_module_version "vboxguest") reloaded" + 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" + else + # In case of failure, sent SIGTERM to abandoned control processes to remove leftovers from failed reloading. + send_signal "-TERM" "control" + + fail "kernel modules and services were not reloaded" + fi + else + fail "cannot stop user services" + fi +} + +dmnstatus() +{ + if running_vboxguest; then + echo "The VirtualBox Additions are currently running." + else + echo "The VirtualBox Additions are not currently running." + fi +} + +for i; do + case "$i" in quiet) QUIET=yes;; esac +done +case "$1" in +# Does setup without clean-up first and marks all kernels currently found on the +# system so that we can see later if any were added. +start) + check_root + start + ;; +# Tries to build kernel modules for kernels added since start. Tries to unmount +# shared folders. Uninstalls our Chromium 3D libraries since we can't always do +# this fast enough at start time if we discover we do not want to use them. +stop) + check_root + stop + ;; +restart) + check_root + restart + ;; +# Tries to reload kernel modules and restart user processes. +reload) + check_root + reload + ;; +# Setup does a clean-up (see below) and re-does all Additions-specific +# configuration of the guest system, including building kernel modules for the +# current kernel. +setup) + check_root + cleanup && start + ;; +# Builds kernel modules for the specified kernels if they are not already built. +quicksetup) + check_root + if test x"$2" = xall; then + for topi in /lib/modules/*; do + KERN_VER="${topi%/misc}" + KERN_VER="${KERN_VER#/lib/modules/}" + setup_modules "$KERN_VER" + done + elif test -n "$2"; then + setup_modules "$2" + else + setup_modules "$TARGET_VER" + fi + ;; +# Clean-up removes all Additions-specific configuration of the guest system, +# including all kernel modules. +cleanup) + check_root + cleanup + ;; +status) + dmnstatus + ;; +status-kernel) + check_root + check_status_kernel + if [ $? -eq 0 ]; then + info "kernel modules $VBOX_VERSION $VBOX_REVISION are loaded" + else + info "kernel modules $VBOX_VERSION $VBOX_REVISION were not loaded" + false + fi + ;; +status-user) + check_root + check_status_user + if [ $? -eq 0 ]; then + info "user-land services $VBOX_VERSION $VBOX_REVISION are running" + else + info "user-land services $VBOX_VERSION $VBOX_REVISION are not running" + false + fi + ;; +*) + echo "Usage: $0 {start|stop|restart|reload|status|status-kernel|status-user|setup|quicksetup|cleanup} [quiet]" + exit 1 +esac + +exit -- cgit v1.2.3