WIP: Support setuid/setgid

This commit is contained in:
4lDO2
2022-06-16 14:51:44 +02:00
parent 37cc4e5383
commit a7c817d81a
3 changed files with 42 additions and 8 deletions
+1
View File
@@ -124,6 +124,7 @@ pub fn static_init(sp: &'static Stack) {
tcb.masters_len = mem::size_of::<Master>();
tcb.copy_masters().expect_notls("failed to copy TLS master data");
tcb.activate();
}
//TODO: Warning on multiple TLS sections?
+8 -4
View File
@@ -11,6 +11,8 @@ use syscall::{
flag::{AT_ENTRY, AT_NULL, AT_PHDR, AT_PHENT, AT_PHNUM, MapFlags},
};
use crate::fs::File;
fn read_all(fd: usize, offset: u64, buf: &mut [u8]) -> Result<()> {
syscall::lseek(fd, offset as isize, syscall::SEEK_SET).unwrap();
@@ -63,7 +65,8 @@ const PAGE_SIZE: usize = 4096;
const FD_ANONYMOUS: usize = !0;
pub fn fexec_impl(fd: usize, path: &[u8], args: &[&[u8]], envs: &[&[u8]], args_envs_size_without_nul: usize) -> Result<usize> {
pub fn fexec_impl(file: File, path: &[u8], args: &[&[u8]], envs: &[&[u8]], args_envs_size_without_nul: usize) -> Result<usize> {
let fd = *file as usize;
let total_args_envs_size = args_envs_size_without_nul + args.len() + envs.len();
// Here, we do the minimum part of loading an application, which is what the kernel used to do.
@@ -261,10 +264,11 @@ pub fn fexec_impl(fd: usize, path: &[u8], args: &[&[u8]], envs: &[&[u8]], args_e
unsafe { crate::ld_so::tcb::Tcb::deactivate(); }
// TODO: Restore old name if exec failed?
if let Ok(fd) = syscall::open("thisproc:current/name", syscall::O_WRONLY) {
let _ = syscall::write(fd, path);
let _ = syscall::close(fd);
if let Ok(name_fd) = syscall::open("thisproc:current/name", syscall::O_WRONLY) {
let _ = syscall::write(name_fd, path);
let _ = syscall::close(name_fd);
}
drop(file);
syscall::exec(&memranges, instruction_ptr, sp)?;
unreachable!();
+33 -4
View File
@@ -218,7 +218,9 @@ impl Pal for Sys {
mut argv: *const *mut c_char,
mut envp: *const *mut c_char,
) -> c_int {
let mut file = match File::open(path, fcntl::O_RDONLY | fcntl::O_CLOEXEC) {
// NOTE: We must omit O_CLOEXEC and close manually, otherwise it will be closed before we
// have even read it!
let mut file = match File::open(path, fcntl::O_RDONLY) {
Ok(file) => file,
Err(_) => return -1,
};
@@ -309,7 +311,7 @@ impl Pal for Sys {
Ok(cstring) => cstring,
Err(_) => return -1,
};
file = match File::open(&cstring, fcntl::O_RDONLY | fcntl::O_CLOEXEC) {
file = match File::open(&cstring, fcntl::O_RDONLY) {
Ok(file) => file,
Err(_) => return -1,
};
@@ -351,6 +353,32 @@ impl Pal for Sys {
envp = envp.add(1);
}
// Close all O_CLOEXEC file descriptors. TODO: close_range?
{
let name = CStr::from_bytes_with_nul(b"thisproc:current/files\0").expect("string should be valid");
let files_fd = match File::open(name, fcntl::O_RDONLY) {
Ok(f) => f,
Err(_) => return -1,
};
for line in BufReader::new(files_fd).lines() {
let line = match line {
Ok(l) => l,
Err(_) => break,
};
let fd = match line.parse::<usize>() {
Ok(f) => f,
Err(_) => continue,
};
let flags = Self::fcntl(fd as c_int, fcntl::F_GETFD, 0);
if flags != -1 {
if flags & fcntl::O_CLOEXEC == fcntl::O_CLOEXEC {
let _ = Self::close(fd as c_int);
}
}
}
}
if !is_interpreted && wants_setugid {
let name = CStr::from_bytes_with_nul(b"escalate:\0").expect("string should be valid");
// We are now going to invoke `escalate:` rather than loading the program ourselves.
@@ -368,7 +396,7 @@ impl Pal for Sys {
// descriptor and not a path will allow escalated to run in a limited namespace.
//
// TODO: Plus, at this point fexecve is not implemented (but specified in
// POSIX.1-2008), and to avoid bad syscalls such as fpath passing a file descriptor
// POSIX.1-2008), and to avoid bad syscalls such as fpath, passing a file descriptor
// would be better.
escalate_fd.write_all(path.to_bytes());
@@ -382,13 +410,14 @@ impl Pal for Sys {
}
// escalated will take care of the rest when responding to SYS_CLOSE.
// FIXME: close escalate_fd
if escalate_fd.write(&[]).is_err() {
return -1;
}
unreachable!()
} else {
e(self::exec::fexec_impl(*file as usize, path.to_bytes(), &args, &envs, args_envs_size_without_nul)) as c_int
e(self::exec::fexec_impl(file, path.to_bytes(), &args, &envs, args_envs_size_without_nul)) as c_int
}
}