diff --git a/os/StarryOS/kernel/src/syscall/fs/ctl.rs b/os/StarryOS/kernel/src/syscall/fs/ctl.rs index 95cf25880d..598cddd606 100644 --- a/os/StarryOS/kernel/src/syscall/fs/ctl.rs +++ b/os/StarryOS/kernel/src/syscall/fs/ctl.rs @@ -128,10 +128,12 @@ ktracepoint::define_event_trace!( ); pub fn sys_mkdirat(dirfd: i32, path: *const c_char, mode: u32) -> AxResult { + let curr = current(); + let thread = curr.as_thread(); let path = vm_load_string(path)?; debug!("sys_mkdirat <= dirfd: {dirfd}, path: {path}, mode: {mode}"); - let mode = mode & !current().as_thread().proc_data.umask(); + let mode = mode & !thread.proc_data.umask(); let mode = NodePermission::from_bits_truncate(mode as u16); // call tp:trace_sys_mkdirat @@ -150,6 +152,8 @@ pub fn sys_mkdirat(dirfd: i32, path: *const c_char, mode: u32) -> AxResult Result { + let curr = current(); + let thread = curr.as_thread(); let path = vm_load_string(path)?; debug!( "sys_mknodat <= dirfd: {}, path: {:?}, mode: {}, dev: {}", @@ -160,7 +164,7 @@ pub fn sys_mknodat(dirfd: i32, path: *const c_char, mode: u32, dev: u64) -> Resu let ftype = mode & S_IFMT; let mut perm = mode & !S_IFMT; // apply umask like mkdir - perm &= !current().as_thread().proc_data.umask(); + perm &= !thread.proc_data.umask(); // Linux mknod semantics: S_IFDIR → EPERM, unknown type bits → EINVAL. let node_type = match ftype { diff --git a/os/StarryOS/kernel/src/syscall/fs/fd_ops.rs b/os/StarryOS/kernel/src/syscall/fs/fd_ops.rs index 466b34c6a7..31c1b5d212 100644 --- a/os/StarryOS/kernel/src/syscall/fs/fd_ops.rs +++ b/os/StarryOS/kernel/src/syscall/fs/fd_ops.rs @@ -218,6 +218,8 @@ pub fn sys_openat( // call tp:trace_sys_enter_openat trace_sys_enter_openat(dirfd, path as _, flags as _, mode); + let curr = current(); + let thread = curr.as_thread(); let path = vm_load_string(path)?; debug!("sys_openat <= {dirfd} {path:?} {flags:#o} {mode:#o}"); @@ -266,9 +268,9 @@ pub fn sys_openat( dirfd }; - let mode = mode & !current().as_thread().proc_data.umask(); + let mode = mode & !thread.proc_data.umask(); - let cred = current().as_thread().cred(); + let cred = thread.cred(); let options = flags_to_options(flags, mode, (cred.fsuid, cred.fsgid)); with_fs(dirfd, |fs| options.open(fs, path)) .and_then(|it| add_to_fd(it, flags as _)) diff --git a/test-suit/starryos/normal/qemu-smp4/test-openat-umask-smp/c/CMakeLists.txt b/test-suit/starryos/normal/qemu-smp4/test-openat-umask-smp/c/CMakeLists.txt new file mode 100644 index 0000000000..61db0d7aa8 --- /dev/null +++ b/test-suit/starryos/normal/qemu-smp4/test-openat-umask-smp/c/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.20) +project(test-openat-umask-smp C) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS OFF) +add_executable(test-openat-umask-smp src/main.c) +target_compile_options(test-openat-umask-smp PRIVATE -Wall -Wextra -Werror) +install(TARGETS test-openat-umask-smp RUNTIME DESTINATION usr/bin) diff --git a/test-suit/starryos/normal/qemu-smp4/test-openat-umask-smp/c/src/main.c b/test-suit/starryos/normal/qemu-smp4/test-openat-umask-smp/c/src/main.c new file mode 100644 index 0000000000..af7ab023ac --- /dev/null +++ b/test-suit/starryos/normal/qemu-smp4/test-openat-umask-smp/c/src/main.c @@ -0,0 +1,128 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WORKERS 8 +#define ITERS 300 +#define STACK_SIZE (64 * 1024) + +static volatile int g_started; +static volatile int g_done; +static volatile int g_failed; +static volatile int g_progress; + +static int worker(void *arg) +{ + int id = (int)(long)arg; + char path[128]; + + __sync_fetch_and_add(&g_started, 1); + + for (int i = 0; i < ITERS && !g_failed; i++) { + mode_t old = umask((mode_t)((id + i) & 077)); + + snprintf(path, sizeof(path), "/tmp/openat-umask-smp-%d-%d.tmp", id, i); + int fd = openat(AT_FDCWD, path, O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, 0666); + (void)umask(old); + if (fd < 0) { + printf("FAIL: worker %d openat iter %d errno=%d (%s)\n", id, i, + errno, strerror(errno)); + g_failed = 1; + return 1; + } + + if (write(fd, "x", 1) != 1) { + printf("FAIL: worker %d write iter %d errno=%d (%s)\n", id, i, errno, + strerror(errno)); + g_failed = 1; + } + close(fd); + unlink(path); + + __sync_fetch_and_add(&g_progress, 1); + if ((i & 15) == 0) { + sched_yield(); + } + } + + __sync_fetch_and_add(&g_done, 1); + return g_failed ? 1 : 0; +} + +int main(void) +{ + setvbuf(stdout, NULL, _IONBF, 0); + + void *stacks[WORKERS]; + int tids[WORKERS]; + memset(stacks, 0, sizeof(stacks)); + memset(tids, -1, sizeof(tids)); + + int flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND; + for (int i = 0; i < WORKERS; i++) { + stacks[i] = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (stacks[i] == MAP_FAILED) { + printf("FAIL: mmap stack %d errno=%d (%s)\n", i, errno, + strerror(errno)); + return 1; + } + + int tid = clone(worker, (char *)stacks[i] + STACK_SIZE, flags, + (void *)(long)i); + if (tid < 0) { + printf("FAIL: clone worker %d errno=%d (%s)\n", i, errno, + strerror(errno)); + return 1; + } + tids[i] = tid; + } + + int last = -1; + int stalls = 0; + for (int tick = 0; tick < 600 && g_done < WORKERS && !g_failed; tick++) { + usleep(100000); + int progress = __atomic_load_n(&g_progress, __ATOMIC_RELAXED); + if (progress == last) { + if (++stalls > 100) { + printf("FAIL: stalled started=%d done=%d progress=%d\n", g_started, + g_done, progress); + g_failed = 1; + break; + } + } else { + stalls = 0; + last = progress; + } + } + + for (int i = 0; i < WORKERS; i++) { + if (tids[i] >= 0) { + int status = 0; + if (waitpid(tids[i], &status, __WALL) < 0) { + printf("FAIL: wait worker %d errno=%d (%s)\n", i, errno, + strerror(errno)); + g_failed = 1; + } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + printf("FAIL: worker %d exit status=0x%x\n", i, status); + g_failed = 1; + } + } + } + + if (g_failed || g_done != WORKERS || g_progress != WORKERS * ITERS) { + printf("FAIL: started=%d done=%d progress=%d expected=%d\n", g_started, + g_done, g_progress, WORKERS * ITERS); + return 1; + } + + printf("PASS: openat_umask_smp workers=%d iterations=%d\n", WORKERS, ITERS); + return 0; +} diff --git a/test-suit/starryos/normal/qemu-smp4/test-openat-umask-smp/qemu-riscv64.toml b/test-suit/starryos/normal/qemu-smp4/test-openat-umask-smp/qemu-riscv64.toml new file mode 100644 index 0000000000..90f72c1c5e --- /dev/null +++ b/test-suit/starryos/normal/qemu-smp4/test-openat-umask-smp/qemu-riscv64.toml @@ -0,0 +1,17 @@ +args = [ + "-nographic", "-cpu", "rv64", + "-m", "512M", + "-smp", "4", + "-accel", "tcg,thread=single", + "-device", "virtio-blk-pci,drive=disk0", + "-drive", "id=disk0,if=none,format=raw,file=${workspace}/tmp/axbuild/rootfs/rootfs-riscv64-alpine.img", + "-device", "virtio-net-pci,netdev=net0", + "-netdev", "user,id=net0", +] +uefi = false +to_bin = true +shell_prefix = "root@starry:" +shell_init_cmd = "/usr/bin/test-openat-umask-smp" +success_regex = ['(?m)^PASS: openat_umask_smp workers=\d+ iterations=\d+\s*$'] +fail_regex = ['(?i)\bpanic(?:ked)?\b', '(?m)^FAIL:'] +timeout = 180