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的圖標了,也可以打開,但無法正常運行虛擬機,還需要解決上面提示的錯誤才可以。
使用自簽證書對內核模塊進行簽名
但很遺憾的是,當時折騰的時候,沒想到要記錄,所以沒有詳細記錄下具體的步驟,也沒有拍照。但在寫這篇文章的時候,從網上搜了一些資料,和當時自己折騰的內容很相似,所以有些內容就直接盜用網上的資料了。在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的內核。
參考資料
Working with Kernel Modules
virtualbox - How to sign a kernel module Ubuntu 18.04 - Super User
linux - Sign virtual box modules (vboxdrv, vboxnetflt, vboxnetadp, vboxpci) Centos 8 - Stack Overflow
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博客
Working with Kernel Modules :: Fedora Docs