From 8123dcec5160b0d29e541cec1c9a027a1dd42c48 Mon Sep 17 00:00:00 2001 From: licunlong Date: Wed, 14 Jun 2023 15:52:40 +0800 Subject: [PATCH] fix: check if the given unit name is valid before we prepare the unit --- core/bin/unit/base/load.rs | 8 ----- core/bin/unit/manager.rs | 8 ++++- core/bin/unit/uload.rs | 6 +++- core/lib/unit/base.rs | 70 ++++++++++++++++++++++++++++++++++++++ core/lib/unit/mod.rs | 3 +- 5 files changed, 84 insertions(+), 11 deletions(-) diff --git a/core/bin/unit/base/load.rs b/core/bin/unit/base/load.rs index 2281d06..700237d 100644 --- a/core/bin/unit/base/load.rs +++ b/core/bin/unit/base/load.rs @@ -10,14 +10,6 @@ // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. -#[allow(dead_code)] -enum UnitNameFlags { - Plain = 1, - Instance = 2, - Template = 4, - Any = 1 | 2 | 4, -} - #[allow(dead_code)] enum UnitFileState { Enabled, diff --git a/core/bin/unit/manager.rs b/core/bin/unit/manager.rs index 4b3f4fb..cb5d957 100644 --- a/core/bin/unit/manager.rs +++ b/core/bin/unit/manager.rs @@ -50,7 +50,10 @@ use sysmaster::error::*; use sysmaster::exec::ExecParameters; use sysmaster::exec::{ExecCommand, ExecContext}; use sysmaster::rel::{ReStation, ReStationKind, ReliLastFrame, Reliability}; -use sysmaster::unit::{UmIf, UnitActiveState, UnitDependencyMask, UnitStatus, UnitType}; +use sysmaster::unit::{ + unit_name_is_valid, UmIf, UnitActiveState, UnitDependencyMask, UnitNameFlags, UnitStatus, + UnitType, +}; use unit_submanager::UnitSubManagers; //#[derive(Debug)] @@ -525,6 +528,9 @@ impl UnitManager { /// pub fn units_get(&self, name: &str) -> Option> { + if !unit_name_is_valid(name, UnitNameFlags::PLAIN | UnitNameFlags::INSTANCE) { + return None; + } self.db.units_get(name).map(|uxr| uxr.unit()) } diff --git a/core/bin/unit/uload.rs b/core/bin/unit/uload.rs index d972fb4..d6fea43 100644 --- a/core/bin/unit/uload.rs +++ b/core/bin/unit/uload.rs @@ -22,7 +22,7 @@ use crate::utils::table::{TableOp, TableSubscribe}; use basic::path_lookup::LookupPaths; use std::cell::RefCell; use std::rc::{Rc, Weak}; -use sysmaster::unit::UnitType; +use sysmaster::unit::{unit_name_is_valid, UnitNameFlags, UnitType}; //#[derive(Debug)] pub(super) struct UnitLoad { @@ -100,6 +100,10 @@ impl UnitLoadData { } pub(self) fn prepare_unit(&self, name: &str) -> Option> { + if !unit_name_is_valid(name, UnitNameFlags::PLAIN | UnitNameFlags::INSTANCE) { + return None; + } + if let Some(u) = self.db.units_get(name) { if u.load_state() != UnitLoadState::NotFound { return Some(Rc::clone(&u)); diff --git a/core/lib/unit/base.rs b/core/lib/unit/base.rs index f066ed7..555bb69 100644 --- a/core/lib/unit/base.rs +++ b/core/lib/unit/base.rs @@ -14,10 +14,14 @@ use super::super::rel::ReStation; use super::kill::{KillContext, KillOperation}; use super::state::{UnitActiveState, UnitNotifyFlags}; use super::umif::UnitMngUtil; +use super::UnitType; use crate::error::*; +use bitflags::bitflags; use nix::sys::wait::WaitStatus; use nix::{sys::socket::UnixCredentials, unistd::Pid}; use std::any::Any; +use std::num::ParseIntError; +use std::str::FromStr; use std::{collections::HashMap, path::PathBuf, rc::Rc}; ///The trait Defining Shared Behavior from Base Unit to SUB unit @@ -206,3 +210,69 @@ macro_rules! declure_unitobj_plugin_with_param { } }; } + +bitflags! { + /// used to when check the given unit name is valid + pub struct UnitNameFlags: u8 { + /// Allow foo.service + const PLAIN = 1 << 0; + /// Allow foo@.service + const TEMPLATE = 1 << 1; + /// Allow foo@123.service + const INSTANCE = 1 << 2; + /// Any of the above + const ANY = Self::PLAIN.bits() | Self::TEMPLATE.bits() | Self::INSTANCE.bits(); + } +} + +/// The maximum length of a valid unit name +const UNIT_NAME_MAX: usize = 255; + +/// check if the given unit name is valid +pub fn unit_name_is_valid(name: &str, flag: UnitNameFlags) -> bool { + if name.is_empty() { + return false; + } + if name.len() > UNIT_NAME_MAX { + return false; + } + /* Take foo@123.service for example, "foo@123" is its first_name, + * "foo" is prefix, "service" is its last_name, suffix, or type. */ + let (first_name, last_name) = match name.split_once('.') { + None => return false, + Some(v) => (v.0, v.1), + }; + + let unit_type = match unit_type_from_string(last_name) { + Err(_) => return false, + Ok(v) => v, + }; + + if unit_type == UnitType::UnitTypeInvalid { + return false; + } + + match first_name.split_once('@') { + None => flag.contains(UnitNameFlags::PLAIN), + Some(v) => { + /* "@" is the first character */ + if v.0.is_empty() { + return false; + } + /* "@" is the last character */ + if v.1.is_empty() { + return flag.contains(UnitNameFlags::TEMPLATE); + } + /* there is more than one "@" */ + if v.1.contains('@') { + return false; + } + flag.contains(UnitNameFlags::INSTANCE) + } + } +} + +/// convert the type string of one unit to UnitType +pub fn unit_type_from_string(type_string: &str) -> Result { + UnitType::from_str(type_string) +} diff --git a/core/lib/unit/mod.rs b/core/lib/unit/mod.rs index 7211aec..1eb565c 100644 --- a/core/lib/unit/mod.rs +++ b/core/lib/unit/mod.rs @@ -11,11 +11,12 @@ // See the Mulan PSL v2 for more details. //! -pub use base::{SubUnit, UnitBase}; +pub use base::{unit_name_is_valid, SubUnit, UnitBase, UnitNameFlags}; pub use deps::{UnitDependencyMask, UnitRelationAtom, UnitRelations, UnitType}; pub use kill::{KillContext, KillMode, KillOperation}; pub use state::{UnitActiveState, UnitNotifyFlags, UnitStatus}; pub use umif::{UmIf, UnitManagerObj, UnitMngUtil}; + mod base; mod deps; mod kill; -- 2.30.2