genpolicy: don't parse /etc/passwd in a loop

Instead of looping over the users per group and parsing passwd for each
user, we can do the reverse lookup uid->user up front and then compare
the names directly. This has the nice side-effect of silencing warnings
about non-existent users mentioned in /etc/group, which is not relevant
for policy decisions.

Signed-off-by: Markus Rudy <mr@edgeless.systems>
This commit is contained in:
Markus Rudy 2025-06-04 17:13:44 +02:00
parent a1baaf6fe2
commit 1c240de58d

View File

@ -258,29 +258,34 @@ impl Container {
} }
} }
fn get_user_from_passwd_uid(&self, uid: u32) -> Result<String> {
for record in parse_passwd_file(&self.passwd)? {
if record.uid == uid {
return Ok(record.user);
}
}
Err(anyhow!("No user found with uid {uid}"))
}
pub fn get_additional_groups_from_uid(&self, uid: u32) -> Result<Vec<u32>> { pub fn get_additional_groups_from_uid(&self, uid: u32) -> Result<Vec<u32>> {
if self.group.is_empty() || self.passwd.is_empty() { if self.group.is_empty() || self.passwd.is_empty() {
return Err(anyhow!( return Err(anyhow!(
"No /etc/group, /etc/passwd file is available, unable to parse additional group membership from uid" "No /etc/group, /etc/passwd file is available, unable to parse additional group membership from uid"
)); ));
} }
let user = self.get_user_from_passwd_uid(uid)?;
match parse_group_file(&self.group) { match parse_group_file(&self.group) {
Ok(records) => { Ok(records) => {
let mut groups = Vec::new(); let mut groups = Vec::new();
for record in records.iter() { for record in records.iter() {
record.user_list.iter().for_each(|u| { record.user_list.iter().for_each(|u| {
match self.get_uid_gid_from_passwd_user(u.to_string()) { if u == &user && &record.name != u {
Ok((record_uid, _)) => { // The second condition works around containerd bug
if record_uid == uid && &record.name != u { // https://github.com/containerd/containerd/issues/11937.
// The second condition works around containerd bug groups.push(record.gid);
// https://github.com/containerd/containerd/issues/11937. }
groups.push(record.gid);
}
},
Err(inner_e) => warn!(
"/etc/group indicates a user {u} that is not in /etc/passwd - error {inner_e}"
),
};
}); });
} }
Ok(groups) Ok(groups)