Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions os/StarryOS/kernel/src/syscall/fs/ctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,12 @@ ktracepoint::define_event_trace!(
);

pub fn sys_mkdirat(dirfd: i32, path: *const c_char, mode: u32) -> AxResult<isize> {
let curr = current();
let thread = curr.as_thread();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

建议后续 PR 同步处理 sys_fchownat(ctl.rs:460 let cred = current().as_thread().cred())和 sys_fchmodat 等同类位点——它们也在 vm_load_string() / resolve_at() 之后二次读取 current()。当前 PR 聚焦已观测 crash 路径是合理的。

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
Expand All @@ -150,6 +152,8 @@ pub fn sys_mkdirat(dirfd: i32, path: *const c_char, mode: u32) -> AxResult<isize
}

pub fn sys_mknodat(dirfd: i32, path: *const c_char, mode: u32, dev: u64) -> Result<isize, AxError> {
let curr = current();
let thread = curr.as_thread();
let path = vm_load_string(path)?;
debug!(
"sys_mknodat <= dirfd: {}, path: {:?}, mode: {}, dev: {}",
Expand All @@ -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 {
Expand Down
6 changes: 4 additions & 2 deletions os/StarryOS/kernel/src/syscall/fs/fd_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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}");

Expand Down Expand Up @@ -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 _))
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
128 changes: 128 additions & 0 deletions test-suit/starryos/normal/qemu-smp4/test-openat-umask-smp/c/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>

#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;
}
Original file line number Diff line number Diff line change
@@ -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:']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

success_regex 要求 workers=\d+ iterations=\d+ 精确匹配,fail_regex 同时覆盖 panic 和 FAIL: 前缀,设计清晰。180s timeout 对 8×300 次 openat+write+close+unlink 循环在 QEMU TCG 下留有充足余量。

timeout = 180