diff --git a/src/agent/rustjail/src/container.rs b/src/agent/rustjail/src/container.rs index a1207104fc..5f1aa56066 100644 --- a/src/agent/rustjail/src/container.rs +++ b/src/agent/rustjail/src/container.rs @@ -42,7 +42,7 @@ use nix::pty; use nix::sched::{self, CloneFlags}; use nix::sys::signal::{self, Signal}; use nix::sys::stat::{self, Mode}; -use nix::unistd::{self, fork, ForkResult, Gid, Pid, Uid}; +use nix::unistd::{self, fork, ForkResult, Gid, Pid, Uid, User}; use std::os::unix::fs::MetadataExt; use std::os::unix::io::AsRawFd; @@ -64,8 +64,6 @@ use rlimit::{setrlimit, Resource, Rlim}; use tokio::io::AsyncBufReadExt; use tokio::sync::Mutex; -use crate::utils; - pub const EXEC_FIFO_FILENAME: &str = "exec.fifo"; const INIT: &str = "INIT"; @@ -662,12 +660,17 @@ fn do_init_child(cwfd: RawFd) -> Result<()> { } } - // set the "HOME" env getting from "/etc/passwd", if - // there's no uid entry in /etc/passwd, set "/" as the - // home env. if env::var_os(HOME_ENV_KEY).is_none() { - let home_dir = utils::home_dir(guser.uid).unwrap_or_else(|_| String::from("/")); - env::set_var(HOME_ENV_KEY, home_dir); + // try to set "HOME" env by uid + if let Ok(Some(user)) = User::from_uid(Uid::from_raw(guser.uid)) { + if let Ok(user_home_dir) = user.dir.into_os_string().into_string() { + env::set_var(HOME_ENV_KEY, user_home_dir); + } + } + // set default home dir as "/" if "HOME" env is still empty + if env::var_os(HOME_ENV_KEY).is_none() { + env::set_var(HOME_ENV_KEY, String::from("/")); + } } let exec_file = Path::new(&args[0]); diff --git a/src/agent/rustjail/src/lib.rs b/src/agent/rustjail/src/lib.rs index dc7ff6cdc6..dafac6381e 100644 --- a/src/agent/rustjail/src/lib.rs +++ b/src/agent/rustjail/src/lib.rs @@ -41,7 +41,6 @@ pub mod seccomp; pub mod specconv; pub mod sync; pub mod sync_with_async; -pub mod utils; pub mod validator; use std::collections::HashMap; diff --git a/src/agent/rustjail/src/utils.rs b/src/agent/rustjail/src/utils.rs deleted file mode 100644 index cf69c77a2a..0000000000 --- a/src/agent/rustjail/src/utils.rs +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2021 Ant Group -// -// SPDX-License-Identifier: Apache-2.0 -// -use anyhow::{anyhow, Context, Result}; -use libc::gid_t; -use libc::uid_t; -use std::fs::File; -use std::io::{BufRead, BufReader}; - -const PASSWD_FILE: &str = "/etc/passwd"; - -// An entry from /etc/passwd -#[derive(Debug, PartialEq, PartialOrd)] -pub struct PasswdEntry { - // username - pub name: String, - // user password - pub passwd: String, - // user id - pub uid: uid_t, - // group id - pub gid: gid_t, - // user Information - pub gecos: String, - // home directory - pub dir: String, - // User's Shell - pub shell: String, -} - -// get an entry for a given `uid` from `/etc/passwd` -fn get_entry_by_uid(uid: uid_t, path: &str) -> Result { - let file = File::open(path).with_context(|| format!("open file {}", path))?; - let mut reader = BufReader::new(file); - - let mut line = String::new(); - loop { - line.clear(); - match reader.read_line(&mut line) { - Ok(0) => return Err(anyhow!(format!("file {} is empty", path))), - Ok(_) => (), - Err(e) => { - return Err(anyhow!(format!( - "failed to read file {} with {:?}", - path, e - ))) - } - } - - if line.starts_with('#') { - continue; - } - - let parts: Vec<&str> = line.split(':').map(|part| part.trim()).collect(); - if parts.len() != 7 { - continue; - } - - match parts[2].parse() { - Err(_e) => continue, - Ok(new_uid) => { - if uid != new_uid { - continue; - } - - let entry = PasswdEntry { - name: parts[0].to_string(), - passwd: parts[1].to_string(), - uid: new_uid, - gid: parts[3].parse().unwrap_or(0), - gecos: parts[4].to_string(), - dir: parts[5].to_string(), - shell: parts[6].to_string(), - }; - - return Ok(entry); - } - } - } -} - -pub fn home_dir(uid: uid_t) -> Result { - get_entry_by_uid(uid, PASSWD_FILE).map(|entry| entry.dir) -} - -#[cfg(test)] -mod tests { - use super::*; - use std::io::Write; - use tempfile::Builder; - - #[test] - fn test_get_entry_by_uid() { - let tmpdir = Builder::new().tempdir().unwrap(); - let tmpdir_path = tmpdir.path().to_str().unwrap(); - let temp_passwd = format!("{}/passwd", tmpdir_path); - - let mut tempf = File::create(temp_passwd.as_str()).unwrap(); - let passwd_entries = "root:x:0:0:root:/root0:/bin/bash -root:x:1:0:root:/root1:/bin/bash -#root:x:1:0:root:/rootx:/bin/bash -root:x:2:0:root:/root2:/bin/bash -root:x:3:0:root:/root3 -root:x:3:0:root:/root3:/bin/bash"; - writeln!(tempf, "{}", passwd_entries).unwrap(); - - let entry = get_entry_by_uid(0, temp_passwd.as_str()).unwrap(); - assert_eq!(entry.dir.as_str(), "/root0"); - - let entry = get_entry_by_uid(1, temp_passwd.as_str()).unwrap(); - assert_eq!(entry.dir.as_str(), "/root1"); - - let entry = get_entry_by_uid(2, temp_passwd.as_str()).unwrap(); - assert_eq!(entry.dir.as_str(), "/root2"); - - let entry = get_entry_by_uid(3, temp_passwd.as_str()).unwrap(); - assert_eq!(entry.dir.as_str(), "/root3"); - } -}