我写了这段测试代码,发现这个程序即使在运行时取消了读取权限,也始终能成功读取文件getchar()
。
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/types.h>
int main(){
int f = open("a.txt",O_RDONLY);
uint8_t data[200];
printf("Got %d from read", pread(f, (void *)data, 200, 0));
getchar();
printf("Got %d from read", pread(f, (void *)data, 200, 0));
}
这个程序打印了
读完得9分
两次,即使我chmod a-r a.txt
在暂停期间使用。
我很确定我只是一个普通用户,我的进程没有 CAP_DAC_OVERRIDE;为什么第二个不pread()
返回任何错误?
我的猜测是,在进行读/写时,内核仅检查打开文件描述的文件权限,该文件描述是使用 创建的open()
,并且即使我更改了底层文件系统上的文件权限也不会更改。
我的猜测正确吗?
额外问题:
如果我是对的,那么 mmaped 区域怎么样?
当我读/写/执行该映射区域时,内核是否只检查页表中记录的权限?
存储在文件系统中的真正 inode 数据是否仅在创建打开文件描述和 mmap 区域时使用?
答案1
是的,仅在开放时检查权限并记录。因此,无论您是否能够写入文件,都无法写入以只读访问方式打开的文件描述符。
内核查阅内存中的索引节点而不是存储在文件系统中的索引节点。它们的不同之处在于打开文件的引用计数,并且挂载点获取已挂载文件的索引节点。
如果我是对的,那么 mmaped 区域怎么样?
相同的。 (传递给的 PROT_* 标志mmap()
相当于传递给的 O_RDWR / O_RDONLY / O_WRONLY 标志open()
)。
当我读/写/执行该映射区域时,内核是否只检查页表中记录的权限?
我不确定它什么时候可以检查页表中记录的权限:-)。据我了解你的问题:是的。
存储在文件系统中的真正 inode 数据是否仅在创建打开文件描述和 mmap 区域时使用?
还检查元数据操作的 inode 权限,例如mkdir()
(open()
与 O_CREAT 类似)。
并且不要忘记chdir()
,这与任何调用都不同open()
。 (或者至少,它与open()
当前 Linux 上的任何调用不同)。
我不确定 SELinux 特定的权限。