Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] FileMode::contain函数在判断O_WRONLY时,检测到同时存在O_WRONLY和O_RDONLY #1059

Closed
xiaolin2004 opened this issue Nov 27, 2024 · 5 comments · Fixed by #1061
Assignees
Labels
A-fs Area: 文件系统 bug Something isn't working needs-triage 这个问题可能需要分类处理。如果已经完成分类,请移除它。

Comments

@xiaolin2004
Copy link
Collaborator

xiaolin2004 commented Nov 27, 2024

描述错误
调换Pipe::open中判断O_WRONLY和O_RDONLY的判断顺序之后
image

请填写您的电脑的信息:

重现步骤
重现行为的步骤:

  1. 修改代码DragonOS/kernel/src/ipc/pipe.rs
fn open(
        &self,
        mut data: SpinLockGuard<FilePrivateData>,
        mode: &crate::filesystem::vfs::file::FileMode,
    ) -> Result<(), SystemError> {
        let mut guard = self.inner.lock();
        // 不能以读写方式打开管道
        if mode.contains(FileMode::O_WRONLY) {
            println!(
                "FIFO:     pipe try open in write mode with {} reader, writer pid:{:?}",
                guard.reader,
                ProcessManager::current_pid()
            );
            guard.writer += 1;
        }
        if mode.contains(FileMode::O_RDWR) {
            return Err(SystemError::EACCES);
        }
        if mode.contains(FileMode::O_RDONLY) {
            guard.reader += 1;
            guard.had_reader = true;
            println!(
                "FIFO:     pipe try open in read mode with reader pid:{:?}",
                ProcessManager::current_pid()
            );
        }
...
}
  1. 使用以下测试代码进行测试
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>

#define FIFO_PATH "/bin/test_fifo"

int main() {
    // 创建 FIFO
    if (mkfifo(FIFO_PATH, 0666) == -1 && errno != EEXIST) {
        perror("mkfifo failed");
        exit(EXIT_FAILURE);
    }

    printf("Opening FIFO in write mode...\n");

    // 尝试以阻塞模式打开 FIFO 的写端
    int fd = open(FIFO_PATH, O_WRONLY=);
    printf("fd: %d\n",fd);
    if (fd == -1) {
        if (errno == ENXIO) {
            printf("Error: No readers (ENXIO).\n");
        } else {
            perror("Failed to open FIFO");
        }
    } else {
        printf("FIFO opened successfully in write mode.\n");
        close(fd);
    }

    // 删除 FIFO
    unlink(FIFO_PATH);

    return 0;
}
  1. 运行测试

期望行为
两个mode应该是互斥关系,不应该重复判断

其他上下文
#886 (comment)

@dragonosbot dragonosbot added the needs-triage 这个问题可能需要分类处理。如果已经完成分类,请移除它。 label Nov 27, 2024
@xiaolin2004 xiaolin2004 added bug Something isn't working A-fs Area: 文件系统 labels Nov 27, 2024
@xiaolin2004 xiaolin2004 changed the title [BUG REPORT] FileMode::contain函数在判断O_WRONLY时,检测到同时存在O_WRONLY和O_RDONLY [BUG] FileMode::contain函数在判断O_WRONLY时,检测到同时存在O_WRONLY和O_RDONLY Nov 27, 2024
@xiaolin2004
Copy link
Collaborator Author

xiaolin2004 commented Nov 27, 2024

在bitflags-1.3.2库中,contain代码如下

/// Returns `true` if all of the flags in `other` are contained within `self`.
            #[inline]
            pub const fn contains(&self, other: Self) -> bool {
                (self.bits & other.bits) == other.bits
            }

而FileMode 中,这些模式(O_RDONLY、O_WRONLY、O_RDWR)的值是 非互斥的
因为 O_RDONLY 的值为 0,所以在 contains 检查时:

(self.bits & other.bits) == other.bits

如果 other 是 O_RDONLY,无论 self.bits 的值如何,这个判断始终为 true,因为:

self.bits & 0 == 0

即只要 other.bits == 0,条件总是成立。

需要重新设定FileMode中的模式以保证其之间的互斥性

@fslongjin
Copy link
Member

FileMode那个是Linux规定的。那看来判断是否O_RDONLY、O_WRONLY、O_RDWR的话,应该是得在file mode里面实现个函数去判断。

判断方法应该是filemode.bits & 0x3 之后,判断跟上面的O_RDONLY、O_WRONLY、O_RDWR是否相等

@xiaolin2004
Copy link
Collaborator Author

xiaolin2004 commented Nov 27, 2024

Linux 使用 O_ACCMODE 掩码 来提取文件访问模式

#define O_ACCMODE 0x0003
int access_mode = flags & O_ACCMODE;
if (access_mode == O_RDONLY) {
    // Handle read-only
} else if (access_mode == O_WRONLY) {
    // Handle write-only
} else if (access_mode == O_RDWR) {
    // Handle read-write
}

@xiaolin2004
Copy link
Collaborator Author

xiaolin2004 commented Nov 27, 2024

FileMode那个是Linux规定的。那看来判断是否O_RDONLY、O_WRONLY、O_RDWR的话,应该是得在file mode里面实现个函数去判断。

判断方法应该是filemode.bits & 0x3 之后,判断跟上面的O_RDONLY、O_WRONLY、O_RDWR是否相等

该方法已经存在
accmode

@xiaolin2004 xiaolin2004 self-assigned this Nov 27, 2024
@xiaolin2004
Copy link
Collaborator Author

#1060 (comment)
在此pr中解决

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-fs Area: 文件系统 bug Something isn't working needs-triage 这个问题可能需要分类处理。如果已经完成分类,请移除它。
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants