解决 libvirt 启动失败的问题:外部磁盘权限限制

2026-05-17#虚拟机#AppArmor#libvirt#Cockpit

我在 LinuxMint 上使用 Cockit 和 libvirt 来管理虚拟机。安装好了虚拟机后,我又给它挂载了一个硬盘,磁盘位于我的第二块外置硬盘上(挂载到了 /mnt/data)。每次启动虚拟机时都会失败,提示没有权限打开磁盘文件。但是,如果手动卸载了该硬盘,然后再次添加到虚拟中,虚拟机又可以正常启动。每次这么手动操作未免过于复杂,而且虚拟机无法自动启动了。后来我发现,问题的根源在于 libvirt 的默认安全策略限制了对外部磁盘的访问。解决方法是修改 libvirt 的安全策略,允许访问指定的磁盘路径。

问题描述 🔗

在 Cockpit 启动虚拟机时候,错误如下(/mnt/data/var/lib/libvirt/images/win11 即为虚拟机的磁盘文件路径):

internal error: process exited while connecting to monitor: 2026-05-17T05:48:06.851067Z qemu-system-x86_64: -blockdev {"driver":"file","filename":"/mnt/data/var/lib/libvirt/images/win11","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}: Could not open '/mnt/data/var/lib/libvirt/images/win11': Permission denied

经排查,该虚拟机磁盘文件路径里的每个目录,都允许执行和读取权限。

解决方法 🔗

解决方法为:修改 libvirt 的安全策略,允许访问指定的磁盘路径。具体方法如下:

  1. 新建文件 /etc/apparmor.d/local/abstractions/libvirt-qemu,加入如下内容:
/mnt/data/var/lib/libvirt/images/ r,
/mnt/data/var/lib/libvirt/images/** rwk,
  1. 执行以下命令重载 AppArmor 和重启 libvirt 服务:
sudo systemctl reload apparmor
sudo systemctl restart libvirtd

原因分析 🔗

Linux Mint 默认启用了 AppArmor 强制访问控制(MAC) 机制,因此虚拟化进程(QEMU)的访问权限受到了严格的策略文件(Profile)限制。在这种机制下,MAC 的安全策略具有最高优先级,它独立于且凌驾于传统的 Linux 自主访问控制(DAC,即文件权限和用户组)之上。即使目标镜像文件及沿途目录在传统权限上已对 libvirt-qemu 用户完全开放,但因为该自定义路径(/mnt/data/...)并未包含在 AppArmor 的默认白名单规则中,内核安全模块仍会直接拦截该访问请求,从而导致 Permission denied 错误。