问题总结
我有一个在 samba 下共享的本地文件夹,但如果我尝试允许 qemu(通过用户会话)通过 virtio-9p 访问它,则会收到错误 (SELinux avc)。在禁用 SELinux 的情况下工作正常,但我想让它工作和SELinux。请帮忙。
背景
在 Fedora 主机上,我安装了 samba 和 virt-manager/qemu。两者都可以彼此独立地正常工作(例如,samba 目录和 vm 目录完全不同的路径,甚至不在同一驱动器上)。
对于我正在开发的一个新项目,我想找到一种方法,允许 virt-manager/qemu 和 samba(也可能是 docker/podman)访问当前由 samba 共享的现有主机文件夹,同时仍然限制访问越多越好。我的理解是,通过协议访问共享smb://
虽然可能,但会因网络开销而产生一些 I/O 延迟,即使两者位于同一主机上。为此,我希望smb://
完全避免协议,并让虚拟机通过 virtio-9p 或类似的东西在本地访问共享主机文件夹。另外,需要澄清的是,这不是本地安装的远程 samba 共享,而是共享给我的局域网上其他计算机的本地文件夹。
每一些红帽文档,我发现了一个布尔值,我认为它可能允许我的虚拟机访问上下文下的文件samba_share_t
:
virt_use_samba 允许虚拟机访问 CIFS 文件。
由于我之前使用 samba 文件上下文配置了该文件夹:
# setsebool -P samba_export_all_ro=1;
# setsebool -P samba_export_all_rw=1;
# setsebool -P samba_share_fusefs=1;
# sambaShare=/media/d/shared
# semanage fcontext --add --type "samba_share_t" "${sambaShare}(/.*)?"
# sudo restorecon -R "${sambaShare}";
从 samba 方面来看,一切工作正常,我可以在那里读/写,没有任何问题。
今天,我设置了新的布尔值,认为这会让虚拟机也这样做
# setsebool -P virt_use_samba=1
# getsebool -a | grep -P '(smb|cifs|samba|virt_|emu).*on$'
samba_export_all_ro --> on
samba_export_all_rw --> on
samba_share_fusefs --> on
virt_sandbox_use_all_caps --> on
virt_sandbox_use_audit --> on
virt_use_nfs --> on
virt_use_samba --> on
virt_use_usb --> on
xend_run_qemu --> on
但我仍然收到错误。鉴于我在此主机上已经有一个 Windows 虚拟机,能够通过smb://
协议访问 samba 共享事先的设置此变量..我不确定是否virt_use_samba
旨在允许虚拟机访问该协议,但 Windows 只是做不同的事情,如果它旨在允许虚拟机访问具有samba_share_t
文件上下文的文件夹,但由于某种原因它不是对我来说工作正常,或者如果它已被弃用/完全做其他事情。设置变量后我还重新启动了系统,只是为了排除这种情况,但这没有任何区别。
我已经测试过,临时使用时设置有效setenforce 0
- 我可以通过虚拟机设置添加文件系统,然后将其安装在虚拟机中,甚至可以毫无问题地写入它。但是,一旦我重新打开 SELinux,我什至无法再启动虚拟机 - 我收到错误并且必须删除 virtio-9p 文件系统条目才能再次启动。
错误和配置详细信息
系统
# inxi -Sz
System:
Kernel: 6.6.6-100.fc38.x86_64 arch: x86_64 bits: 64 Console: pty pts/0
Distro: Fedora release 38 (Thirty Eight)
# dnf list installed selinux-policy
Installed Packages
selinux-policy.noarch 38.30-1.fc38 @updates
我还在用户(例如qemu:///session
)而不是根用户(例如qemu:///system
)下运行 virt-manager/qemu(如果这有什么区别的话)。我通过设置这个gsettings
,例如
gsettings set org.virt-manager.virt-manager.connections uris "['qemu:///session']";
gsettings set org.virt-manager.virt-manager.connections autoconnect "['qemu:///session']";
virtio-9p 配置
* 注意:我实际上是通过 virt-manager gui 手动配置的,但这是生成的 xml。我正在做的实际过程是(来自 virt-manager),我打开 VM 对话框并转到详细信息选项卡,然后选择左下角的“添加硬件”按钮 > 文件系统 > driver=virtio-9p,定义源和目标路径 > 完成按钮。然后,一旦虚拟机启动,我就会使用以下命令进行安装:mount -t 9p -o trans=virtio "${virtualPath}" "${guestMountPoint}"
其中 virtualPath 是下面 xml 中定义的目标路径, guestMountPoint 是来宾操作系统上的任何路径(例如/media/shared
)。
<filesystem type="mount" accessmode="mapped">
<source dir="/media/d/shared"/>
<target dir="/virtio-9p/shared"/>
</filesystem>
virt-manager 消息框出现错误:
Unable to complete install: 'internal error: qemu unexpectedly closed the monitor: 2023-12-17T04:07:05.237139Z qemu-system-x86_64: -device {"driver":"virtio-9p-pci","id":"fs1","fsdev":"fsdev-fs1","mount_tag":"/virtio-9p/shared","bus":"pci.2","addr":"0x0"}: cannot initialize fsdev 'fsdev-fs1': failed to open '/media/d/shared': Permission denied'
Traceback (most recent call last):
File "/usr/share/virt-manager/virtManager/asyncjob.py", line 72, in cb_wrapper
callback(asyncjob, *args, **kwargs)
File "/usr/share/virt-manager/virtManager/createvm.py", line 2008, in _do_async_install
installer.start_install(guest, meter=meter)
File "/usr/share/virt-manager/virtinst/install/installer.py", line 695, in start_install
domain = self._create_guest(
^^^^^^^^^^^^^^^^^^^
File "/usr/share/virt-manager/virtinst/install/installer.py", line 637, in _create_guest
domain = self.conn.createXML(initial_xml or final_xml, 0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib64/python3.11/site-packages/libvirt.py", line 4481, in createXML
raise libvirtError('virDomainCreateXML() failed')
libvirt.libvirtError: internal error: qemu unexpectedly closed the monitor: 2023-12-17T04:07:05.237139Z qemu-system-x86_64: -device {"driver":"virtio-9p-pci","id":"fs1","fsdev":"fsdev-fs1","mount_tag":"/virtio-9p/shared","bus":"pci.2","addr":"0x0"}: cannot initialize fsdev 'fsdev-fs1': failed to open '/media/d/shared': Permission denied
来自 SELinux 的错误:
# ausearch -m avc -ts boot
----
time->Sat Dec 16 23:07:05 2023
type=AVC msg=audit(1702786025.235:319): avc: denied { read } for pid=4221 comm="qemu-system-x86" name="shared" dev="dm-4" ino=83951617 scontext=unconfined_u:unconfined_r:svirt_t:s0:c98,c936 tcontext=unconfined_u:object_r:samba_share_t:s0 tclass=dir permissive=0
问题:
我了解问题是我的虚拟机无权访问samba_share_t
.从我迄今为止所做的研究来看,听起来有几种可用的选择:
我在网上看到过提示,可能可以修改规则,但从来没有任何实际这样做的命令/教程(例如“为现有文件类型添加缺少的访问规则”)这次讨论)。假设修改现有的 SELinux 规则集,例如允许 qemu/svirt_t/etc 访问“samba_share_t”文件上下文,有人可以向我展示一个简单的示例来说明如何执行此操作吗?或者,如果它比我想象的更复杂,即使是一个简短的 10,000 英尺概述和链接也将不胜感激。我仍在学习 SELinux,还没有接受过正规教育,所以请记住,我无法访问任何付费的 RH 知识门户,并且公共 RH 文档并不总是最清晰的。我找到了一个Gentoo wiki 上的 SELinux 页面这就是我下一步计划尝试的地方(我想先在这里问一下,因为我不确定要关注哪一部分,而且有很多东西要读)。
我在网上看到一些提到可以将目录的文件上下文更改为
public_context_rw_t
并设置 selinux 布尔值以允许访问。我想我需要setsebool -P smbd_anon_write=1
(或或许setsebool -P allow_smbd_anon_write 1
?)以允许 samba 访问此上下文。但我发现的所有示例都是针对 httpd 等更流行的服务,我完全不知道我需要为 qemu/virt-manager (或 docker/podman)设置的布尔值的名称是什么。我在getsebool -a
输出中没有看到任何类似名称的内容。我也有点犹豫是否使用这种方法,因为这似乎也允许其他服务访问该文件夹。假设我采用这种方法,我需要为 qemu 和 docker/podman 设置哪些布尔值?我对其他严肃的选择持开放态度(例如,对“关闭 SELinux”作为解决方案不感兴趣)。
如果解决方案需要任何其他相关信息,请告诉我。