mirror of https://github.com/telemt/telemt.git
Privileges fix
Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>
This commit is contained in:
parent
4d87a790cc
commit
fa4e2000a8
|
|
@ -339,31 +339,35 @@ fn is_process_running(pid: i32) -> bool {
|
||||||
|
|
||||||
/// Drops privileges to the specified user and group.
|
/// Drops privileges to the specified user and group.
|
||||||
///
|
///
|
||||||
/// This should be called after binding privileged ports but before
|
/// This should be called after binding privileged ports but before entering
|
||||||
/// entering the main event loop.
|
/// the main event loop.
|
||||||
pub fn drop_privileges(user: Option<&str>, group: Option<&str>) -> Result<(), DaemonError> {
|
pub fn drop_privileges(
|
||||||
// Look up group first (need to do this while still root)
|
user: Option<&str>,
|
||||||
|
group: Option<&str>,
|
||||||
|
pid_file: Option<&PidFile>,
|
||||||
|
) -> Result<(), DaemonError> {
|
||||||
let target_gid = if let Some(group_name) = group {
|
let target_gid = if let Some(group_name) = group {
|
||||||
Some(lookup_group(group_name)?)
|
Some(lookup_group(group_name)?)
|
||||||
} else if let Some(user_name) = user {
|
} else if let Some(user_name) = user {
|
||||||
// If no group specified but user is, use user's primary group
|
|
||||||
Some(lookup_user_primary_gid(user_name)?)
|
Some(lookup_user_primary_gid(user_name)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Look up user
|
|
||||||
let target_uid = if let Some(user_name) = user {
|
let target_uid = if let Some(user_name) = user {
|
||||||
Some(lookup_user(user_name)?)
|
Some(lookup_user(user_name)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Drop privileges: set GID first, then UID
|
if (target_uid.is_some() || target_gid.is_some())
|
||||||
// (Setting UID first would prevent us from setting GID)
|
&& let Some(file) = pid_file.and_then(|pid| pid.file.as_ref())
|
||||||
|
{
|
||||||
|
unistd::fchown(file, target_uid, target_gid).map_err(DaemonError::PrivilegeDrop)?;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(gid) = target_gid {
|
if let Some(gid) = target_gid {
|
||||||
unistd::setgid(gid).map_err(DaemonError::PrivilegeDrop)?;
|
unistd::setgid(gid).map_err(DaemonError::PrivilegeDrop)?;
|
||||||
// Also set supplementary groups to just this one
|
|
||||||
unistd::setgroups(&[gid]).map_err(DaemonError::PrivilegeDrop)?;
|
unistd::setgroups(&[gid]).map_err(DaemonError::PrivilegeDrop)?;
|
||||||
info!(gid = gid.as_raw(), "Dropped group privileges");
|
info!(gid = gid.as_raw(), "Dropped group privileges");
|
||||||
}
|
}
|
||||||
|
|
@ -371,6 +375,36 @@ pub fn drop_privileges(user: Option<&str>, group: Option<&str>) -> Result<(), Da
|
||||||
if let Some(uid) = target_uid {
|
if let Some(uid) = target_uid {
|
||||||
unistd::setuid(uid).map_err(DaemonError::PrivilegeDrop)?;
|
unistd::setuid(uid).map_err(DaemonError::PrivilegeDrop)?;
|
||||||
info!(uid = uid.as_raw(), "Dropped user privileges");
|
info!(uid = uid.as_raw(), "Dropped user privileges");
|
||||||
|
|
||||||
|
if uid.as_raw() != 0 && let Some(pid) = pid_file {
|
||||||
|
let parent = pid.path.parent().unwrap_or(Path::new("."));
|
||||||
|
let probe_path = parent.join(format!(
|
||||||
|
".telemt_pid_probe_{}_{}",
|
||||||
|
std::process::id(),
|
||||||
|
getpid().as_raw()
|
||||||
|
));
|
||||||
|
OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.create_new(true)
|
||||||
|
.mode(0o600)
|
||||||
|
.open(&probe_path)
|
||||||
|
.map_err(|e| {
|
||||||
|
DaemonError::PidFile(format!(
|
||||||
|
"cannot create probe in PID directory {} as uid {} (pid cleanup will fail): {}",
|
||||||
|
parent.display(),
|
||||||
|
uid.as_raw(),
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
fs::remove_file(&probe_path).map_err(|e| {
|
||||||
|
DaemonError::PidFile(format!(
|
||||||
|
"cannot remove probe in PID directory {} as uid {} (pid cleanup will fail): {}",
|
||||||
|
parent.display(),
|
||||||
|
uid.as_raw(),
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -763,7 +763,11 @@ async fn run_inner(
|
||||||
|
|
||||||
// Drop privileges after binding sockets (which may require root for port < 1024)
|
// Drop privileges after binding sockets (which may require root for port < 1024)
|
||||||
if daemon_opts.user.is_some() || daemon_opts.group.is_some() {
|
if daemon_opts.user.is_some() || daemon_opts.group.is_some() {
|
||||||
if let Err(e) = drop_privileges(daemon_opts.user.as_deref(), daemon_opts.group.as_deref()) {
|
if let Err(e) = drop_privileges(
|
||||||
|
daemon_opts.user.as_deref(),
|
||||||
|
daemon_opts.group.as_deref(),
|
||||||
|
_pid_file.as_ref(),
|
||||||
|
) {
|
||||||
error!(error = %e, "Failed to drop privileges");
|
error!(error = %e, "Failed to drop privileges");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue