mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-30 12:44:39 +00:00
rustjail: fix the issue of home_dir function
Since the crate dirs::home_dir function depends on the libc's api: getpwuid_r, but this api function wouldn't be static linked on glibc, thus we'd better to figure out an alternative way to get the home dir from /etc/passwd. For much more info about this glibc's issue, please see: https://sourceware.org/bugzilla/show_bug.cgi?id=19341. This commit read and parse the "/etc/passwd" directly and fetch the corresponding uid's home dir. Fixes: #675 Signed-off-by: fupan.lfp <fupan.lfp@antfin.com>
This commit is contained in:
parent
f6630ddd49
commit
81607e348e
@ -22,7 +22,6 @@ slog-scope = "4.1.2"
|
|||||||
scan_fmt = "0.2"
|
scan_fmt = "0.2"
|
||||||
regex = "1.1"
|
regex = "1.1"
|
||||||
path-absolutize = "1.2.0"
|
path-absolutize = "1.2.0"
|
||||||
dirs = "3.0.1"
|
|
||||||
anyhow = "1.0.32"
|
anyhow = "1.0.32"
|
||||||
cgroups = { package = "cgroups-rs", version = "0.2.1" }
|
cgroups = { package = "cgroups-rs", version = "0.2.1" }
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
|
@ -58,6 +58,8 @@ use async_trait::async_trait;
|
|||||||
use rlimit::{setrlimit, Resource, Rlim};
|
use rlimit::{setrlimit, Resource, Rlim};
|
||||||
use tokio::io::AsyncBufReadExt;
|
use tokio::io::AsyncBufReadExt;
|
||||||
|
|
||||||
|
use crate::utils;
|
||||||
|
|
||||||
const STATE_FILENAME: &str = "state.json";
|
const STATE_FILENAME: &str = "state.json";
|
||||||
const EXEC_FIFO_FILENAME: &str = "exec.fifo";
|
const EXEC_FIFO_FILENAME: &str = "exec.fifo";
|
||||||
const VER_MARKER: &str = "1.2.5";
|
const VER_MARKER: &str = "1.2.5";
|
||||||
@ -634,8 +636,9 @@ fn do_init_child(cwfd: RawFd) -> Result<()> {
|
|||||||
|
|
||||||
// set the "HOME" env getting from "/etc/passwd"
|
// set the "HOME" env getting from "/etc/passwd"
|
||||||
if env::var_os(HOME_ENV_KEY).is_none() {
|
if env::var_os(HOME_ENV_KEY).is_none() {
|
||||||
if let Some(home_dir) = dirs::home_dir() {
|
match utils::home_dir(guser.uid) {
|
||||||
env::set_var(HOME_ENV_KEY, home_dir);
|
Ok(home_dir) => env::set_var(HOME_ENV_KEY, home_dir),
|
||||||
|
Err(e) => log_child!(cfd_log, "failed to get home dir: {:?}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ pub mod process;
|
|||||||
pub mod specconv;
|
pub mod specconv;
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
pub mod sync_with_async;
|
pub mod sync_with_async;
|
||||||
|
pub mod utils;
|
||||||
pub mod validator;
|
pub mod validator;
|
||||||
|
|
||||||
// pub mod factory;
|
// pub mod factory;
|
||||||
//pub mod configs;
|
//pub mod configs;
|
||||||
// pub mod devices;
|
// pub mod devices;
|
||||||
|
119
src/agent/rustjail/src/utils.rs
Normal file
119
src/agent/rustjail/src/utils.rs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// 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<PasswdEntry> {
|
||||||
|
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<String> {
|
||||||
|
get_entry_by_uid(uid, PASSWD_FILE).map(|entry| entry.dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use std::io::{self, 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();
|
||||||
|
writeln!(tempf, "root:x:0:0:root:/root0:/bin/bash").unwrap();
|
||||||
|
writeln!(tempf, "root:x:1:0:root:/root1:/bin/bash").unwrap();
|
||||||
|
writeln!(tempf, "#root:x:1:0:root:/rootx:/bin/bash").unwrap();
|
||||||
|
writeln!(tempf, "root:x:2:0:root:/root2:/bin/bash").unwrap();
|
||||||
|
writeln!(tempf, "root:x:3:0:root:/root3").unwrap();
|
||||||
|
writeln!(tempf, "root:x:3:0:root:/root3:/bin/bash").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");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user