os/kernel/syscall/
cred.rs

1//! 用户凭证和权限相关的系统调用
2//!
3//! 在单 root 用户系统中,这些系统调用存储值但不实际限制权限
4
5use crate::kernel::task::current_task;
6use crate::uapi::cred::{GID_UNCHANGED, ROOT_GID, ROOT_UID, UID_UNCHANGED};
7use crate::uapi::errno::{EFAULT, EPERM};
8use crate::util::user_buffer::{validate_user_ptr_mut, write_to_user};
9
10/// 获取真实用户 ID
11///
12/// 返回当前进程的真实用户 ID
13pub fn getuid() -> isize {
14    let task = current_task();
15    let task_inner = task.lock();
16    task_inner.credential.uid as isize
17}
18
19/// 获取有效用户 ID
20///
21/// 返回当前进程的有效用户 ID(用于权限检查)
22pub fn geteuid() -> isize {
23    let task = current_task();
24    let task_inner = task.lock();
25    task_inner.credential.euid as isize
26}
27
28/// 获取真实组 ID
29///
30/// 返回当前进程的真实组 ID
31pub fn getgid() -> isize {
32    let task = current_task();
33    let task_inner = task.lock();
34    task_inner.credential.gid as isize
35}
36
37/// 获取有效组 ID
38///
39/// 返回当前进程的有效组 ID(用于权限检查)
40pub fn getegid() -> isize {
41    let task = current_task();
42    let task_inner = task.lock();
43    task_inner.credential.egid as isize
44}
45
46/// 设置用户 ID
47///
48/// 在单 root 用户系统中,只允许设置为 0(root)
49pub fn setuid(uid: u32) -> isize {
50    if uid == ROOT_UID {
51        // 在单 root 用户系统中,uid 始终是 0,不需要实际修改
52        0
53    } else {
54        // 假装没有权限设置非 root 用户
55        -EPERM as isize
56    }
57}
58
59/// 设置组 ID
60///
61/// 在单 root 用户系统中,只允许设置为 0(root 组)
62pub fn setgid(gid: u32) -> isize {
63    if gid == ROOT_GID { 0 } else { -EPERM as isize }
64}
65
66/// 设置有效用户 ID
67pub fn seteuid(euid: u32) -> isize {
68    if euid == ROOT_UID { 0 } else { -EPERM as isize }
69}
70
71/// 设置有效组 ID
72pub fn setegid(egid: u32) -> isize {
73    if egid == ROOT_GID { 0 } else { -EPERM as isize }
74}
75
76/// 同时设置真实、有效和保存的用户 ID
77///
78/// # 参数
79/// * `ruid` - 真实用户 ID(u32::MAX 表示不改变)
80/// * `euid` - 有效用户 ID(u32::MAX 表示不改变)
81/// * `suid` - 保存的用户 ID(u32::MAX 表示不改变)
82///
83/// # 返回值
84/// * 0 - 成功
85/// * -EPERM - 权限不足
86/// * -EINVAL - 无效参数
87pub fn setresuid(ruid: u32, euid: u32, suid: u32) -> isize {
88    // 检查参数有效性:要么是 ROOT_UID,要么是 UID_UNCHANGED
89    if (ruid != ROOT_UID && ruid != UID_UNCHANGED)
90        || (euid != ROOT_UID && euid != UID_UNCHANGED)
91        || (suid != ROOT_UID && suid != UID_UNCHANGED)
92    {
93        return -EPERM as isize;
94    }
95
96    // 在单 root 用户系统中,所有 ID 始终是 0,不需要实际修改
97    0
98}
99
100/// 同时设置真实、有效和保存的组 ID
101///
102/// # 参数
103/// * `rgid` - 真实组 ID(u32::MAX 表示不改变)
104/// * `egid` - 有效组 ID(u32::MAX 表示不改变)
105/// * `sgid` - 保存的组 ID(u32::MAX 表示不改变)
106///
107/// # 返回值
108/// * 0 - 成功
109/// * -EPERM - 权限不足
110/// * -EINVAL - 无效参数
111pub fn setresgid(rgid: u32, egid: u32, sgid: u32) -> isize {
112    // 检查参数有效性:要么是 ROOT_GID,要么是 GID_UNCHANGED
113    if (rgid != ROOT_GID && rgid != GID_UNCHANGED)
114        || (egid != ROOT_GID && egid != GID_UNCHANGED)
115        || (sgid != ROOT_GID && sgid != GID_UNCHANGED)
116    {
117        return -EPERM as isize;
118    }
119
120    // 在单 root 用户系统中,所有 ID 始终是 0,不需要实际修改
121    0
122}
123
124/// 获取真实、有效和保存的用户 ID
125///
126/// # 参数
127/// * `ruid` - 指向存储真实用户 ID 的指针
128/// * `euid` - 指向存储有效用户 ID 的指针
129/// * `suid` - 指向存储保存的用户 ID 的指针
130///
131/// # 返回值
132/// * 0 - 成功
133/// * -EFAULT - 指针无效(指向内核空间或不可写)
134///
135/// # 安全性
136/// 此函数会验证所有指针是否指向有效的用户空间地址,
137/// 防止恶意用户程序传入内核空间地址导致内核内存被破坏。
138pub fn getresuid(ruid: *mut u32, euid: *mut u32, suid: *mut u32) -> isize {
139    // 验证所有指针的有效性
140    if !ruid.is_null() && !validate_user_ptr_mut(ruid) {
141        return -(EFAULT as isize);
142    }
143    if !euid.is_null() && !validate_user_ptr_mut(euid) {
144        return -(EFAULT as isize);
145    }
146    if !suid.is_null() && !validate_user_ptr_mut(suid) {
147        return -(EFAULT as isize);
148    }
149
150    let task = current_task();
151    let task_inner = task.lock();
152    let cred = &task_inner.credential;
153
154    // 安全地写入用户空间
155    unsafe {
156        if !ruid.is_null() {
157            write_to_user(ruid, cred.uid);
158        }
159        if !euid.is_null() {
160            write_to_user(euid, cred.euid);
161        }
162        if !suid.is_null() {
163            write_to_user(suid, cred.suid);
164        }
165    }
166    0
167}
168
169/// 获取真实、有效和保存的组 ID
170///
171/// # 参数
172/// * `rgid` - 指向存储真实组 ID 的指针
173/// * `egid` - 指向存储有效组 ID 的指针
174/// * `sgid` - 指向存储保存的组 ID 的指针
175///
176/// # 返回值
177/// * 0 - 成功
178/// * -EFAULT - 指针无效(指向内核空间或不可写)
179///
180/// # 安全性
181/// 此函数会验证所有指针是否指向有效的用户空间地址,
182/// 防止恶意用户程序传入内核空间地址导致内核内存被破坏。
183pub fn getresgid(rgid: *mut u32, egid: *mut u32, sgid: *mut u32) -> isize {
184    // 验证所有指针的有效性
185    if !rgid.is_null() && !validate_user_ptr_mut(rgid) {
186        return -(EFAULT as isize);
187    }
188    if !egid.is_null() && !validate_user_ptr_mut(egid) {
189        return -(EFAULT as isize);
190    }
191    if !sgid.is_null() && !validate_user_ptr_mut(sgid) {
192        return -(EFAULT as isize);
193    }
194
195    let task = current_task();
196    let task_inner = task.lock();
197    let cred = &task_inner.credential;
198
199    // 安全地写入用户空间
200    unsafe {
201        if !rgid.is_null() {
202            write_to_user(rgid, cred.gid);
203        }
204        if !egid.is_null() {
205            write_to_user(egid, cred.egid);
206        }
207        if !sgid.is_null() {
208            write_to_user(sgid, cred.sgid);
209        }
210    }
211    0
212}
213
214/// 设置文件创建掩码
215///
216/// # 参数
217/// * `mask` - 新的 umask 值
218///
219/// # 返回值
220/// 返回之前的 umask 值
221///
222/// # 注意
223/// 在当前方案中,umask 值会被存储但不会实际应用到文件创建过程z
224pub fn umask(mask: u32) -> isize {
225    let task = current_task();
226    let mut task_inner = task.lock();
227    let old_umask = task_inner.umask;
228    task_inner.umask = mask & 0o777; // 只保留权限位
229    old_umask as isize
230}