Unix 在FreeBSD上,为什么chmod+;t在非目录上执行特权操作?

Unix 在FreeBSD上,为什么chmod+;t在非目录上执行特权操作?,unix,freebsd,chmod,Unix,Freebsd,Chmod,在FreeBSD上,如果file不是目录,则chmod+t file是一种特权操作: $ 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 A special file mode, called the stic

在FreeBSD上,如果
file
不是目录,则
chmod+t file
是一种特权操作:

$ 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
 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.
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)说明如果
文件
不是目录,则忽略
S_ISVTX

$ 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
 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.
一种特殊的文件模式,称为粘性位(模式S_isText),用于
指示对目录的特殊处理。它被忽略为常规
文件夹。有关文件的说明,请参阅chmod(2)或文件
模式。
在FreeBSD上将非目录标记为粘性是一种特权操作的历史或技术原因是什么?为什么在本应为
EPERM
ENOTDIR
的地方发明了额外的错误代码
EFTYPE

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

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

为什么在本应为EPERM或ENOTDIR的情况下为此发明了额外的错误代码EFTYPE


见第(2)条。EFTYPE并不是专门为这种情况而发明的,它的含义更广泛,并且比EPERM更适合这种情况,而ENOTDIR的用途完全不相关。

从历史上看,最初的Unix不允许这样做。警察说

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

如果用户试图设置粘性位,则不会返回错误,但它只是默默地关闭了该位:

if (u.u_uid)
    uap->fmode &= ~ISVTX;
这一行为未经任何修改就继续存在于BSD中。具有以下代码,该代码在非根用户的非目录上以静默方式关闭ISVTX位:

if (u.u_uid) {
    if ((ip->i_mode & IFMT) != IFDIR)
        mode &= ~ISVTX;
    ...
}
代码已更改为返回错误
EFTYPE
,但未提及该错误。我不知道为什么要改

if (cred->cr_uid) {
    if (vp->v_type != VDIR && (mode & ISVTX))
        return (EFTYPE);
    ...
}
包含与4.4BSD相同的代码

if (cred->cr_uid) {
    if (vp->v_type != VDIR && (mode & ISVTX))
         return (EFTYPE);
    ...
}
这已转入当前版本。有以下几点:

if (vp->v_type != VDIR && (mode & S_ISTXT)) {
    if (priv_check_cred(cred, PRIV_VFS_STICKYFILE, 0))
        return (EFTYPE);
}
有类似的代码:

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

Solaris 10以静默方式忽略非root用户设置文件粘性位的尝试。(如果可用,我将添加源代码片段。)

我测试的所有其他系统都允许任意用户将文件设置为粘性文件。这和二进制文件的粘性位(在交换空间中保留二进制文件)的历史意义是一致的。FreeBSD是唯一的异常值。您的帖子没有给出合理的解释,也没有提供其声明的来源。向下投票。哦,是的,
chmod
(及其变体)是唯一将
errno
设置为
EFTYPE
的系统调用。系统调用不是唯一使用标准错误代码的地方。遗憾的是,
EFTYPE
不是我发现的任何标准的一部分。从历史上看,最初的Unix不允许这样做。手册页上说“设置此位的能力仅限于超级用户,因为交换空间被图像占用”。我无法解释为什么后代选择保留这一禁令,即使他们不支持该功能。OpenBSD还禁止非root用户在文件上设置粘性位,返回EFTYPE。Solaris会自动忽略非root用户在文件上设置粘性位的尝试(chmod()返回0,但无效)。@MarkPlotnick您能将此转换为答案吗?这回答了我的问题。