Skip to content
Open
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
12 changes: 6 additions & 6 deletions etc/syscalls_linux_aarch64.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,13 @@
| 0x8c (140) | setpriority | (int which, int who, int niceval) | __arm64_sys_setpriority | false |
| 0x8d (141) | getpriority | (int which, int who) | __arm64_sys_getpriority | false |
| 0x8e (142) | reboot | (int magic1, int magic2, unsigned int cmd, void *arg) | __arm64_sys_reboot | partially |
| 0x8f (143) | setregid | (gid_t rgid, gid_t egid) | __arm64_sys_setregid | false |
| 0x90 (144) | setgid | (gid_t gid) | __arm64_sys_setgid | false |
| 0x91 (145) | setreuid | (uid_t ruid, uid_t euid) | __arm64_sys_setreuid | false |
| 0x92 (146) | setuid | (uid_t uid) | __arm64_sys_setuid | false |
| 0x93 (147) | setresuid | (uid_t ruid, uid_t euid, uid_t suid) | __arm64_sys_setresuid | false |
| 0x8f (143) | setregid | (gid_t rgid, gid_t egid) | __arm64_sys_setregid | true |
| 0x90 (144) | setgid | (gid_t gid) | __arm64_sys_setgid | true |
| 0x91 (145) | setreuid | (uid_t ruid, uid_t euid) | __arm64_sys_setreuid | true |
| 0x92 (146) | setuid | (uid_t uid) | __arm64_sys_setuid | true |
| 0x93 (147) | setresuid | (uid_t ruid, uid_t euid, uid_t suid) | __arm64_sys_setresuid | true |
| 0x94 (148) | getresuid | (uid_t *ruidp, uid_t *euidp, uid_t *suidp) | __arm64_sys_getresuid | true |
| 0x95 (149) | setresgid | (gid_t rgid, gid_t egid, gid_t sgid) | __arm64_sys_setresgid | false |
| 0x95 (149) | setresgid | (gid_t rgid, gid_t egid, gid_t sgid) | __arm64_sys_setresgid | true |
| 0x96 (150) | getresgid | (gid_t *rgidp, gid_t *egidp, gid_t *sgidp) | __arm64_sys_getresgid | true |
| 0x97 (151) | setfsuid | (uid_t uid) | __arm64_sys_setfsuid | false |
| 0x98 (152) | setfsgid | (gid_t gid) | __arm64_sys_setfsgid | false |
Expand Down
9 changes: 8 additions & 1 deletion src/arch/arm64/exceptions/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ use crate::{
clone::sys_clone,
creds::{
sys_getegid, sys_geteuid, sys_getgid, sys_getresgid, sys_getresuid, sys_getsid,
sys_gettid, sys_getuid, sys_setfsgid, sys_setfsuid, sys_setsid,
sys_gettid, sys_getuid, sys_setfsgid, sys_setfsuid, sys_setgid, sys_setregid,
sys_setresgid, sys_setresuid, sys_setreuid, sys_setsid, sys_setuid,
},
exec::sys_execve,
exit::{sys_exit, sys_exit_group},
Expand Down Expand Up @@ -537,6 +538,11 @@ pub async fn handle_syscall(mut ctx: ProcessCtx) {
return;
}
0x8e => sys_reboot(&ctx, arg1 as _, arg2 as _, arg3 as _, arg4 as _).await,
0x8f => sys_setregid(&ctx, arg1 as _, arg2 as _),
0x90 => sys_setgid(&ctx, arg1 as _),
0x91 => sys_setreuid(&ctx, arg1 as _, arg2 as _),
0x92 => sys_setuid(&ctx, arg1 as _),
0x93 => sys_setresuid(&ctx, arg1 as _, arg2 as _, arg3 as _),
0x94 => {
sys_getresuid(
&ctx,
Expand All @@ -546,6 +552,7 @@ pub async fn handle_syscall(mut ctx: ProcessCtx) {
)
.await
}
0x95 => sys_setresgid(&ctx, arg1 as _, arg2 as _, arg3 as _),
0x96 => {
sys_getresgid(
&ctx,
Expand Down
228 changes: 226 additions & 2 deletions src/process/creds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use crate::{
sched::syscall_ctx::ProcessCtx,
};
use libkernel::{
error::Result,
error::{KernelError, Result},
memory::address::TUA,
proc::{
caps::Capabilities,
caps::{Capabilities, CapabilitiesFlags},
ids::{Gid, Uid},
},
};
Expand Down Expand Up @@ -94,6 +94,230 @@ pub fn sys_getegid(ctx: &ProcessCtx) -> core::result::Result<usize, Infallible>
Ok(gid as _)
}

pub fn sys_setuid(ctx: &ProcessCtx, uid: usize) -> Result<usize> {
let mut creds = ctx.shared().creds.lock_save_irq();
let new_uid = Uid::new(uid as u32);

if creds.caps.is_capable(CapabilitiesFlags::CAP_SETUID) {
creds.uid = new_uid;
creds.euid = new_uid;
creds.suid = new_uid;
} else {
if new_uid == creds.uid || new_uid == creds.suid {
creds.euid = new_uid;
} else {
return Err(KernelError::NotPermitted);
}
}

Ok(0)
}

pub fn sys_setgid(ctx: &ProcessCtx, gid: usize) -> Result<usize> {
let mut creds = ctx.shared().creds.lock_save_irq();
let new_gid = Gid::new(gid as u32);

if creds.caps.is_capable(CapabilitiesFlags::CAP_SETGID) {
creds.gid = new_gid;
creds.egid = new_gid;
creds.sgid = new_gid;
} else {
if new_gid == creds.gid || new_gid == creds.sgid {
creds.egid = new_gid;
} else {
return Err(KernelError::NotPermitted);
}
}

Ok(0)
}

pub fn sys_setreuid(ctx: &ProcessCtx, ruid: usize, euid: usize) -> Result<usize> {
let mut creds = ctx.shared().creds.lock_save_irq();
let new_ruid = if ruid == usize::MAX {
creds.uid
} else {
Uid::new(ruid as u32)
};
let new_euid = if euid == usize::MAX {
creds.euid
} else {
Uid::new(euid as u32)
};

let capable = creds.caps.is_capable(CapabilitiesFlags::CAP_SETUID);

if !capable {
if ruid != usize::MAX
&& new_ruid != creds.uid
&& new_ruid != creds.euid
&& new_ruid != creds.suid
{
return Err(KernelError::NotPermitted);
}
if euid != usize::MAX
&& new_euid != creds.uid
&& new_euid != creds.euid
&& new_euid != creds.suid
{
return Err(KernelError::NotPermitted);
}
}

if ruid != usize::MAX || (euid != usize::MAX && new_euid != creds.uid) {
creds.suid = new_euid;
}

creds.uid = new_ruid;
creds.euid = new_euid;

Ok(0)
}

pub fn sys_setregid(ctx: &ProcessCtx, rgid: usize, egid: usize) -> Result<usize> {
let mut creds = ctx.shared().creds.lock_save_irq();
let new_rgid = if rgid == usize::MAX {
creds.gid
} else {
Gid::new(rgid as u32)
};
let new_egid = if egid == usize::MAX {
creds.egid
} else {
Gid::new(egid as u32)
};

let capable = creds.caps.is_capable(CapabilitiesFlags::CAP_SETGID);

if !capable {
if rgid != usize::MAX
&& new_rgid != creds.gid
&& new_rgid != creds.egid
&& new_rgid != creds.sgid
{
return Err(KernelError::NotPermitted);
}
if egid != usize::MAX
&& new_egid != creds.gid
&& new_egid != creds.egid
&& new_egid != creds.sgid
{
return Err(KernelError::NotPermitted);
}
}

if rgid != usize::MAX || (egid != usize::MAX && new_egid != creds.gid) {
creds.sgid = new_egid;
}

creds.gid = new_rgid;
creds.egid = new_egid;

Ok(0)
}

pub fn sys_setresuid(ctx: &ProcessCtx, ruid: usize, euid: usize, suid: usize) -> Result<usize> {
let mut creds = ctx.shared().creds.lock_save_irq();
let new_ruid = if ruid == usize::MAX {
creds.uid
} else {
Uid::new(ruid as u32)
};
let new_euid = if euid == usize::MAX {
creds.euid
} else {
Uid::new(euid as u32)
};
let new_suid = if suid == usize::MAX {
creds.suid
} else {
Uid::new(suid as u32)
};

let capable = creds.caps.is_capable(CapabilitiesFlags::CAP_SETUID);

if !capable {
if ruid != usize::MAX
&& new_ruid != creds.uid
&& new_ruid != creds.euid
&& new_ruid != creds.suid
{
return Err(KernelError::NotPermitted);
}
if euid != usize::MAX
&& new_euid != creds.uid
&& new_euid != creds.euid
&& new_euid != creds.suid
{
return Err(KernelError::NotPermitted);
}
if suid != usize::MAX
&& new_suid != creds.uid
&& new_suid != creds.euid
&& new_suid != creds.suid
{
return Err(KernelError::NotPermitted);
}
}

creds.uid = new_ruid;
creds.euid = new_euid;
creds.suid = new_suid;

Ok(0)
}

pub fn sys_setresgid(ctx: &ProcessCtx, rgid: usize, egid: usize, sgid: usize) -> Result<usize> {
let mut creds = ctx.shared().creds.lock_save_irq();
let new_rgid = if rgid == usize::MAX {
creds.gid
} else {
Gid::new(rgid as u32)
};
let new_egid = if egid == usize::MAX {
creds.egid
} else {
Gid::new(egid as u32)
};
let new_sgid = if sgid == usize::MAX {
creds.sgid
} else {
Gid::new(sgid as u32)
};

let capable = creds.caps.is_capable(CapabilitiesFlags::CAP_SETGID);

if !capable {
if rgid != usize::MAX
&& new_rgid != creds.gid
&& new_rgid != creds.egid
&& new_rgid != creds.sgid
{
return Err(KernelError::NotPermitted);
}
if egid != usize::MAX
&& new_egid != creds.gid
&& new_egid != creds.egid
&& new_egid != creds.sgid
{
return Err(KernelError::NotPermitted);
}
if sgid != usize::MAX
&& new_sgid != creds.gid
&& new_sgid != creds.egid
&& new_sgid != creds.sgid
{
return Err(KernelError::NotPermitted);
}
}

creds.gid = new_rgid;
creds.egid = new_egid;
creds.sgid = new_sgid;

Ok(0)
}

pub fn sys_setfsuid(ctx: &ProcessCtx, _new_id: usize) -> core::result::Result<usize, Infallible> {
// Return the uid. This syscall is deprecated.
sys_getuid(ctx)
Expand Down
Loading