Skip to content

Commit 12493e3

Browse files
committed
whippet: fix default values and wildcard usage
Use the correct default value for the `max_fds` fields of send and receive records. Replace wildcard values for send and receive rules with an empty string as this is what the broker uses for fallback rules. Signed-off-by: Arnaldo Garcia Rincon <agarrcia@amazon.com>
1 parent 3907fa0 commit 12493e3

File tree

5 files changed

+224
-17
lines changed

5 files changed

+224
-17
lines changed

sources/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sources/whippet/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ zvariant = { workspace = true }
2424

2525
[build-dependencies]
2626
generate-readme.workspace = true
27+
28+
[dev-dependencies]
29+
test-case.workspace = true

sources/whippet/src/dbus_policy.rs

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ use serde::Serialize;
2626
use snafu::ResultExt;
2727
use zvariant::{Type, Value as ZVariantValue};
2828

29+
const DEFAULT_MAX_FDS: u64 = u64::MAX;
30+
2931
/// Top-level policy structure that matches launcher's Dbus format. It is crucial that
3032
/// the order of the fields remains like it is, otherwise the broker rejects the policy.
3133
///
@@ -72,7 +74,7 @@ pub struct OwnRecord {
7274
/// https://github.com/bus1/dbus-broker/blob/b0db0890d1254477cf832e5f9f0a798360c80fd9/src/launch/policy.c#L877
7375
macro_rules! impl_record {
7476
($record_type:ident) => {
75-
#[derive(Debug, Type, Serialize, Clone, ZVariantValue, Default)]
77+
#[derive(Debug, Type, Serialize, Clone, ZVariantValue)]
7678
pub struct $record_type {
7779
pub verdict: bool,
7880
pub priority: u64,
@@ -85,6 +87,23 @@ macro_rules! impl_record {
8587
pub min_fds: u64,
8688
pub max_fds: u64,
8789
}
90+
91+
impl Default for $record_type {
92+
fn default() -> Self {
93+
Self {
94+
verdict: Default::default(),
95+
priority: Default::default(),
96+
name: Default::default(),
97+
path: Default::default(),
98+
interface: Default::default(),
99+
member: Default::default(),
100+
record_type: Default::default(),
101+
broadcast: Default::default(),
102+
min_fds: Default::default(),
103+
max_fds: crate::dbus_policy::DEFAULT_MAX_FDS,
104+
}
105+
}
106+
}
88107
};
89108
}
90109

@@ -98,19 +117,16 @@ impl TryFrom<&Rule> for SendRecord {
98117
allow,
99118
priority,
100119
send_broadcast,
101-
send_destination,
102-
send_interface,
103-
send_member,
104-
send_path,
105120
send_type,
121+
..
106122
} => Ok(Self {
107123
verdict: *allow,
108124
priority: *priority,
109125
broadcast: *send_broadcast,
110-
name: send_destination.clone(),
111-
interface: send_interface.clone(),
112-
member: send_member.clone(),
113-
path: send_path.clone(),
126+
name: rule.name()?,
127+
interface: rule.interface()?,
128+
member: rule.member()?,
129+
path: rule.path()?,
114130
record_type: *send_type,
115131
..Self::default()
116132
}),
@@ -133,19 +149,16 @@ impl TryFrom<&Rule> for ReceiveRecord {
133149
allow,
134150
priority,
135151
receive_broadcast,
136-
receive_interface,
137-
receive_member,
138-
receive_path,
139-
receive_sender,
140152
receive_type,
153+
..
141154
} => Ok(Self {
142155
verdict: *allow,
143156
priority: *priority,
144157
broadcast: *receive_broadcast,
145-
interface: receive_interface.clone(),
146-
member: receive_member.clone(),
147-
path: receive_path.clone(),
148-
name: receive_sender.clone(),
158+
interface: rule.interface()?,
159+
member: rule.member()?,
160+
path: rule.path()?,
161+
name: rule.name()?,
149162
record_type: *receive_type,
150163
..Self::default()
151164
}),
@@ -455,4 +468,24 @@ mod tests {
455468
let dbus_policy: DbusPolicy = policy.try_into().unwrap();
456469
assert_eq!(dbus_policy.uid_entries[1].1.send_rules.len(), 2);
457470
}
471+
472+
#[test]
473+
fn test_wildcards_replaced_with_empty_string() {
474+
let config_str = r#"
475+
[default]
476+
rules = [
477+
{ allow = true, send_interface = "*", send_destination = "*", send_path = "*", send_member = "*" },
478+
]
479+
"#;
480+
let mut policy: Policy = toml::from_str(config_str).unwrap();
481+
policy.set_rule_priorities(&mut 0u64);
482+
policy.prepare().unwrap();
483+
policy.optimize();
484+
485+
let dbus_policy: DbusPolicy = policy.try_into().unwrap();
486+
assert_eq!(dbus_policy.uid_entries[0].1.send_rules[0].interface, "");
487+
assert_eq!(dbus_policy.uid_entries[0].1.send_rules[0].name, "");
488+
assert_eq!(dbus_policy.uid_entries[0].1.send_rules[0].member, "");
489+
assert_eq!(dbus_policy.uid_entries[0].1.send_rules[0].path, "");
490+
}
458491
}

sources/whippet/src/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,7 @@ pub enum Error {
133133
uid: String,
134134
source: std::num::ParseIntError,
135135
},
136+
137+
#[snafu(display("Can't get property '{property}' from rule '{rule_type}'"))]
138+
InvalidPropertyForRule { property: String, rule_type: String },
136139
}

