diff --git a/jay-config/src/_private.rs b/jay-config/src/_private.rs index 95188583..29359e2f 100644 --- a/jay-config/src/_private.rs +++ b/jay-config/src/_private.rs @@ -82,6 +82,7 @@ pub enum ClientCriterionIpc { regex: bool, }, Sandboxed, + Uid(i32), } #[derive(Serialize, Deserialize, Clone, Debug, Hash, Eq, PartialEq)] diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index 2a9d1639..12c8e3b4 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -1542,6 +1542,7 @@ impl ConfigClient { ClientCriterion::SandboxInstanceId(t) => string!(t, SandboxInstanceId, false), ClientCriterion::SandboxInstanceIdRegex(t) => string!(t, SandboxInstanceId, true), ClientCriterion::Sandboxed => ClientCriterionIpc::Sandboxed, + ClientCriterion::Uid(p) => ClientCriterionIpc::Uid(p), }; let res = self.send_with_response(&ClientMessage::CreateClientMatcher { criterion }); get_response!( diff --git a/jay-config/src/client.rs b/jay-config/src/client.rs index 601053f4..1b2d4206 100644 --- a/jay-config/src/client.rs +++ b/jay-config/src/client.rs @@ -77,6 +77,8 @@ pub enum ClientCriterion<'a> { SandboxInstanceIdRegex(&'a str), /// Matches if the client is sandboxed. Sandboxed, + /// Matches the user ID of the client. + Uid(i32), } impl ClientCriterion<'_> { diff --git a/src/config/handler.rs b/src/config/handler.rs index 82cb3454..b34500a6 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -1885,6 +1885,7 @@ impl ConfigProxyHandler { } } ClientCriterionIpc::Sandboxed => mgr.sandboxed(), + ClientCriterionIpc::Uid(p) => mgr.uid(*p), }; let cached = Rc::new(CachedCriterion { crit: criterion.clone(), diff --git a/src/criteria/clm.rs b/src/criteria/clm.rs index 44e77ce7..a1d67a68 100644 --- a/src/criteria/clm.rs +++ b/src/criteria/clm.rs @@ -11,6 +11,7 @@ use { clmm_string::{ ClmMatchSandboxAppId, ClmMatchSandboxEngine, ClmMatchSandboxInstanceId, }, + clmm_uid::ClmMatchUid, }, crit_graph::{ CritMgr, CritRoot, CritRootFixed, CritTarget, CritTargetOwner, WeakCritTargetOwner, @@ -52,6 +53,7 @@ pub struct RootMatchers { sandbox_app_id: ClmRootMatcherMap, sandbox_engine: ClmRootMatcherMap, sandbox_instance_id: ClmRootMatcherMap, + uid: ClmRootMatcherMap, } pub async fn handle_cl_changes(state: Rc) { @@ -151,6 +153,7 @@ impl ClMatcherManager { unconditional!(sandbox_instance_id); unconditional!(sandbox_app_id); unconditional!(sandbox_engine); + unconditional!(uid); fixed!(sandboxed); self.constant[true].handle(data); } @@ -171,6 +174,10 @@ impl ClMatcherManager { pub fn sandboxed(&self) -> Rc { self.sandboxed[true].clone() } + + pub fn uid(&self, pid: i32) -> Rc { + self.root(ClmMatchUid(pid as _)) + } } impl CritTarget for Rc { diff --git a/src/criteria/clm/clm_matchers.rs b/src/criteria/clm/clm_matchers.rs index 58d2968b..b7886e61 100644 --- a/src/criteria/clm/clm_matchers.rs +++ b/src/criteria/clm/clm_matchers.rs @@ -19,3 +19,4 @@ macro_rules! fixed_root_criterion { pub mod clmm_sandboxed; pub mod clmm_string; +pub mod clmm_uid; diff --git a/src/criteria/clm/clm_matchers/clmm_uid.rs b/src/criteria/clm/clm_matchers/clmm_uid.rs new file mode 100644 index 00000000..6056b955 --- /dev/null +++ b/src/criteria/clm/clm_matchers/clmm_uid.rs @@ -0,0 +1,20 @@ +use { + crate::{ + client::Client, + criteria::{RootMatcherMap, clm::RootMatchers, crit_graph::CritRootCriterion}, + }, + std::rc::Rc, + uapi::c, +}; + +pub struct ClmMatchUid(pub c::uid_t); + +impl CritRootCriterion> for ClmMatchUid { + fn matches(&self, data: &Rc) -> bool { + data.pid_info.uid == self.0 + } + + fn nodes(roots: &RootMatchers) -> Option<&RootMatcherMap, Self>> { + Some(&roots.uid) + } +} diff --git a/toml-config/src/config.rs b/toml-config/src/config.rs index ad678a8c..c5c53eff 100644 --- a/toml-config/src/config.rs +++ b/toml-config/src/config.rs @@ -232,6 +232,7 @@ pub struct ClientMatch { pub sandbox_instance_id: Option, pub sandbox_instance_id_regex: Option, pub sandboxed: Option, + pub uid: Option, } #[derive(Debug, Clone)] diff --git a/toml-config/src/config/parsers/client_match.rs b/toml-config/src/config/parsers/client_match.rs index d82b5d9e..59c8a22f 100644 --- a/toml-config/src/config/parsers/client_match.rs +++ b/toml-config/src/config/parsers/client_match.rs @@ -3,7 +3,7 @@ use { config::{ ClientMatch, GenericMatch, MatchExactly, context::Context, - extractor::{Extractor, ExtractorError, arr, bol, n32, opt, str, val}, + extractor::{Extractor, ExtractorError, arr, bol, n32, opt, s32, str, val}, parser::{DataType, ParseResult, Parser, UnexpectedDataType}, }, toml::{ @@ -49,7 +49,7 @@ impl Parser for ClientMatchParser<'_> { sandbox_app_id, sandbox_app_id_regex, ), - (sandbox_instance_id, sandbox_instance_id_regex), + (sandbox_instance_id, sandbox_instance_id_regex, uid), ) = ext.extract(( ( opt(str("name")), @@ -66,6 +66,7 @@ impl Parser for ClientMatchParser<'_> { ( opt(str("sandbox-instance-id")), opt(str("sandbox-instance-id-regex")), + opt(s32("uid")), ), ))?; let mut not = None; @@ -106,6 +107,7 @@ impl Parser for ClientMatchParser<'_> { sandbox_instance_id: sandbox_instance_id.despan_into(), sandbox_instance_id_regex: sandbox_instance_id_regex.despan_into(), sandboxed: sandboxed.despan(), + uid: uid.despan(), }) } } diff --git a/toml-config/src/rules.rs b/toml-config/src/rules.rs index 73cab65f..f077d928 100644 --- a/toml-config/src/rules.rs +++ b/toml-config/src/rules.rs @@ -95,6 +95,13 @@ impl Rule for ClientRule { } }; } + macro_rules! value { + ($ty:ident, $field:ident) => { + if let Some(value) = match_.$field { + all.push(m(ClientCriterion::$ty(value))); + } + }; + } macro_rules! bool { ($ty:ident, $field:ident) => { if let Some(value) = &match_.$field { @@ -113,6 +120,7 @@ impl Rule for ClientRule { value_ref!(SandboxAppIdRegex, sandbox_app_id_regex); value_ref!(SandboxInstanceId, sandbox_instance_id); value_ref!(SandboxInstanceIdRegex, sandbox_instance_id_regex); + value!(Uid, uid); bool!(Sandboxed, sandboxed); Some(()) } diff --git a/toml-spec/spec/spec.generated.json b/toml-spec/spec/spec.generated.json index 1c65d462..b343ca76 100644 --- a/toml-spec/spec/spec.generated.json +++ b/toml-spec/spec/spec.generated.json @@ -559,6 +559,10 @@ "sandbox-instance-id-regex": { "type": "string", "description": "Matches the instance id of the client's sandbox with a regular expression.\n" + }, + "uid": { + "type": "integer", + "description": "Matches the user ID of the client." } }, "required": [] diff --git a/toml-spec/spec/spec.generated.md b/toml-spec/spec/spec.generated.md index b7a23796..f7011d77 100644 --- a/toml-spec/spec/spec.generated.md +++ b/toml-spec/spec/spec.generated.md @@ -871,6 +871,14 @@ The table has the following fields: The value of this field should be a string. +- `uid` (optional): + + Matches the user ID of the client. + + The value of this field should be a number. + + The numbers should be integers. + ### `ClientMatchExactly` diff --git a/toml-spec/spec/spec.yaml b/toml-spec/spec/spec.yaml index 510292f3..37cdb901 100644 --- a/toml-spec/spec/spec.yaml +++ b/toml-spec/spec/spec.yaml @@ -3237,6 +3237,11 @@ ClientMatch: required: false description: | Matches the instance id of the client's sandbox with a regular expression. + uid: + kind: number + integer_only: true + required: false + description: Matches the user ID of the client. ClientMatchExactly: