考虑使用/dev/disk/by-{path,id}/

考虑使用/dev/disk/by-{path,id}/

我经常处理格式化 USB 驱动器,这些驱动器注册为 /dev/sdX。这包括执行mkfsfdisk以及mount其他通常以 root 身份执行的命令。然而,我担心我可能会不小心输错一个字母,并格式化我的硬盘。

理想情况下,我希望将/dev/sdX*设备设置为“只读”模式,这样任何设备fdisk mkfs wipefs都会失败,除非通过手动命令将设备切换到“读写”模式。

我以为chmod ugo-w /dev/sdX会像那样工作。然而令我惊讶的是,chmod 0000 /dev/sdc1接下来的mkfs /dev/sdc1作品完全没问题。

如何防止所有用户(包括 root 用户)修改硬盘驱动器及其分区表、对硬盘驱动器进行分区以及以通过已安装的文件系统以外的方式写入分区?如果我愿意,如何使用此方法启用对驱动器的写入?

我知道我可以使该设备归用户所有。然而,这需要我在用户和 root 之间切换才能发出类似chrootormount或 之类的命令umount,这是一个安全漏洞。我不希望所有 USB 存储设备都归用户所有。我正在寻找更好的解决方案。理想情况下,我希望保留 root 用户身份,但不会格式化错误的光盘。

答案1

考虑使用/dev/disk/by-{path,id}/

/dev/disk/by-path/具有到块设备的符号链接,其中符号链接的名称描述设备的“硬件路径”(子系统、总线、控制器、端口等)。我的系统上经过编辑的列表显示了一个 NVME 设备、一个SATA 设备和一个 USB 驱动器(以及每个驱动器上的第一个分区):

/dev/disk/by-path
├── pci-0000:00:14.0-usb-0:1:1.0-scsi-0:0:0:0 -> ../../sdc
├── pci-0000:00:14.0-usb-0:1:1.0-scsi-0:0:0:0-part1 -> ../../sdc1
├── pci-0000:00:17.0-ata-2 -> ../../sda
├── pci-0000:00:17.0-ata-2-part1 -> ../../sda1
├── pci-0000:02:00.0-nvme-1 -> ../../nvme0n1
└── pci-0000:02:00.0-nvme-1-part1 -> ../../nvme0n1p1

/dev/disk/by-id工作原理类似,但具有子系统、设备品牌/型号和序列号。我确实似乎有很多三星存储:

/dev/disk/by-id
├── ata-Samsung_SSD_860_EVO_500GB_XXXXXXXXXXXXXXX -> ../../sda
├── ata-Samsung_SSD_860_EVO_500GB_XXXXXXXXXXXXXXX-part1 -> ../../sda1
├── nvme-Samsung_SSD_980_PRO_1TB_XXXXXXXXXXXXXXX -> ../../nvme0n1
├── nvme-Samsung_SSD_980_PRO_1TB_XXXXXXXXXXXXXXX-part1 -> ../../nvme0n1p1
├── usb-Samsung_Flash_Drive_FIT_XXXXXXXXXXXXXXXX-0:0 -> ../../sdc
└── usb-Samsung_Flash_Drive_FIT_XXXXXXXXXXXXXXXX-0:0-part1 -> ../../sdc1

假设您的目标是不混淆插入的 USB 驱动器和您的 (sata/nvme) 系统驱动器,这些名称可能会有所帮助。您可以只使用这些命令的名称,并且应该按预期工作:

fdisk /dev/disk/by-id/usb-Samsung_Flash_Drive_FIT_XXXXXXXXXXXXXXXX-0:0
mke2fs /dev/disk/by-id/usb-Samsung_Flash_Drive_FIT_XXXXXXXXXXXXXXXX-0:0-part1

希望这足以引起您的注意并中止:

mke2fs /dev/disk/by-id/nvme-Samsung_SSD_980_PRO_1TB_XXXXXXXXXXXXXXX-part1

答案2

rm /dev/sda /dev/sda1 如果您想防止意外引用这些设备,一个简单的策略是在启动后等等。mknod /dev/sda1 b 8 1如果需要的话,您总是可以使用等等重新创建索引节点,但umount /dev/sda1没有它也可以工作,因为它可能在某处有适当的信息。

但这确实是一个良好卫生的问题;最好不要以 root 身份登录,也不要 su 到 root,或者如果您必须仅在一个红色背景的终端中这样做,请不要复制粘贴到其中,为重复任务编写脚本并确保它们检查参数并进行其他健全性检查。

答案3

嗯,有blockdev --setro一个块设备是只读的(--setrw用于读写)。

# blockdev --setro /dev/sdx3
# mkfs.ext4 /dev/sdx3
mke2fs 1.47.0 (5-Feb-2023)
/dev/sdx3 contains a vfat file system
Proceed anyway? (y,N) y
/dev/sdx3: Operation not permitted while setting up superblock
# wipefs -a /dev/sdx3
wipefs: /dev/sdcx3: failed to erase vfat magic string at
  offset 0x00000052: Operation not permitted

那么你可以让块设备只读,甚至对于 root 来说也是如此吗?是的。嗯,有点。

然而,它不是很可靠。例如,如果内核因任何原因重新读取分区表。即使分区实际上没有更改,重新读取后从/dev/sdx3技术上讲也是一个新设备,从未设置过此 ro 标志。

因此,至少您需要一些 udev 规则来始终管理和维护您的只读标志。 (如果在任何地方有一个标志默认使块设备只读,我不知道它。)

此外,任何已经在写入模式下使用该设备的设备都可以继续这样做。因此,这不会影响已安装的文件系统...直到这些文件系统出于任何原因尝试重新打开设备(在重新安装或其他情况下更改安装标志时)。

当然,使分区只读并不会阻止在偏移处向主设备写入某些内容 - 反之亦然。有多个块设备指向完全相同的存储区域是正常的。您必须确保将所有这些设置为只读,而不仅仅是一个。

所以这是可能的,是的,只是不太实际。

设置此标志可能会导致其他程序出现错误,并且此类错误可能会导致不同类型的数据丢失。通常,您希望写入成功或丢失任何应该写入的内容。

因此,这种方法完全有可能造成比它解决的问题更多的问题。最后,您仍然想要格式化您的 USB 记忆棒,为此您必须使其可写,并且为此您必须能够识别和使用正确的设备名称,而不是将其与错误的名称混淆。

您可以检查/dev/disk/by-*/* 是否有更合适的名称,例如/dev/disk/by-id/usb-Flash…不太可能指内部驱动器。

答案4

您正在寻找一种技术解决方案来防止您在计算机上做坏事。

我们许多人学会避免这些问题的一种方法是做错事然后丢失数据。我们学会放慢速度并仔细检查事情。

如果你能够从别人的错误中吸取教训,那就太好了。我从自己的错误中学到了很多东西。

技术解决方案可能会很好地工作你的电脑就像现在一样。改进应对危险行为的方法将帮助您任何未来的电脑。

Unix 是一种能完成小工作的小工具。就像锋利的刀子、剪刀和凿子一样,这完全取决于用户如何使用它们。

对工具感到满意,但永远不要自满。

相关内容