- Set supplementary groups when dropping privileges - Show more descriptive error messages on missing files errors - Create /usr/libexec/keylime directory Related: rhbz#2084552 Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
163 lines
5.3 KiB
Diff
163 lines
5.3 KiB
Diff
From 4ec807b1bbcfaa67f85d0c2659b1f439c2f540b4 Mon Sep 17 00:00:00 2001
|
|
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
|
Date: Fri, 24 Jun 2022 16:25:54 +0200
|
|
Subject: [PATCH] permissions: Set supplementary groups when dropping
|
|
privileges
|
|
|
|
This allows the agent to run with the user primary group and have the
|
|
access given by the supplementary groups.
|
|
|
|
Fixes: #414
|
|
|
|
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
|
---
|
|
src/permissions.rs | 70 ++++++++++++++++++++++++++++++++++------------
|
|
1 file changed, 52 insertions(+), 18 deletions(-)
|
|
|
|
diff --git a/src/permissions.rs b/src/permissions.rs
|
|
index 279a6dd..86e3fae 100644
|
|
--- a/src/permissions.rs
|
|
+++ b/src/permissions.rs
|
|
@@ -2,7 +2,7 @@
|
|
// Copyright 2021 Keylime Authors
|
|
|
|
use crate::error::{Error, Result};
|
|
-use libc::{gid_t, uid_t};
|
|
+use libc::{c_char, c_int, gid_t, uid_t};
|
|
use log::*;
|
|
use std::os::unix::ffi::OsStrExt;
|
|
use std::{
|
|
@@ -13,10 +13,9 @@ use std::{
|
|
ptr,
|
|
};
|
|
|
|
-#[derive(Debug)]
|
|
pub(crate) struct UserIds {
|
|
- uid: uid_t,
|
|
- gid: gid_t,
|
|
+ passwd: libc::passwd,
|
|
+ group: libc::group,
|
|
}
|
|
|
|
pub(crate) fn get_gid() -> gid_t {
|
|
@@ -47,14 +46,14 @@ impl TryFrom<&str> for UserIds {
|
|
let group = parts[1];
|
|
|
|
// Get gid from group name
|
|
- let gid = if let Ok(g_cstr) = CString::new(group.as_bytes()) {
|
|
+ let grnam = if let Ok(g_cstr) = CString::new(group.as_bytes()) {
|
|
let p = unsafe { libc::getgrnam(g_cstr.as_ptr()) };
|
|
if p.is_null() {
|
|
let e = io::Error::last_os_error();
|
|
error!("Could not get group {}: {}", group, e);
|
|
return Err(Error::Conversion(e.to_string()));
|
|
}
|
|
- unsafe { (*p).gr_gid }
|
|
+ unsafe { (*p) }
|
|
} else {
|
|
return Err(Error::Conversion(format!(
|
|
"Failed to convert {} to CString",
|
|
@@ -63,14 +62,14 @@ impl TryFrom<&str> for UserIds {
|
|
};
|
|
|
|
// Get uid from user name
|
|
- let uid = if let Ok(u_cstr) = CString::new(user.as_bytes()) {
|
|
+ let passwd = if let Ok(u_cstr) = CString::new(user.as_bytes()) {
|
|
let p = unsafe { libc::getpwnam(u_cstr.as_ptr()) };
|
|
if p.is_null() {
|
|
let e = io::Error::last_os_error();
|
|
error!("Could not get user {}: {}", user, e);
|
|
return Err(Error::Conversion(e.to_string()));
|
|
}
|
|
- unsafe { (*p).pw_uid }
|
|
+ unsafe { (*p) }
|
|
} else {
|
|
return Err(Error::Conversion(format!(
|
|
"Failed to convert {} to CString",
|
|
@@ -78,7 +77,10 @@ impl TryFrom<&str> for UserIds {
|
|
)));
|
|
};
|
|
|
|
- Ok(UserIds { uid, gid })
|
|
+ Ok(UserIds {
|
|
+ passwd,
|
|
+ group: grnam,
|
|
+ })
|
|
}
|
|
}
|
|
|
|
@@ -88,22 +90,51 @@ impl TryFrom<&str> for UserIds {
|
|
pub(crate) fn run_as(user_group: &str) -> Result<()> {
|
|
let ids: UserIds = user_group.try_into()?;
|
|
|
|
- // Drop supplementary groups
|
|
- if unsafe { libc::setgroups(0, ptr::null()) } != 0 {
|
|
+ // Set gid
|
|
+ if unsafe { libc::setgid(ids.group.gr_gid) } != 0 {
|
|
let e = io::Error::last_os_error();
|
|
- error!("Could not drop supplementary groups: {}", e);
|
|
+ error!("Could not set group id: {}", e);
|
|
return Err(Error::Permission);
|
|
}
|
|
|
|
- // Set gid
|
|
- if unsafe { libc::setgid(ids.gid) } != 0 {
|
|
+ // Get list of supplementary groups
|
|
+ let mut sup_groups: [gid_t; 32] = [0u32; 32];
|
|
+ let mut ngroups: c_int = 32;
|
|
+ if unsafe {
|
|
+ libc::getgrouplist(
|
|
+ ids.passwd.pw_name,
|
|
+ ids.group.gr_gid,
|
|
+ sup_groups.as_mut_ptr(),
|
|
+ &mut ngroups,
|
|
+ )
|
|
+ } < 0
|
|
+ {
|
|
+ // Allocate a Vec and try again
|
|
+ let mut sup_groups: Vec<gid_t> = Vec::with_capacity(ngroups as usize);
|
|
+ if unsafe {
|
|
+ libc::getgrouplist(
|
|
+ ids.passwd.pw_name,
|
|
+ ids.group.gr_gid,
|
|
+ sup_groups.as_mut_ptr(),
|
|
+ &mut ngroups,
|
|
+ )
|
|
+ } < 0
|
|
+ {
|
|
+ error!("Could not get list of supplementary groups");
|
|
+ return Err(Error::Permission);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Set supplementary groups
|
|
+ if unsafe { libc::setgroups(ngroups as usize, sup_groups.as_ptr()) } != 0
|
|
+ {
|
|
let e = io::Error::last_os_error();
|
|
- error!("Could not set group id: {}", e);
|
|
+ error!("Could not set supplementary groups: {}", e);
|
|
return Err(Error::Permission);
|
|
}
|
|
|
|
// Set uid
|
|
- if unsafe { libc::setuid(ids.uid) } != 0 {
|
|
+ if unsafe { libc::setuid(ids.passwd.pw_uid) } != 0 {
|
|
let e = io::Error::last_os_error();
|
|
error!("Could not set user id: {}", e);
|
|
return Err(Error::Permission);
|
|
@@ -126,9 +157,12 @@ pub(crate) fn chown(user_group: &str, path: &Path) -> Result<()> {
|
|
return Err(Error::Permission);
|
|
}
|
|
|
|
- // change directory owner to root
|
|
+ // change directory owner
|
|
let c_path = CString::new(path.as_os_str().as_bytes())?;
|
|
- if unsafe { libc::chown(c_path.as_ptr(), ids.uid, ids.gid) } != 0 {
|
|
+ if unsafe {
|
|
+ libc::chown(c_path.as_ptr(), ids.passwd.pw_uid, ids.group.gr_gid)
|
|
+ } != 0
|
|
+ {
|
|
error!("Failed to change file {} owner.", path.display());
|
|
return Err(Error::Permission);
|
|
}
|