sources/whippet/src/policy.rs

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,118 @@ fn find_priority_threshold(rules: &[Rule]) -> u64 {
466466
}
467467

468468
impl Rule {
469+
/// Returns the "interface" value used in the final policy, replacing wildcards with empty
470+
/// strings
471+
/// See: https://github.com/bus1/dbus-broker/blob/e3324b3736fd40d95e7943fca6e485013d15d643/src/launch/policy.c#L97
472+
pub(crate) fn interface(&self) -> Result<String> {
473+
match self {
474+
Self::Send { send_interface, .. } => {
475+
if send_interface == "*" {
476+
Ok("".to_string())
477+
} else {
478+
Ok(send_interface.to_owned())
479+
}
480+
}
481+
Self::Receive {
482+
receive_interface, ..
483+
} => {
484+
if receive_interface == "*" {
485+
Ok("".to_string())
486+
} else {
487+
Ok(receive_interface.to_owned())
488+
}
489+
}
490+
_ => error::InvalidPropertyForRuleSnafu {
491+
property: "interface".to_string(),
492+
rule_type: format!("{self:?}"),
493+
}
494+
.fail(),
495+
}
496+
}
497+
498+
/// Returns the "name" value used in the final policy, replacing wildcards with empty
499+
/// strings
500+
/// See: https://github.com/bus1/dbus-broker/blob/e3324b3736fd40d95e7943fca6e485013d15d643/src/launch/policy.c#L97
501+
pub(crate) fn name(&self) -> Result<String> {
502+
match self {
503+
Self::Send {
504+
send_destination, ..
505+
} => {
506+
if send_destination == "*" {
507+
Ok("".to_string())
508+
} else {
509+
Ok(send_destination.to_owned())
510+
}
511+
}
512+
Self::Receive { receive_sender, .. } => {
513+
if receive_sender == "*" {
514+
Ok("".to_string())
515+
} else {
516+
Ok(receive_sender.to_owned())
517+
}
518+
}
519+
_ => error::InvalidPropertyForRuleSnafu {
520+
property: "name".to_string(),
521+
rule_type: format!("{self:?}"),
522+
}
523+
.fail(),
524+
}
525+
}
526+
527+
/// Returns the "member" value used in the final policy, replacing wildcards with empty
528+
/// strings
529+
/// See: https://github.com/bus1/dbus-broker/blob/e3324b3736fd40d95e7943fca6e485013d15d643/src/launch/policy.c#L97
530+
pub(crate) fn member(&self) -> Result<String> {
531+
match self {
532+
Self::Send { send_member, .. } => {
533+
if send_member == "*" {
534+
Ok("".to_string())
535+
} else {
536+
Ok(send_member.to_owned())
537+
}
538+
}
539+
Self::Receive { receive_member, .. } => {
540+
if receive_member == "*" {
541+
Ok("".to_string())
542+
} else {
543+
Ok(receive_member.to_owned())
544+
}
545+
}
546+
_ => error::InvalidPropertyForRuleSnafu {
547+
property: "member".to_string(),
548+
rule_type: format!("{self:?}"),
549+
}
550+
.fail(),
551+
}
552+
}
553+
554+
/// Returns the "path" value used in the final policy, replacing wildcards with empty
555+
/// strings
556+
/// See: https://github.com/bus1/dbus-broker/blob/e3324b3736fd40d95e7943fca6e485013d15d643/src/launch/policy.c#L97
557+
pub(crate) fn path(&self) -> Result<String> {
558+
match self {
559+
Self::Send { send_path, .. } => {
560+
if send_path == "*" {
561+
Ok("".to_string())
562+
} else {
563+
Ok(send_path.to_owned())
564+
}
565+
}
566+
Self::Receive { receive_path, .. } => {
567+
if receive_path == "*" {
568+
Ok("".to_string())
569+
} else {
570+
Ok(receive_path.to_owned())
571+
}
572+
}
573+
_ => error::InvalidPropertyForRuleSnafu {
574+
property: "path".to_string(),
575+
rule_type: format!("{self:?}"),
576+
}
577+
.fail(),
578+
}
579+
}
580+
469581
/// Sets the priority of the rule
470582
fn set_priority(&mut self, new_priority: u64) {
471583
match self {
@@ -551,6 +663,7 @@ impl UsernameResolver for PasswdUsernameResolver {
551663
#[cfg(test)]
552664
mod tests {
553665
use super::*;
666+
use test_case::test_case;
554667

555668
const ALICE_USER: u32 = 1;
556669
const BOB_USER: u32 = 2;
@@ -920,4 +1033,58 @@ mod tests {
9201033
clean_connect_rules(4, &mut rules);
9211034
assert!(rules.is_empty());
9221035
}
1036+
1037+
#[test_case(Rule::Send {
1038+
allow: false,
1039+
priority: u64::default(),
1040+
send_broadcast: u32::default(),
1041+
send_destination: "*".to_string(),
1042+
send_interface: "*".to_string(),
1043+
send_member: "*".to_string(),
1044+
send_path: "*".to_string(),
1045+
send_type: MessageType::default(),
1046+
}; "witt a send rule wildcards are replaced with empty strings")]
1047+
#[test_case(Rule::Receive {
1048+
allow: false,
1049+
priority: u64::default(),
1050+
receive_broadcast: u32::default(),
1051+
receive_interface: "*".to_string(),
1052+
receive_member: "*".to_string(),
1053+
receive_path: "*".to_string(),
1054+
receive_sender: "*".to_string(),
1055+
receive_type: MessageType::default(),
1056+
}; "with a receive rule wildcards are replaced with empty strings")]
1057+
fn rules_with_wildcards(rule: Rule) {
1058+
assert_eq!(rule.name().unwrap(), "");
1059+
assert_eq!(rule.interface().unwrap(), "");
1060+
assert_eq!(rule.member().unwrap(), "");
1061+
assert_eq!(rule.path().unwrap(), "");
1062+
}
1063+
1064+
#[test_case(Rule::Send {
1065+
allow: false,
1066+
priority: u64::default(),
1067+
send_broadcast: u32::default(),
1068+
send_destination: "name".to_string(),
1069+
send_interface: "interface".to_string(),
1070+
send_member: "member".to_string(),
1071+
send_path: "path".to_string(),
1072+
send_type: MessageType::default(),
1073+
}; "with a send rule the original value is returned")]
1074+
#[test_case(Rule::Receive {
1075+
allow: false,
1076+
priority: u64::default(),
1077+
receive_broadcast: u32::default(),
1078+
receive_interface: "interface".to_string(),
1079+
receive_member: "member".to_string(),
1080+
receive_path: "path".to_string(),
1081+
receive_sender: "name".to_string(),
1082+
receive_type: MessageType::default(),
1083+
}; "with a receive rule the original value is returned")]
1084+
fn rules_without_wildcards(rule: Rule) {
1085+
assert_eq!(rule.name().unwrap(), "name");
1086+
assert_eq!(rule.interface().unwrap(), "interface");
1087+
assert_eq!(rule.member().unwrap(), "member");
1088+
assert_eq!(rule.path().unwrap(), "path");
1089+
}
9231090
}

0 commit comments

Comments
 (0)