Fedora38安装VirtualBox
2023.07.08
背景
我的电脑使用的Fedora38系统,但由于某些原因,需要使用其它操作系统,通过虚拟机安装其它系统是一个最好的选择,在linux系统中,VirtualBox是比较知名的虚拟机软件,但VirtualBox对Fedora系统的支持目前只支持到Fedora36,而现在Fedora早已经发布了Fedora38版本,我的电脑使用的即是Fedora38系统,于是开始了一番折腾。
环境
操作系统: Fedora Linux 38 (Workstation Edition)
CPU:11th Gen Intel® Core™ i5-11300H × 8
下载软件
VirtualBox: VirtualBox 7.0.8
由于VirtualBox不再支持更高版本的Fedora系统,导入一些RMP源我又觉得麻烦,而VirtualBox官网又提供了"All distributions(build on EL6 and therefore not requiring recent system libraries)"版本,于是决定安装此版本。在官网上找到下载界面,选中"All distributions”,鼠标右键,选择“链接另存为”按钮,如下图所示:
点击按钮后,弹出保存界面,如下图所示:
将名字改为sh后缀。不改应该也可以,因为我的电脑上保存的时候,默认的后缀是txt,看着不太习惯,毕竟是一个可执行程序,于是修改为了sh后缀。
安装
下载下来后,加上可执行权限,以root用户执行下载的软件,直接安装即可,命令如下:
[root@fedora 下载]# chmod +x VirtualBox-7.0.8-156879-Linux_amd64.sh
[root@fedora 下载]# ./VirtualBox-7.0.8-156879-Linux_amd64.sh
Verifying archive integrity... 100% MD5 checksums are OK. All good.
Uncompressing VirtualBox for Linux installation 100%
VirtualBox Version 7.0.8 r156879 (2023-04-17T17:29:53Z) installer
Removing previous installation of VirtualBox 7.0.6 r155176 from /opt/VirtualBox
Installing VirtualBox to /opt/VirtualBox
warnings.warn(
/usr/lib/python3.11/site-packages/setuptools/command/easy_install.py:144: EasyInstallDeprecationWarning: easy_install command is deprecated. Use build and pip and other standards-based tools.
warnings.warn(
zip_safe flag not set; analyzing archive contents...
vboxdrv.sh: failed: modprobe vboxdrv failed. Please use 'dmesg' to find out why.
There were problems setting up VirtualBox. To re-start the set-up process, run
/sbin/vboxconfig
as root. If your system is using EFI Secure Boot you may need to sign the
kernel modules (vboxdrv, vboxnetflt, vboxnetadp, vboxpci) before you can load
them. Please see your Linux system's documentation for more information.
VirtualBox has been installed successfully.
可以看到,安装到了/opt/VirualBox目录,安装之前还会卸载之前安装的版本(因为我之前安装了7.0.6版本)。但是也可以看到执行modprobe vboxdrv failed,后面也给出了提示:If your system is using EFI secure Boot you may need to sign the kernel modules(vboxdrv,vboxnetflt,vboxnetadp,vboxpci)。刚好我的电脑是EFI Secure Boot,所以会有此提示。解决方案有两个:关闭secure boot或者使用自签名证书为自己想要加载的内核模块签名。由于自己没接触过给内核模块签名,所以想挑战一把。
此时,电脑菜单中已经可以看到VirtualBox的图标了,也可以打开,但无法正常运行虚拟机,还需要解决上面提示的错误才可以。
![](/qrcode.jpg)
使用自签证书对内核模块进行签名
但很遗憾的是,当时折腾的时候,没想到要记录,所以没有详细记录下具体的步骤,也没有拍照。但在写这篇文章的时候,从网上搜了一些资料,和当时自己折腾的内容很相似,所以有些内容就直接盗用网上的资料了。在Fedora中全自动签名英伟达驱动内核模块以支持安全启动(Secure Boot)_mokutil_KylinDemons.的博客-CSDN博客这篇文章中有比较详细的步骤。我盗用下主要的步骤,如有侵权,请作者联系我,我会删除。
安装Mok工具和密钥生成工具
dnf install mokutil openssl
生成自签名的证书和密钥
sudo openssl req -new -x509 -newkey rsa:2048 -keyout ~/my_private_key.key -outform DER -out ~/my_private_key.der -nodes -days 36500 -subj "/CN=Private Driver Signing"
将自签名的密钥注册到BIOS中
导入后,linux内核会信任由该自签密钥签名过的任何软件,命令如下:
sudo mokutil --import ~/my_private_key.der
执行完此命令后,控制台会让您设置一个密码,该密码的作用是用来导入并注册自签自签密钥,只会在第6步用到一次,合理设置即可,建议8位。
重启电脑
sudo reboot
导入并注册自签名密钥
重启时,系统启动之前会出现一个蓝色界面(标题为MOK Manager)。在安全启动的条件下安装过Ubuntu的您可能会熟悉。按照以下选项导入密钥即可:
注意:以下几个步骤要小心,任何一步误操作,都必须从第4步开始重做。
-
通过方向键选择"Enroll MOK",如下图所示:
-
选择“Continue”,如下图所示:
-
选择“yes”,如下图所示:
-
在此步骤中输入之前设置的密码并回车(输入过程中密码不会显示),如下图所示:
-
成功后选择“Reboot”,如下图所示:
-
此时,电脑会再次重启,等待进入系统即可。
使用自签名证书注册VirtualBox相关内核模块
在安装完VirtualBox后,其内核模块一般会安装到当前内核版本所在的目录中,可以使用以下命令查看下:
[root@fedora 下载]# ls -l /lib/modules/$(uname -r)/misc
总计 5220
-rw-r--r--. 1 root root 3950220 6月29日 21:25 vboxdrv.ko
-rw-r--r--. 1 root root 504708 6月29日 21:25 vboxnetadp.ko
-rw-r--r--. 1 root root 884388 6月29日 21:25 vboxnetflt.ko
注册内核模块的命令为:/usr/src/kernels/$(uname -r)/scripts/sign-file sha256 xxxx.priv xxx.der file_path,如要注册vboxdrv.ko模块,则命令为:
/usr/src/kernels/6.3.11-200.fc38.x86_64/scripts/sign-file sha256 ~/my_private_key.key ~/my_private_key.der /lib/modules/6.3.11-200.fc38.x86_64/misc/vboxdrv.ko
以上路径是在我电脑中的路径,具体请以自己的内核版本为准。从网上搜到一个脚本,命名为a.sh,脚本内容如下:
[root@fedora zy]# cat a.sh
#!/bin/bash
for modfile in $(dirname $(modinfo -n vboxdrv))/*.ko; do
echo "Signing $modfile"
/usr/src/kernels/$(uname -r)/scripts/sign-file sha256 \
~/my_private_key.priv \
~/my_private_key.der "$modfile"
done
my_private_key.priv、my_private_key.der的名字及路径请以自己生成的为准。执行这个脚本,可以看到如下结果:
[root@fedora 下载]# ./a.sh
Signing /lib/modules/6.3.8-200.fc38.x86_64/misc/vboxdrv.ko
Signing /lib/modules/6.3.8-200.fc38.x86_64/misc/vboxnetadp.ko
Signing /lib/modules/6.3.8-200.fc38.x86_64/misc/vboxnetflt.ko
说明virtualbox的内核模块已经注册成功,此时,内核已经信任这几个ko模块,可以正常加载这几个内核模块了。执行如下命令加载这几个内核模块:
[root@fedora 下载]# modprobe vboxdrv
[root@fedora 下载]# modprobe vboxnetadp
[root@fedora 下载]# modprobe vboxnetflt
此时,一般情况下就可以正常使用VirtualBox了。
重启后自动加载VirtualBox内核模块
以上通过modprobe方式加载的内核,在系统重启后就失效了,系统重启后并不会自动加载上这些内核模块。想要在系统启动的时候让Linux内核自动加载这些内核模块,有很多种方法,不同的操作系统可能也不太一样,我采用了在/etc/modules-load.d/目录中创建配置文件的方法,我自己创建了一个modules.conf的文件,文件名称也可以是别的,根据自己的喜好命名即可,内容是各个内核模块的名称(其实就是传给modprobe命令的参数),内容如下:
[root@fedora zy]# cat /etc/modules-load.d/modules.conf
vboxdrv
vboxguest
vboxnetadp
vboxnetflt
vboxsf
vboxvideo
这样,在系统重启后,Linux内核就会自动加载这些内核模块了。
遇到的问题
虚拟机无法启动,一直卡在20%处
配置完虚拟机后,无法启动,一直卡在20%处,如下图所示:
从网上搜到的原因看,可能是是因为intel处理器 后面加了ibt功能导致冲突, 具体从哪一代CPU开始的,不太清楚,也没有去深究,通过将grub中内核启动参数增加ibt=off 搞定。将/etc/default/grub中GRUB_CMDLINE_LINUX中添加ibt=off配置,具体操作如下:
[root@fedora 下载]# cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="resume=UUID=4219809e-7b8f-4f6a-bab6-1450bb3ecf7e rhgb quiet ibt=off"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
[root@fedora 下载]# cp /etc/default/grub /etc/default/grub.bak
[root@fedora 下载]# vi /etc/default/grub
[root@fedora 下载]#
[root@fedora 下载]# ls /boot/grub2/
fonts/ grub.cfg grubenv
[root@fedora 下载]# cat /proc/cmdline
BOOT_IMAGE=(hd0,gpt2)/vmlinuz-6.3.11-200.fc38.x86_64 root=UUID=debb2e87-b92f-4f5c-a8b7-8ed0e0689167 ro resume=UUID=4219809e-7b8f-4f6a-bab6-1450bb3ecf7e rhgb quiet
[root@fedora 下载]# cp /boot/grub2/
fonts/ grub.cfg grubenv
[root@fedora 下载]# cp /boot/grub2/grub.cfg /boot/grub2/grub.cfg.bak
[root@fedora 下载]# grub2-mk
grub2-mkconfig grub2-mkimage grub2-mknetdir grub2-mkrelpath grub2-mkstandalone
grub2-mkfont grub2-mklayout grub2-mkpasswd-pbkdf2 grub2-mkrescue
[root@fedora 下载]# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Adding boot menu entry for UEFI Firmware Settings ...
done
重启操作系统即可。
已经安装过了VirtualBox,也已经用了一段时间,但升级内核版本后,发现又无法打开了
VirtualBox软件可以正常打开,但无法正常运行虚拟机,运行虚拟机的时候,会提示如下错误:
一般情况下,执行/sbin/vboxconfig即可,然而在我的电脑中,执行/sbin/vboxconfig报如下错误:
[root@fedora 下载]# /sbin/vboxconfig
vboxdrv.sh: Stopping VirtualBox services.
vboxdrv.sh: Starting VirtualBox services.
vboxdrv.sh: You must sign these kernel modules before using VirtualBox:
vboxdrv vboxnetflt vboxnetadp
See the documentation for your Linux distribution..
vboxdrv.sh: Building VirtualBox kernel modules.
vboxdrv.sh: Signing VirtualBox kernel modules.
vboxdrv.sh: failed: modprobe vboxdrv failed. Please use 'dmesg' to find out why.
There were problems setting up VirtualBox. To re-start the set-up process, run
/sbin/vboxconfig
as root. If your system is using EFI Secure Boot you may need to sign the
kernel modules (vboxdrv, vboxnetflt, vboxnetadp, vboxpci) before you can load
them. Please see your Linux system's documentation for more information.
提示信息已经很明显了,因为我的电脑是EFI Secure Boot,而virtualbox的ko没有签名,所以不能加载驱动。于是使用之前的a.sh脚本执行一遍,重新注册了VirtualBox的内核模块,执行完后继续执行/sbin/vboxconfig命令,依然提示如下:
[root@fedora zy]# /sbin/vboxconfig
vboxdrv.sh: Stopping VirtualBox services.
vboxdrv.sh: Starting VirtualBox services.
vboxdrv.sh: You must sign these kernel modules before using VirtualBox:
vboxdrv vboxnetflt vboxnetadp
See the documentation for your Linux distribution..
vboxdrv.sh: Building VirtualBox kernel modules.
egrep: warning: egrep is obsolescent; using grep -E
vboxdrv.sh: failed: Look at /var/log/vbox-setup.log to find out what went wrong.
There were problems setting up VirtualBox. To re-start the set-up process, run
/sbin/vboxconfig
as root. If your system is using EFI Secure Boot you may need to sign the
kernel modules (vboxdrv, vboxnetflt, vboxnetadp, vboxpci) before you can load
them. Please see your Linux system's documentation for more information.
有点懵圈了,不知道怎么回事,再重新注册内核模块后,再次执行/sbin/vboxconfig命令,依然提示错误,陷入了死循环。后来想了想,终于知道,执行完/sbin/vboxconfig,使用a.sh注册了内核模块后,应该使用modprobe命令将内核模块加载到内核中,而不是再执行/sbin/vboxconfig模块。升级完内核后,正确的处理顺序应该是如下:
[root@fedora zy]# /sbin/vboxconfig
[root@fedora zy]# ./a.sh
[root@fedora zy]# modprobe vboxdrv
[root@fedora zy]# modprobe vboxnetadp
[root@fedora zy]# modprobe vboxnetflt
这样就可以了。
那为什么每次执行完/sbin/vboxconfig,都会提示以下内容呢?
vboxdrv.sh: You must sign these kernel modules before using VirtualBox:
vboxdrv vboxnetflt vboxnetadp
因为执行/sbin/vboxconfig命令的时候,会重新编译VirtualBox的那几个ko模块,编译出来的文件和之前已经注册的ko文件不同了,所以需要重新注册。
执行modpreobe的时候,提示“Key was rejected by service”错误
手动执行modprobe vboxdrv命令,提示如下:
[root@fedora 下载]# modprobe vboxdrv
modprobe: ERROR: could not insert 'vboxdrv': Key was rejected by service
内核模块没有被注册,重新使用a.sh脚本中类似的命令重新注册即可,如下所示:
[root@fedora 下载]# modprobe vboxdrv
modprobe: ERROR: could not insert 'vboxdrv': Key was rejected by service
[root@fedora 下载]# modprobe vboxnetadp
modprobe: ERROR: could not insert 'vboxnetadp': Key was rejected by service
[root@fedora 下载]# ./a.sh
Signing /lib/modules/6.3.8-200.fc38.x86_64/misc/vboxdrv.ko
Signing /lib/modules/6.3.8-200.fc38.x86_64/misc/vboxnetadp.ko
Signing /lib/modules/6.3.8-200.fc38.x86_64/misc/vboxnetflt.ko
[root@fedora 下载]# modprobe vboxnetadp
可能的原因是多次执行了/sbin/vboxconfig命令,每次执行/sbin/vboxconfig命令都会重新生成新的ko文件,所以第一次执行vboxconfig命令后,对生成的ko进行注册,而再次运行了/sbin/vboxconfig后,又生成了新的ko文件,而新的ko文件并未注册,所以运行modprode命令的时候报错。
运行/sbin/vboxconfig报错,向只读成员‘vm_flags’赋值
运行/sbin/vboxconfig报错,提示查看/var/log/vbox-setup.log文件,打开文件后,有类似如下的内容:
[root@fedora VirtualBox]# vi /var/log/vbox-setup.log
/var/log/vbox-setup.log
In file included from /tmp/vbox.0/combined-os-specific.c:43:
/tmp/vbox.0/r0drv/linux/memobj-r0drv-linux.c: 在函数‘rtR0MemObjNativeLockUser’中:
/tmp/vbox.0/r0drv/linux/memobj-r0drv-linux.c:1404:39: 错误:向只读成员‘vm_flags’赋值
1404 | papVMAs[rc]->vm_flags |= VM_DONTCOPY | VM_LOCKED;
| ^~
/tmp/vbox.0/r0drv/linux/memobj-r0drv-linux.c: 在函数‘rtR0MemObjNativeMapUser’中:
/tmp/vbox.0/r0drv/linux/memobj-r0drv-linux.c:1876:35: 错误:向只读成员‘vm_flags’赋值
1876 | vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
| ^~
make[2]: *** [scripts/Makefile.build:252: /tmp/vbox.0/combined-os-specific.o] Error 1
make[2]: *** 正在等待未完成的任务....
# cmd_check_local_export /tmp/vbox.0/SUPDrvGip.o
./scripts/check-local-export /tmp/vbox.0/SUPDrvGip.o
# cmd_check_local_export /tmp/vbox.0/SUPDrv.o
./scripts/check-local-export /tmp/vbox.0/SUPDrv.o
# cmd_check_local_export /tmp/vbox.0/combined-agnostic2.o
./scripts/check-local-export /tmp/vbox.0/combined-agnostic2.o
# cmd_check_local_export /tmp/vbox.0/combined-agnostic1.o
./scripts/check-local-export /tmp/vbox.0/combined-agnostic1.o
make[1]: *** [Makefile:2037: /tmp/vbox.0] Error 2
make: *** [/tmp/vbox.0/Makefile-footer.gmk:133: vboxdrv] Error 2
这是我用VirtualBox7.0.6版本编译的,可能此版本的代码在新的编译器中无法编译通过,我又换回了7.0.8版本才可以。
感想
不知道是linux做的不太好,还是VirtualBox对linux的支持不好,总感觉折腾下来很麻烦,特别是还遇到了一些问题。而一旦升级内核,又得需要重新执行下/sbin/vboxconfig命令重新编译VirtualBox的内核。
参考资料
virtualbox - How to sign a kernel module Ubuntu 18.04 - Super User
manjaro 内核linux6.1使用virtualbox7.0.8 启动虚拟机时卡在20%_kingzhaoc的博客-CSDN博客
https://github.com/LCTT/TranslateProject/blob/master/published/201311/How%20to%20add%20kernel%20boot%20parameters%20via%20GRUB%20on%20Linux.md
在Fedora中全自动签名英伟达驱动内核模块以支持安全启动(Secure Boot)_mokutil_KylinDemons.的博客-CSDN博客