根据access(),目录不可写,用户仍然可以在其中创建文件

问题描述 投票:0回答:1

我收到了错误报告 这让我摸不着头脑。在我的程序中,我测试了 目录的可写性(这是用户的主目录) 默认),然后让

readline
收集历史记录并在程序退出时将其写入该目录中的文件。

这是有问题的代码:

if (access(dirname, W_OK) != 0)
  complain("cannot create %s in %s", filename, dirname, errno);
else {
  use_readline_for_stuff();
  write_history("%s/%s", dirname, filename);
  exit(0);
}

(当然,这是伪C。真正的代码是这里

用户(我们称她为

USER
)报告收到错误消息“cannot create xxx in /home/USER: 权限被拒绝”,使用
USER@host > touch /home/USER/xxx
手动创建文件后消失。

我希望一个不可写的主目录会导致各种问题 问题,但用户甚至可以简单地

touch
该目录中的文件。

程序不运行 suid,USER 拥有她的主目录(并且 显然可以在其中创建文件)。我的程序显然是唯一的 显示此类问题的程序。它已被相当广泛地使用 多年来,这是第一次报告此错误

Linux 手册页

access (2)

如果发现某个目录是可写的,则可能意味着 可以在目录下创建文件

为什么可能?为什么(以及何时)不always(除了竞争条件,比如有人在

access()
调用后更改权限、完整的 inode 表或达到用户限制)所有这些似乎都不是这里的问题 - 特别是因为
access()
调用失败,
touch xxx
成功。

c libc rlwrap
1个回答
0
投票

所以,我知道这是一篇 5 年前的帖子,但因为它没有任何答案。因为我在搜索同样的问题时发现了它,所以我想我会用自己的解决方案来回答它。

这实际上更像是一种解决方法,因为我不知道原因。与 OP 类似,我有一个 NFS 目录,其中调用

access(2)
来测试写入权限失败。写入操作本身并没有失败,只是
access(2)
测试失败。

这是我编写的用于排除故障的测试代码(在下面的示例中作为

home_access_test
运行)。

#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char ** argv) {
        char *hd = getenv("HOME");
        if (argc > 1) {
                hd = argv[1];
        }

        int mode = W_OK;
        int r = 0;

        printf("checking if %s is writable.\n",hd);

        r =  access(hd,mode);
        if (r != 0) {
                perror(hd);
                printf("no.\n");
        } else {
                printf("yes.\n");
        }
}

这是测试代码/问题的示例。

jdimpson@magpi:~ $ ./home_access_test /home/jdimpson
checking if /home/jdimpson is writable.
/home/jdimpson: Permission denied
no.
jdimpson@magpi:~ $ ls -ld /home/jdimpson
drwxrwxr-x 60 jdimpson jdimpson 4096 Feb  3 23:01 /home/jdimpson
jdimpson@magpi:~ $ mkdir foo
jdimpson@magpi:~ $ ls -ld /home/jdimpson/foo
drwxr-xr-x 2 jdimpson jdimpson 4096 Feb  3 23:02 /home/jdimpson/foo
jdimpson@magpi:~ $ ./home_access_test /home/jdimpson/foo
checking if /home/jdimpson/foo is writable.
yes.
jdimpson@magpi:~ $

重申此示例所显示的内容,没有实际的写入失败;只是

access(2)
报告的许可被拒绝。这很麻烦,因为我有一个程序拒绝写入其配置文件,因为它所在的目录正在使用
access(2)
进行测试。

简而言之,我的环境是 Linux NFS 服务器和 Linux NFS 客户端,使用 NFSv3 over UDP。

我偶然发现的“解决方案”很简单。设置如下:

jdimpson@magpi:/home $ sudo chmod a+w .
jdimpson@magpi:/home $ ls -ld . jdimpson/ phred/
drwxrwxrwx 20 root     root     4096 Feb  3 23:23 .
drwxrwxr-x 61 jdimpson jdimpson 4096 Feb  3 23:21 jdimpson/
drwx------  7 jdimpson jdimpson 4096 Feb  3 23:23 phred/
jdimpson@magpi:/home $ ~/home_access_test /home/jdimpson
checking if /home/jdimpson is writable.
/home/jdimpson: Permission denied
no.
jdimpson@magpi:/home $ ~/home_access_test /home/phred
checking if /home/phred is writable.
/home/phred: Permission denied
no.

这两个文件夹都存在问题。然后我将一个目录移到另一个目录中,然后再次移出,这修复了该目录:

jdimpson@magpi:/home $ mv jdimpson/ phred
jdimpson@magpi:/home $ ~/home_access_test /home/phred/jdimpson/
bash: /home/jdimpson/home_access_test: No such file or directory
jdimpson@magpi:/home $ /home/phred/jdimpson/home_access_test /home/phred/jdimpson
checking if /home/phred/jdimpson is writable.
yes.
jdimpson@magpi:/home $ mv phred/jdimpson/ .
jdimpson@magpi:/home $ ~/home_access_test /home/jdimpson
checking if /home/jdimpson is writable.
yes.

我对另一个目录重复了它,然后也修复了它:

jdimpson@magpi:/home $ ~/home_access_test /home/phred/
checking if /home/phred/ is writable.
/home/phred/: Permission denied
no.
jdimpson@magpi:/home $ mv phred/ jdimpson/
jdimpson@magpi:/home $ ~/home_access_test /home/jdimpson/phred
checking if /home/jdimpson/phred is writable.
yes.
jdimpson@magpi:/home $ mv jdimpson/phred/ .
jdimpson@magpi:/home $ ~/home_access_test /home/phred/
checking if /home/phred/ is writable.
yes.
sudo chmod go-w .

我不知道根本原因是什么,只能假设将文件夹移动到子文件夹然后退出会导致任何不正确的元数据被修复。

此处未显示,但在 NFS 服务器上运行脚本没有出现问题,并且在 NFS 服务器上以类似方式移动目录也没有修复任何问题。所以我认为问题部分是由 NFS 共享引起的。

© www.soinside.com 2019 - 2024. All rights reserved.