Skip to content

Commit cb0ea91

Browse files
committed
syscall/process: Implement set{u,g,res}id sycalls
1 parent f41031c commit cb0ea91

2 files changed

Lines changed: 157 additions & 13 deletions

File tree

kernel/src/syscall/mod.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -251,25 +251,25 @@ pub(crate) fn dispatch(frame: &mut Context) {
251251

252252
// Identity
253253
numbers::GETGROUPS => sys_unimpl!("getgroups", Ok(0)),
254-
numbers::SETGROUPS => sys_unimpl!("setgroups", Err(Errno::ENOSYS)),
254+
numbers::SETGROUPS => sys_unimpl!("setgroups", Ok(0)),
255255
numbers::GETSID => process::getsid,
256256
numbers::SETSID => process::setsid,
257-
numbers::SETUID => sys_unimpl!("setuid", Ok(0)),
257+
numbers::SETUID => process::setuid,
258258
numbers::GETUID => process::getuid,
259-
numbers::SETGID => sys_unimpl!("setgid", Ok(0)),
259+
numbers::SETGID => process::setgid,
260260
numbers::GETGID => process::getgid,
261261
numbers::GETEUID => process::geteuid,
262-
numbers::SETEUID => sys_unimpl!("seteuid", Ok(0)),
262+
numbers::SETEUID => process::seteuid,
263263
numbers::GETEGID => process::getegid,
264-
numbers::SETEGID => sys_unimpl!("setegid", Ok(0)),
264+
numbers::SETEGID => process::setegid,
265265
numbers::GETPGID => process::getpgid,
266266
numbers::SETPGID => process::setpgid,
267267
numbers::GETRESUID => process::getresuid,
268-
numbers::SETRESUID => sys_unimpl!("setresuid", Err(Errno::ENOSYS)),
268+
numbers::SETRESUID => process::setresuid,
269269
numbers::GETRESGID => process::getresgid,
270-
numbers::SETRESGID => sys_unimpl!("setresgid", Err(Errno::ENOSYS)),
271-
numbers::SETREUID => sys_unimpl!("setreuid", Err(Errno::ENOSYS)),
272-
numbers::SETREGID => sys_unimpl!("setregid", Err(Errno::ENOSYS)),
270+
numbers::SETRESGID => process::setresgid,
271+
numbers::SETREUID => process::setreuid,
272+
numbers::SETREGID => process::setregid,
273273
numbers::UMASK => process::umask,
274274

275275
// Limits

kernel/src/syscall/process.rs

Lines changed: 148 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
to_user,
1111
},
1212
sched::Scheduler,
13-
uapi::{self, limits::PATH_MAX, pid_t, uid_t},
13+
uapi::{self, gid_t, limits::PATH_MAX, pid_t, uid_t},
1414
vfs::{File, file::OpenFlags, inode::Mode},
1515
wrap_syscall,
1616
};
@@ -76,14 +76,83 @@ pub fn getresuid(ruid: VirtAddr, euid: VirtAddr, suid: VirtAddr) -> EResult<()>
7676
Ok(())
7777
}
7878

79+
#[wrap_syscall]
80+
pub fn setuid(uid: uid_t) -> EResult<()> {
81+
let proc = Scheduler::get_current().get_process();
82+
let mut ident = proc.identity.lock();
83+
if ident.is_effective_superuser() {
84+
ident.user_id = uid;
85+
ident.effective_user_id = uid;
86+
ident.set_user_id = uid;
87+
Ok(())
88+
} else if uid == ident.user_id || uid == ident.effective_user_id || uid == ident.set_user_id {
89+
ident.effective_user_id = uid;
90+
Ok(())
91+
} else {
92+
Err(Errno::EPERM)
93+
}
94+
}
95+
96+
#[wrap_syscall]
97+
pub fn seteuid(euid: uid_t) -> EResult<()> {
98+
let proc = Scheduler::get_current().get_process();
99+
let mut ident = proc.identity.lock();
100+
if ident.is_effective_superuser()
101+
|| euid == ident.user_id
102+
|| euid == ident.effective_user_id
103+
|| euid == ident.set_user_id
104+
{
105+
ident.effective_user_id = euid;
106+
Ok(())
107+
} else {
108+
Err(Errno::EPERM)
109+
}
110+
}
111+
112+
#[wrap_syscall]
113+
pub fn setresuid(ruid: uid_t, euid: uid_t, suid: uid_t) -> EResult<()> {
114+
setresuid_inner(ruid, euid, suid)
115+
}
116+
117+
#[wrap_syscall]
118+
pub fn setreuid(ruid: uid_t, euid: uid_t) -> EResult<()> {
119+
setresuid_inner(ruid, euid, uid_t::MAX)
120+
}
121+
122+
fn setresuid_inner(ruid: uid_t, euid: uid_t, suid: uid_t) -> EResult<()> {
123+
let proc = Scheduler::get_current().get_process();
124+
let mut ident = proc.identity.lock();
125+
if !ident.is_effective_superuser() {
126+
for uid in [ruid, euid, suid] {
127+
if uid != uid_t::MAX
128+
&& uid != ident.user_id
129+
&& uid != ident.effective_user_id
130+
&& uid != ident.set_user_id
131+
{
132+
return Err(Errno::EPERM);
133+
}
134+
}
135+
}
136+
if ruid != uid_t::MAX {
137+
ident.user_id = ruid;
138+
}
139+
if euid != uid_t::MAX {
140+
ident.effective_user_id = euid;
141+
}
142+
if suid != uid_t::MAX {
143+
ident.set_user_id = suid;
144+
}
145+
Ok(())
146+
}
147+
79148
#[wrap_syscall]
80149
pub fn getresgid(rgid: VirtAddr, egid: VirtAddr, sgid: VirtAddr) -> EResult<()> {
81150
let proc = Scheduler::get_current().get_process();
82151
let ident = proc.identity.lock();
83152

84-
let mut rgid_ptr = UserPtr::<uid_t>::new(rgid);
85-
let mut egid_ptr = UserPtr::<uid_t>::new(egid);
86-
let mut sgid_ptr = UserPtr::<uid_t>::new(sgid);
153+
let mut rgid_ptr = UserPtr::<gid_t>::new(rgid);
154+
let mut egid_ptr = UserPtr::<gid_t>::new(egid);
155+
let mut sgid_ptr = UserPtr::<gid_t>::new(sgid);
87156

88157
rgid_ptr.write(ident.group_id).ok_or(Errno::EFAULT)?;
89158
egid_ptr
@@ -94,6 +163,76 @@ pub fn getresgid(rgid: VirtAddr, egid: VirtAddr, sgid: VirtAddr) -> EResult<()>
94163
Ok(())
95164
}
96165

