【问题标题】:On FreeBSD, why is chmod +t on a non-directory a privileged operation?在 FreeBSD 上,为什么非目录上的 chmod +t 是特权操作?
【发布时间】:2016-01-26 11:53:43
【问题描述】:

在 FreeBSD 上,如果 <em>file</em> 不是目录,chmod +t <em>file</em> 是特权操作:

$ echo >test
$ chmod +t test
chmod: test: Inappropriate file type or format
$ su
Password:
# chmod +t test
# ls -l test
-rw-r--r-T  1 fuz  wheel  1 Jan 26 12:44 test

chmod(2) 记录了这种行为:

 [EFTYPE]           The effective user ID is not the super-user, the mode
                    includes the sticky bit (S_ISVTX), and path does not
                    refer to a directory.

同时,sticky(7) 解释说如果<em>file</em> 不是目录,S_ISVTX 将被忽略:

 A special file mode, called the sticky bit (mode S_ISTXT), is used to
 indicate special treatment for directories.  It is ignored for regular
 files.  See chmod(2) or the file <sys/stat.h> for an explanation of file
 modes.

在 FreeBSD 上将非目录标记为粘性是一项特权操作的历史或技术原因是什么?为什么在应该是EPERM 或ENOTDIR 的地方为此发明了一个额外的错误代码EFTYPE?

【问题讨论】:

  • 从历史上看,最初的 Unix 不允许这样做。 V7 chmod 手册页说“设置此位的能力仅限于超级用户,因为图像消耗了交换空间”。我不能说为什么后代选择保留这个禁令,即使他们不支持这个功能。 OpenBSD 还禁止非 root 用户在文件上设置粘性位,返回 EFTYPE。 Solaris 会默默地忽略非 root 用户对文件设置粘性位的尝试(chmod() 返回 0 但没有效果)。
  • @MarkPlotnick 你能把这个变成答案吗?这回答了我的问题。

标签: unix freebsd chmod


【解决方案1】:

从历史上看,最初的 Unix 不允许这样做。 V7 chmod man page 说

设置此位的能力仅限于超级用户,因为图像会占用交换空间

V7 chmod system call 不会在用户尝试设置粘性位时返回错误,但它只是默默地关闭了该位:

if (u.u_uid)
    uap->fmode &= ~ISVTX;

此行为在 BSD 上保持不变。 4.3BSD 有这个代码,它会默默地关闭非 root 用户的非目录上的 ISVTX 位:

if (u.u_uid) {
    if ((ip->i_mode & IFMT) != IFDIR)
        mode &= ~ISVTX;
    ...
}

4.4BSD 中的代码已更改为返回错误EFTYPE,尽管4.4BSD chmod man page 没有提及它。不知道为什么改了。

if (cred->cr_uid) {
    if (vp->v_type != VDIR && (mode & ISVTX))
        return (EFTYPE);
    ...
}

FreeBSD 1.0 包含与 4.4BSD 相同的代码。

if (cred->cr_uid) {
    if (vp->v_type != VDIR && (mode & ISVTX))
         return (EFTYPE);
    ...
}

这已延续到当前版本。 FreeBSD 10.2 有这个:

if (vp->v_type != VDIR && (mode & S_ISTXT)) {
    if (priv_check_cred(cred, PRIV_VFS_STICKYFILE, 0))
        return (EFTYPE);
}

OpenBSD 有类似的代码:

if (cred->cr_uid) {
    if (vp->v_type != VDIR && (mode & S_ISTXT))
        return (EFTYPE);
    ...
}

Solaris 10 会默默地忽略非 root 用户在文件上设置粘性位的尝试。 (我会在有源代码的时候添加sn-ps。)

【讨论】:

    【解决方案2】:

    在 FreeBSD 上将非目录标记为粘性是一项特权操作的历史或技术原因是什么?

    为什么不应该呢?首先,这显然不是一个有意义的操作,因此应该将它作为失败报告给用户,以表明他做错了什么。此外,允许它与任何未使用的标志或字段一样不是未来证明 - 它可能用于将来的某些事情,并且不会造成安全或一致性风险,它应该处于可预测的状态。

    为什么在应该是 EPERM 或 ENOTDIR 的地方为此发明了一个额外的错误代码 EFTYPE?

    请参阅 errno(2)。 EFTYPE不是专门为这种情况发明的,意义更广,比EPERM更适合这种情况,而ENOTDIR则完全不相关。

    【讨论】:

    • 我测试的所有其他系统都允许任意用户将文件设置为粘性。这与二进制文件粘性位的历史意义相吻合(将二进制文件保留在交换空间中)。 FreeBSD 是唯一的异常值。您的帖子没有给出合理的解释,也没有提供其主张的来源。投反对票。
    • 哦,是的,chmod(及其变体)是唯一将errno 设置为EFTYPE 的系统调用。
    • 系统调用并不是唯一使用标准错误代码的地方。
    • 遗憾的是,EFTYPE 不是我找到的任何标准的一部分。
    猜你喜欢
    • 2013-11-01
    • 2011-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 2015-05-24
    • 2014-10-11
    • 1970-01-01
    相关资源
    最近更新 更多