Browse Source

WIP: Support setuid/setgid

4lDO2 2 years ago
parent
commit
a7c817d81a
3 changed files with 42 additions and 8 deletions
  1. 1 0
      src/ld_so/mod.rs
  2. 8 4
      src/platform/redox/exec.rs
  3. 33 4
      src/platform/redox/mod.rs

+ 1 - 0
src/ld_so/mod.rs

@@ -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
src/platform/redox/exec.rs

@@ -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
src/platform/redox/mod.rs

@@ -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
         }
     }