core: check suid/sgid dynamically instead of checking file
All checks were successful
All checks were successful
This commit is contained in:
@@ -90,7 +90,7 @@ nixpkgs.lib.nixosSystem {
|
|||||||
defaultEditor = true;
|
defaultEditor = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [ jq ];
|
environment.systemPackages = with pkgs; [ jq pkgs.muscl ];
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use tracing_subscriber::prelude::*;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::common::{
|
core::common::{
|
||||||
DEFAULT_CONFIG_PATH, DEFAULT_SOCKET_PATH, UnixUser, executable_is_suid_or_sgid,
|
DEFAULT_CONFIG_PATH, DEFAULT_SOCKET_PATH, UnixUser, executing_in_suid_sgid_mode,
|
||||||
},
|
},
|
||||||
server::{
|
server::{
|
||||||
config::{MysqlConfig, ServerConfig},
|
config::{MysqlConfig, ServerConfig},
|
||||||
@@ -81,7 +81,7 @@ pub fn bootstrap_server_connection_and_drop_privileges(
|
|||||||
) -> anyhow::Result<StdUnixStream> {
|
) -> anyhow::Result<StdUnixStream> {
|
||||||
if will_connect_to_external_server(server_socket_path.as_ref(), config.as_ref())? {
|
if will_connect_to_external_server(server_socket_path.as_ref(), config.as_ref())? {
|
||||||
assert!(
|
assert!(
|
||||||
!executable_is_suid_or_sgid()?,
|
!executing_in_suid_sgid_mode()?,
|
||||||
"The executable should not be SUID or SGID when connecting to an external server"
|
"The executable should not be SUID or SGID when connecting to an external server"
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ fn bootstrap_internal_server_and_drop_privs(
|
|||||||
config_path: Option<PathBuf>,
|
config_path: Option<PathBuf>,
|
||||||
) -> anyhow::Result<StdUnixStream> {
|
) -> anyhow::Result<StdUnixStream> {
|
||||||
if let Some(config_path) = config_path {
|
if let Some(config_path) = config_path {
|
||||||
if !executable_is_suid_or_sgid()? {
|
if !executing_in_suid_sgid_mode()? {
|
||||||
anyhow::bail!("Executable is not SUID/SGID - refusing to start internal sever");
|
anyhow::bail!("Executable is not SUID/SGID - refusing to start internal sever");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +195,7 @@ fn bootstrap_internal_server_and_drop_privs(
|
|||||||
|
|
||||||
let config_path = PathBuf::from(DEFAULT_CONFIG_PATH);
|
let config_path = PathBuf::from(DEFAULT_CONFIG_PATH);
|
||||||
if fs::metadata(&config_path).is_ok() {
|
if fs::metadata(&config_path).is_ok() {
|
||||||
if !executable_is_suid_or_sgid()? {
|
if !executing_in_suid_sgid_mode()? {
|
||||||
anyhow::bail!("Executable is not SUID/SGID - refusing to start internal sever");
|
anyhow::bail!("Executable is not SUID/SGID - refusing to start internal sever");
|
||||||
}
|
}
|
||||||
tracing::debug!("Starting server with default config at {:?}", config_path);
|
tracing::debug!("Starting server with default config at {:?}", config_path);
|
||||||
|
|||||||
@@ -67,28 +67,20 @@ fn get_unix_groups(user: &LibcUser) -> anyhow::Result<Vec<LibcGroup>> {
|
|||||||
Ok(groups)
|
Ok(groups)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the current executable is SUID or SGID.
|
/// Check if the current executable is running in SUID/SGID mode
|
||||||
///
|
|
||||||
/// If the check fails, an error is returned.
|
|
||||||
#[cfg(feature = "suid-sgid-mode")]
|
#[cfg(feature = "suid-sgid-mode")]
|
||||||
pub fn executable_is_suid_or_sgid() -> anyhow::Result<bool> {
|
pub fn executing_in_suid_sgid_mode() -> anyhow::Result<bool> {
|
||||||
use std::{fs, os::unix::fs::PermissionsExt};
|
let euid = nix::unistd::geteuid();
|
||||||
let result = std::env::current_exe()
|
let uid = nix::unistd::getuid();
|
||||||
.context("Failed to get current executable path")
|
let egid = nix::unistd::getegid();
|
||||||
.and_then(|executable| {
|
let gid = nix::unistd::getgid();
|
||||||
fs::metadata(executable).context("Failed to get executable metadata")
|
|
||||||
})
|
Ok(euid != uid || egid != gid)
|
||||||
.context("Failed to check SUID/SGID bits on executable")
|
|
||||||
.map(|metadata| {
|
|
||||||
let mode = metadata.permissions().mode();
|
|
||||||
mode & 0o4000 != 0 || mode & 0o2000 != 0
|
|
||||||
})?;
|
|
||||||
Ok(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "suid-sgid-mode"))]
|
#[cfg(not(feature = "suid-sgid-mode"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn executable_is_suid_or_sgid() -> anyhow::Result<bool> {
|
pub fn executing_in_suid_sgid_mode() -> anyhow::Result<bool> {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use futures_util::StreamExt;
|
|||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
core::{
|
||||||
bootstrap::bootstrap_server_connection_and_drop_privileges,
|
bootstrap::bootstrap_server_connection_and_drop_privileges,
|
||||||
common::{ASCII_BANNER, KIND_REGARDS, executable_is_suid_or_sgid},
|
common::{ASCII_BANNER, KIND_REGARDS, executing_in_suid_sgid_mode},
|
||||||
protocol::{Response, create_client_to_server_message_stream},
|
protocol::{Response, create_client_to_server_message_stream},
|
||||||
},
|
},
|
||||||
server::{command::ServerArgs, landlock::landlock_restrict_server},
|
server::{command::ServerArgs, landlock::landlock_restrict_server},
|
||||||
@@ -151,7 +151,7 @@ fn main() -> anyhow::Result<()> {
|
|||||||
fn handle_dynamic_completion() -> anyhow::Result<Option<()>> {
|
fn handle_dynamic_completion() -> anyhow::Result<Option<()>> {
|
||||||
if std::env::var_os("COMPLETE").is_some() {
|
if std::env::var_os("COMPLETE").is_some() {
|
||||||
#[cfg(feature = "suid-sgid-mode")]
|
#[cfg(feature = "suid-sgid-mode")]
|
||||||
if executable_is_suid_or_sgid()? {
|
if executing_in_suid_sgid_mode()? {
|
||||||
use crate::core::bootstrap::drop_privs;
|
use crate::core::bootstrap::drop_privs;
|
||||||
drop_privs()?
|
drop_privs()?
|
||||||
}
|
}
|
||||||
@@ -202,7 +202,7 @@ fn handle_server_command(args: &Args) -> anyhow::Result<Option<()>> {
|
|||||||
match args.command {
|
match args.command {
|
||||||
Command::Server(ref command) => {
|
Command::Server(ref command) => {
|
||||||
assert!(
|
assert!(
|
||||||
!executable_is_suid_or_sgid()?,
|
!executing_in_suid_sgid_mode()?,
|
||||||
"The executable should not be SUID or SGID when running the server manually"
|
"The executable should not be SUID or SGID when running the server manually"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user