如何使符号链接只读(`chattr +i /location/symlink`)?

如何使符号链接只读(`chattr +i /location/symlink`)?

我们如何锁定符号链接以使其无法被删除?

使用普通的文件/目录chattr +i /file/location可以实现这一点,但是使用符号链接来实现这一点,我们得到chattr: Operation not supported while reading flags on my-file

有一个类似的问题,如何为我的“/etc/resolv.conf”设置“chattr +i”?,但没有可以应用于此处的解决方案。

答案1

这没有提供解决方案,但它解释了为什么chattr不能使符号链接不可变。

在 Linux 上,不可变属性是一组标志的一部分,这些标志使用FS_IOC_SETFLAGS ioctl.从历史上看,这是首先在 ext2 中实现的,并且chattr它本身仍然是e2fsprogs.当它尝试时检索标志,在设置它们之前,chattr显式检查它正在处​​理的文件是常规文件还是目录:

    if (!lstat(name, &buf) &&
        !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
        goto notsupp;
    }

人们可能认为删除这些检查,或更改它们以允许符号链接,将是允许符号链接不可变的良好第一步chattr,但此后立即出现下一个障碍:

    fd = open (name, OPEN_FLAGS);
    if (fd == -1)
        return -1;
    r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);

ioctl对文件描述符进行操作,这意味着必须先打开目标,然后才能设置其标志。符号链接无法打开以用于ioctl;尽管open支持O_NOFOLLOWO_NOPATH在符号链接上,前者本身将失败并显示ELOOP,而后者将返回一个不能与 一起使用的文件描述符ioctl

答案2

符号链接不支持 chattr,但您可以使用绑定安装创建不可删除的链接。

对于目录:

$ mkdir a b
$ echo a>a/ok
$ sudo mount --bind a b
$ cat b/ok
a
$ rmdir b
rmdir: failed to remove 'b': Device or resource busy

对于文件:

$ mkdir c d
$ echo c>c/ok
$ echo d>d/ok
$ sudo mount --bind c/ok d/ok
$ cat d/ok
c
$ rm d/ok
rm: cannot remove 'd/ok': Device or resource busy

答案3

因为我无法发表评论:

chattr 最有可能使用 chmod、fchmod() 或 fchmodat() 系统调用之一,或 ioctl(其中没有提及任何有关符号链接的内容)。不过现在找不到哪个。使用此处的 Ubuntu 手册页,其中一些内容可能会发生变化。

来自 chmod 手册页:

chmod 永远不会更改符号链接的权限; chmod 系统调用无法更改其权限。这不是问题,因为符号链接的权限从未被使用过。然而,对于命令行上列出的每个符号链接,chmod 都会更改指向文件的权限。相反,chmod 会忽略递归目录遍历期间遇到的符号链接。

浏览 fchmod、chmod 和 fchmodat 系统调用的联机帮助页,它们都没有实现它。 Chmod-ing 只会取消引用路径,并且 fchmodat() 系统调用尚未实现 AT_SYMLINK_NOFOLLOW:

AT_SYMLINK_NOFOLLOW 如果路径名是符号链接,则不要取消引用它:而是对链接本身进行操作。该标志当前尚未实现。

相关内容