sysmaster/backport-fix-check-if-the-given-unit-name-is-valid-before-we-.patch
licunlong 0c7d548f94 sync patches from upstream
(cherry picked from commit e23ebb83bd7672e4dc8da68a9a8c73fe6e016341)
2023-06-19 10:39:49 +08:00

194 lines
6.1 KiB
Diff

From 8123dcec5160b0d29e541cec1c9a027a1dd42c48 Mon Sep 17 00:00:00 2001
From: licunlong <licunlong1@huawei.com>
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<Rc<Unit>> {
+ 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<Rc<UnitX>> {
+ 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, ParseIntError> {
+ 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