1pub const FATHER_MAGIC_GID: u32 = 7823;
10
11pub const KNOWN_MAGIC_GIDS: &[(u32, &str)] = &[(7823, "Father")];
15
16pub fn classify_magic_gid(gid: u32) -> Option<&'static str> {
19 KNOWN_MAGIC_GIDS
20 .iter()
21 .find(|&&(known_gid, _)| known_gid == gid)
22 .map(|&(_, name)| name)
23}
24
25pub fn has_magic_gid(gids: &[u32]) -> bool {
27 gids.iter().any(|&g| classify_magic_gid(g).is_some())
28}
29
30#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
32pub struct MagicGidFinding {
33 pub pid: u32,
35 pub comm: String,
37 pub magic_gid: u32,
39 pub rootkit_name: &'static str,
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn classify_father_magic_gid_returns_some() {
49 assert_eq!(classify_magic_gid(7823), Some("Father"));
50 }
51
52 #[test]
53 fn classify_normal_gid_returns_none() {
54 assert_eq!(classify_magic_gid(1000), None);
55 }
56
57 #[test]
58 fn classify_zero_gid_returns_none() {
59 assert_eq!(classify_magic_gid(0), None);
60 }
61
62 #[test]
63 fn has_magic_gid_true_when_present() {
64 assert!(has_magic_gid(&[1000, 7823]));
65 }
66
67 #[test]
68 fn has_magic_gid_false_when_absent() {
69 assert!(!has_magic_gid(&[1000, 2000]));
70 }
71
72 #[test]
73 fn has_magic_gid_empty_slice_is_false() {
74 assert!(!has_magic_gid(&[]));
75 }
76
77 #[test]
78 fn magic_gid_finding_fields_constructible() {
79 let finding = MagicGidFinding {
80 pid: 1234,
81 comm: "evil".to_string(),
82 magic_gid: 7823,
83 rootkit_name: "Father",
84 };
85 assert_eq!(finding.pid, 1234);
86 assert_eq!(finding.comm, "evil");
87 assert_eq!(finding.magic_gid, 7823);
88 assert_eq!(finding.rootkit_name, "Father");
89 }
90
91 #[test]
92 fn magic_gid_finding_serializes_to_json() {
93 let finding = MagicGidFinding {
94 pid: 42,
95 comm: "rootkit".to_string(),
96 magic_gid: 7823,
97 rootkit_name: "Father",
98 };
99 let json = serde_json::to_string(&finding).unwrap();
100 assert!(json.contains("\"pid\":42"));
101 assert!(json.contains("\"magic_gid\":7823"));
102 assert!(json.contains("\"rootkit_name\":\"Father\""));
103 }
104
105 #[test]
106 fn magic_gid_finding_clone_and_debug() {
107 let finding = MagicGidFinding {
108 pid: 99,
109 comm: "sh".to_string(),
110 magic_gid: 7823,
111 rootkit_name: "Father",
112 };
113 let cloned = finding.clone();
114 let dbg = format!("{cloned:?}");
115 assert!(dbg.contains("Father"));
116 }
117
118 #[test]
119 fn father_magic_gid_constant_matches_known_table() {
120 let found = KNOWN_MAGIC_GIDS
121 .iter()
122 .any(|&(gid, name)| gid == FATHER_MAGIC_GID && name == "Father");
123 assert!(found, "FATHER_MAGIC_GID must appear in KNOWN_MAGIC_GIDS");
124 }
125}