Check that executable is not SUID/SGID for unrelated subcommands
This commit is contained in:
@@ -20,6 +20,23 @@ fn get_unix_groups(_user: &LibcUser) -> anyhow::Result<Vec<LibcGroup>> {
|
|||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the current executable is SUID or SGID.
|
||||||
|
///
|
||||||
|
/// If the check fails, an error is returned.
|
||||||
|
pub fn executable_is_suid_or_sgid() -> anyhow::Result<bool> {
|
||||||
|
let result = std::env::current_exe()
|
||||||
|
.context("Failed to get current executable path")
|
||||||
|
.and_then(|executable| {
|
||||||
|
fs::metadata(executable).context("Failed to get executable metadata")
|
||||||
|
})
|
||||||
|
.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(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
fn get_unix_groups(user: &LibcUser) -> anyhow::Result<Vec<LibcGroup>> {
|
fn get_unix_groups(user: &LibcUser) -> anyhow::Result<Vec<LibcGroup>> {
|
||||||
let user_cstr =
|
let user_cstr =
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ use futures::StreamExt;
|
|||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
core::{
|
||||||
bootstrap::bootstrap_server_connection_and_drop_privileges,
|
bootstrap::bootstrap_server_connection_and_drop_privileges,
|
||||||
|
common::executable_is_suid_or_sgid,
|
||||||
protocol::{Response, create_client_to_server_message_stream},
|
protocol::{Response, create_client_to_server_message_stream},
|
||||||
},
|
},
|
||||||
server::command::ServerArgs,
|
server::command::ServerArgs,
|
||||||
@@ -152,6 +153,10 @@ fn handle_mysql_admutils_command() -> anyhow::Result<Option<()>> {
|
|||||||
fn handle_server_command(args: &Args) -> anyhow::Result<Option<()>> {
|
fn handle_server_command(args: &Args) -> anyhow::Result<Option<()>> {
|
||||||
match args.command {
|
match args.command {
|
||||||
Command::Server(ref command) => {
|
Command::Server(ref command) => {
|
||||||
|
assert!(
|
||||||
|
!executable_is_suid_or_sgid()?,
|
||||||
|
"The executable should not be SUID or SGID when running the server manually"
|
||||||
|
);
|
||||||
tokio_start_server(
|
tokio_start_server(
|
||||||
args.server_socket_path.to_owned(),
|
args.server_socket_path.to_owned(),
|
||||||
args.config.to_owned(),
|
args.config.to_owned(),
|
||||||
@@ -167,6 +172,10 @@ fn handle_server_command(args: &Args) -> anyhow::Result<Option<()>> {
|
|||||||
fn handle_generate_completions_command(args: &Args) -> anyhow::Result<Option<()>> {
|
fn handle_generate_completions_command(args: &Args) -> anyhow::Result<Option<()>> {
|
||||||
match args.command {
|
match args.command {
|
||||||
Command::GenerateCompletions(ref completion_args) => {
|
Command::GenerateCompletions(ref completion_args) => {
|
||||||
|
assert!(
|
||||||
|
!executable_is_suid_or_sgid()?,
|
||||||
|
"The executable should not be SUID or SGID when generating completions"
|
||||||
|
);
|
||||||
let mut cmd = match completion_args.command {
|
let mut cmd = match completion_args.command {
|
||||||
ToplevelCommands::Mysqladm => Args::command(),
|
ToplevelCommands::Mysqladm => Args::command(),
|
||||||
#[cfg(feature = "mysql-admutils-compatibility")]
|
#[cfg(feature = "mysql-admutils-compatibility")]
|
||||||
|
|||||||
Reference in New Issue
Block a user