孙浩宇 closed issue #9: 实现 getuid/getgid/geteuid/getegid/setuid/setgid 等用户身份 sys...

孙浩宇
2026-04-05T12:37:38Z

背景

Linux 兼容性要求每个进程维护自己的用户/组身份信息。目前这些 syscall 全部是 stub，硬编码返回 0：

getuid, getgid, geteuid, getegid — 获取用户/组 ID

setuid, setgid, setresuid, setresgid — 设置用户/组 ID

getgroups, setgroups — 附加组列表

setsid — 创建新会话

许多用户态程序（如 busybox、coreutils）在启动时会调用这些 syscall，返回不合理的值可能导致行为异常。

目标

让进程真正存储和管理 uid/gid 信息，而不是返回硬编码值。

实现指引

1. 在 Process 结构体中添加字段

文件：kernel/src/process/proc.rs（约第 73 行）

pub struct Process {
// ... 已有字段 ...
/// 真实用户 ID
pub uid: u32,
/// 有效用户 ID
pub euid: u32,
/// 真实组 ID
pub gid: u32,
/// 有效组 ID
pub egid: u32,
/// 会话 ID
pub sid: usize,
}

在 Process 的构造函数中初始化为 0（代表 root）。

2. 实现 syscall 函数

参考已有的 sys_getpid（kernel/src/syscall/proc.rs:282）的模式：

pub fn sys_getpid(&mut self) -> SysResult {
info!("getpid");
Ok(self.process().pid.get())
}

你的实现应该类似：

pub fn sys_getuid(&self) -> SysResult {
info!("getuid");
Ok(self.process().uid as usize)
}

pub fn sys_setuid(&self, uid: usize) -> SysResult {
info!("setuid: uid={}", uid);
self.process().uid = uid as u32;
self.process().euid = uid as u32;
Ok(0)
}

其余 getgid、geteuid、getegid、setgid、setsid 同理。

3. 在 syscall 分发表中注册

文件：kernel/src/syscall/mod.rs

将原来的：

SYS_GETUID => self.unimplemented("getuid", Ok(0)),

改为：

SYS_GETUID => self.sys_getuid(),

4. fork 时继承

在 sys_fork/sys_clone 创建子进程时，确保子进程继承父进程的 uid/gid。查看 kernel/src/syscall/proc.rs 中 sys_fork 的实现。

涉及的 Rust 知识

结构体字段定义和访问

方法（&self / &mut self）

基本类型转换（as）

模式匹配（syscall 分发的 match）

难度

⭐ 入门级 — 适合刚学完 Rust 基本类型、所有权和方法的同学

验证方式

实现后，id 命令和调用 getuid() 的程序应该能正常运行而不产生 warning 日志。