166+
#[wrap_syscall]
167+
pub fn setgid(gid: gid_t) -> EResult<()> {
168+
let proc = Scheduler::get_current().get_process();
169+
let mut ident = proc.identity.lock();
170+
if ident.is_effective_superuser() {
171+
ident.group_id = gid;
172+
ident.effective_group_id = gid;
173+
ident.set_group_id = gid;
174+
Ok(())
175+
} else if gid == ident.group_id || gid == ident.effective_group_id || gid == ident.set_group_id
176+
{
177+
ident.effective_group_id = gid;
178+
Ok(())
179+
} else {
180+
Err(Errno::EPERM)
181+
}
182+
}
183+
184+
#[wrap_syscall]
185+
pub fn setegid(egid: gid_t) -> EResult<()> {
186+
let proc = Scheduler::get_current().get_process();
187+
let mut ident = proc.identity.lock();
188+
if ident.is_effective_superuser()
189+
|| egid == ident.group_id
190+
|| egid == ident.effective_group_id
191+
|| egid == ident.set_group_id
192+
{
193+
ident.effective_group_id = egid;
194+
Ok(())
195+
} else {
196+
Err(Errno::EPERM)
197+
}
198+
}
199+
200+
#[wrap_syscall]
201+
pub fn setresgid(rgid: gid_t, egid: gid_t, sgid: gid_t) -> EResult<()> {
202+
setresgid_inner(rgid, egid, sgid)
203+
}
204+
205+
#[wrap_syscall]
206+
pub fn setregid(rgid: gid_t, egid: gid_t) -> EResult<()> {
207+
setresgid_inner(rgid, egid, gid_t::MAX)
208+
}
209+
210+
fn setresgid_inner(rgid: gid_t, egid: gid_t, sgid: gid_t) -> EResult<()> {
211+
let proc = Scheduler::get_current().get_process();
212+
let mut ident = proc.identity.lock();
213+
if !ident.is_effective_superuser() {
214+
for gid in [rgid, egid, sgid] {
215+
if gid != gid_t::MAX
216+
&& gid != ident.group_id
217+
&& gid != ident.effective_group_id
218+
&& gid != ident.set_group_id
219+
{
220+
return Err(Errno::EPERM);
221+
}
222+
}
223+
}
224+
if rgid != gid_t::MAX {
225+
ident.group_id = rgid;
226+
}
227+
if egid != gid_t::MAX {
228+
ident.effective_group_id = egid;
229+
}
230+
if sgid != gid_t::MAX {
231+
ident.set_group_id = sgid;
232+
}
233+
Ok(())
234+
}
235+
97236
#[wrap_syscall]
98237
pub fn getpgid(pid: pid_t) -> EResult<pid_t> {
99238
let proc = if pid == 0 {
@@ -344,6 +483,10 @@ pub fn waitpid(pid: pid_t, stat_loc: VirtAddr, options: i32) -> EResult<pid_t> {
344483
return Ok(0);
345484
}
346485

486+
if Scheduler::get_current().has_pending_signals() {
487+
return Err(Errno::EINTR);
488+
}
489+
347490
drop(children);
348491
guard.wait();
349492

@@ -358,6 +501,7 @@ pub fn waitpid(pid: pid_t, stat_loc: VirtAddr, options: i32) -> EResult<pid_t> {
358501
}
359502
let state = child.status.lock();
360503
matches!(*state, ProcessState::Exited(_))
504+
|| matches!(*state, ProcessState::Signaled(_))
361505
|| ((options & uapi::wait::WUNTRACED) != 0
362506
&& child.stop_unwaited.load(Ordering::Acquire))
363507
|| ((options & uapi::wait::WCONTINUED) != 0

0 commit comments

Comments
 (0)