Skip to content
API Documentation
BastionGuard™
anonymous_namespace{RootGuardPage.cpp} Namespace Reference

Functions

Gtk::Box * make_status_item (const Glib::ustring &label, Gtk::Label &value)
bool has_exact_path (const BastionGuard::RootGuard::Event &event)
Glib::ustring path_resolution_text (const BastionGuard::RootGuard::Event &event)
Glib::ustring incident_title (const BastionGuard::RootGuard::Event &event)
Glib::ustring incident_detail (const BastionGuard::RootGuard::Event &event)
bool restore_available (const BastionGuard::RootGuard::Event &event)
bool remove_available (const BastionGuard::RootGuard::Event &event)
Glib::ustring recovery_note (const BastionGuard::RootGuard::Event &event)
std::string incident_key (const BastionGuard::RootGuard::Event &event)
bool closes_incident (const BastionGuard::RootGuard::Event &event)
void clear_list (Gtk::ListBox &list)
void append_path_row (Gtk::ListBox &list, const std::string &path)
std::string trim_copy (std::string value)
std::string rules_signature (const BastionGuard::RootGuard::ApplicationRules &rules)

Function Documentation

◆ append_path_row()

void anonymous_namespace{RootGuardPage.cpp}::append_path_row ( Gtk::ListBox & list,
const std::string & path )

Definition at line 238 of file RootGuardPage.cpp.

239{
240 auto* label = Gtk::make_managed<Gtk::Label>(path);
241 label->set_halign(Gtk::Align::START);
242 label->set_hexpand(true);
243 label->set_selectable(true);
244 label->set_margin(8);
245 label->set_tooltip_text(path);
246 list.append(*label);
247}

References append_path_row().

Referenced by append_path_row().

◆ clear_list()

void anonymous_namespace{RootGuardPage.cpp}::clear_list ( Gtk::ListBox & list)

Definition at line 232 of file RootGuardPage.cpp.

233{
234 while (auto* child = list.get_first_child())
235 list.remove(*child);
236}

References clear_list().

Referenced by clear_list().

◆ closes_incident()

bool anonymous_namespace{RootGuardPage.cpp}::closes_incident ( const BastionGuard::RootGuard::Event & event)

Definition at line 225 of file RootGuardPage.cpp.

226{
227 return event.event == "file-restored" ||
228 event.event == "file-quarantined" ||
229 event.event == "integrity-restored";
230}

References closes_incident().

Referenced by closes_incident().

◆ has_exact_path()

bool anonymous_namespace{RootGuardPage.cpp}::has_exact_path ( const BastionGuard::RootGuard::Event & event)

Definition at line 39 of file RootGuardPage.cpp.

40{
41 return !event.filename.empty() && event.filename.front() == '/';
42}

References has_exact_path().

Referenced by has_exact_path(), incident_detail(), incident_key(), recovery_note(), remove_available(), and restore_available().

◆ incident_detail()

Glib::ustring anonymous_namespace{RootGuardPage.cpp}::incident_detail ( const BastionGuard::RootGuard::Event & event)

Definition at line 105 of file RootGuardPage.cpp.

106{
107 std::ostringstream output;
108 output << "Affected object: "
109 << (event.filename.empty() ? "--" : event.filename);
110
111 if (has_exact_path(event)) {
112 const std::filesystem::path affected(event.filename);
113 const std::string directory = affected.parent_path().string();
114 output << "\nAffected directory: "
115 << (directory.empty() ? "/" : directory);
116 } else {
117 output << "\nAffected directory: unavailable";
118 }
119
120 output << "\nPath resolution: " << path_resolution_text(event).raw();
121
122 if (event.device != 0 || event.inode != 0)
123 output << "\nTarget identity: " << event.device << ':' << event.inode;
124
125 output << "\nProcess name: "
126 << (event.comm.empty() ? "unknown" : event.comm)
127 << "\nProcess identifiers: PID " << event.pid
128 << " · TGID " << event.tgid
129 << " · PPID " << event.ppid;
130
131 if (!event.parent_comm.empty())
132 output << "\nParent process: " << event.parent_comm
133 << " (PID " << event.ppid << ')';
134 if (!event.parent_executable.empty())
135 output << "\nParent executable: " << event.parent_executable;
136
137 if (!event.actor_executable.empty()) {
138 output << "\nActor executable: " << event.actor_executable;
139 } else {
140 output << "\nActor executable: unresolved";
141 }
142
143 if (event.actor_device != 0 || event.actor_inode != 0)
144 output << "\nActor identity: " << event.actor_device
145 << ':' << event.actor_inode;
146 if (event.old_euid == event.new_euid)
147 output << "\nActor EUID: " << event.old_euid;
148 else
149 output << "\nActor EUID transition: " << event.old_euid
150 << " → " << event.new_euid;
151
152 if (event.old_mode != event.new_mode) {
153 output << "\nMode: " << std::oct << (event.old_mode & 07777U)
154 << " → " << (event.new_mode & 07777U) << std::dec;
155 }
156 if (event.old_uid != event.new_uid || event.old_gid != event.new_gid) {
157 output << "\nOwner: " << event.old_uid << ':' << event.old_gid
158 << " → " << event.new_uid << ':' << event.new_gid;
159 }
160 if ((event.reason_flags & RG_REASON_METADATA_BURST) != 0)
161 output << "\nBurst size in kernel window: " << event.auxiliary;
162 output << "\nVerdict: " << event.verdict
163 << " · Reason: 0x" << std::hex << event.reason_flags << std::dec;
165 output << "\nScope: system service definition";
166 return output.str();
167}
bool is_system_service_path(const std::string &path) noexcept
bool has_exact_path(const BastionGuard::RootGuard::Event &event)
Glib::ustring path_resolution_text(const BastionGuard::RootGuard::Event &event)
@ RG_REASON_METADATA_BURST

References BastionGuard::RootGuard::Event::actor_device, BastionGuard::RootGuard::Event::actor_executable, BastionGuard::RootGuard::Event::actor_inode, BastionGuard::RootGuard::Event::comm, BastionGuard::RootGuard::Event::device, BastionGuard::RootGuard::Event::filename, has_exact_path(), incident_detail(), BastionGuard::RootGuard::Event::inode, BastionGuard::RootGuard::is_system_service_path(), BastionGuard::RootGuard::Event::new_euid, BastionGuard::RootGuard::Event::new_gid, BastionGuard::RootGuard::Event::new_mode, BastionGuard::RootGuard::Event::new_uid, BastionGuard::RootGuard::Event::old_euid, BastionGuard::RootGuard::Event::old_gid, BastionGuard::RootGuard::Event::old_mode, BastionGuard::RootGuard::Event::old_uid, BastionGuard::RootGuard::Event::parent_comm, BastionGuard::RootGuard::Event::parent_executable, path_resolution_text(), BastionGuard::RootGuard::Event::reason_flags, and RG_REASON_METADATA_BURST.

Referenced by incident_detail().

◆ incident_key()

std::string anonymous_namespace{RootGuardPage.cpp}::incident_key ( const BastionGuard::RootGuard::Event & event)

Definition at line 217 of file RootGuardPage.cpp.

218{
219 if (has_exact_path(event))
220 return event.filename;
221 return event.filename + "\n" + std::to_string(event.device) + ':' +
222 std::to_string(event.inode);
223}

References BastionGuard::RootGuard::Event::device, has_exact_path(), incident_key(), and BastionGuard::RootGuard::Event::inode.

Referenced by incident_key().

◆ incident_title()

Glib::ustring anonymous_namespace{RootGuardPage.cpp}::incident_title ( const BastionGuard::RootGuard::Event & event)

Definition at line 59 of file RootGuardPage.cpp.

60{
61 const bool blocked = event.verdict == "blocked";
62 const bool audit = event.verdict == "audit";
63
64 if (event.event == "service-blocked")
65 return blocked
66 ? _("System service stopped and runtime-blocked")
67 : _("System service blocking failed");
68 if ((event.reason_flags & RG_REASON_METADATA_BURST) != 0)
69 return _("Unusual permission-change burst detected");
70 if (event.event == "integrity-drift")
71 return _("Protected file integrity changed");
72 if (event.event == "permission-change")
73 return blocked ? _("Permission change blocked")
74 : audit ? _("Permission change observed")
75 : _("Permission change detected");
76 if (event.event == "owner-change")
77 return blocked ? _("Ownership change blocked")
78 : audit ? _("Ownership change observed")
79 : _("Ownership change detected");
80 if (event.event == "protected-unlink")
81 return blocked ? _("Protected file removal blocked")
82 : audit ? _("Protected file removal observed")
83 : _("Protected file removal detected");
84 if (event.event == "protected-rename")
85 return blocked ? _("Protected file rename blocked")
86 : audit ? _("Protected file rename observed")
87 : _("Protected file rename detected");
88 if (event.event == "protected-hardlink")
89 return blocked ? _("Protected hard-link creation blocked")
90 : audit ? _("Protected hard-link creation observed")
91 : _("Protected hard-link creation detected");
92 if (event.event == "xattr-change")
93 return blocked ? _("Extended-attribute change blocked")
94 : audit ? _("Extended-attribute change observed")
95 : _("Extended-attribute change detected");
96 if (event.event == "acl-change")
97 return blocked ? _("ACL change blocked")
98 : audit ? _("ACL change observed")
99 : _("ACL change detected");
100 return blocked ? _("Protected metadata change blocked")
101 : audit ? _("Protected metadata change observed")
102 : _("Protected metadata change detected");
103}
#define _(s)

References _, BastionGuard::RootGuard::Event::event, incident_title(), BastionGuard::RootGuard::Event::reason_flags, and RG_REASON_METADATA_BURST.

Referenced by incident_title().

◆ make_status_item()

Gtk::Box * anonymous_namespace{RootGuardPage.cpp}::make_status_item ( const Glib::ustring & label,
Gtk::Label & value )

Definition at line 21 of file RootGuardPage.cpp.

22{
23 auto* box = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 4);
24 box->add_css_class("rootguard-status-item");
25 box->set_hexpand(true);
26
27 auto* name = Gtk::make_managed<Gtk::Label>(label);
28 name->set_halign(Gtk::Align::CENTER);
29 name->add_css_class("rootguard-status-label");
30 box->append(*name);
31
32 value.set_halign(Gtk::Align::CENTER);
33 value.set_wrap(true);
34 value.add_css_class("rootguard-status-value");
35 box->append(value);
36 return box;
37}

References make_status_item().

Referenced by make_status_item().

◆ path_resolution_text()

Glib::ustring anonymous_namespace{RootGuardPage.cpp}::path_resolution_text ( const BastionGuard::RootGuard::Event & event)

Definition at line 44 of file RootGuardPage.cpp.

45{
46 if (event.path_resolution == "protected-baseline")
47 return _("exact path from protected baseline");
48 if (event.path_resolution == "proc-fd")
49 return _("exact path resolved from the process file descriptor");
50 if (event.path_resolution == "process-cwd")
51 return _("exact path resolved from the process working directory");
52 if (event.path_resolution == "kernel-exact")
53 return _("exact path supplied by the kernel event");
54 if (event.path_resolution == "lsm-exact")
55 return _("exact path captured by the LSM before the metadata operation");
56 return _("basename only; the exact path was unavailable in this event");
57}

References _, BastionGuard::RootGuard::Event::path_resolution, and path_resolution_text().

Referenced by incident_detail(), and path_resolution_text().

◆ recovery_note()

Glib::ustring anonymous_namespace{RootGuardPage.cpp}::recovery_note ( const BastionGuard::RootGuard::Event & event)

Definition at line 200 of file RootGuardPage.cpp.

201{
202 if (event.rule_id == 0)
203 return _("This event belongs to global filesystem surveillance. No protected baseline is attached, so Restore and Quarantine are unavailable.");
204 if (!has_exact_path(event))
205 return _("RootGuard has the filesystem identity but not an exact path. Destructive actions are disabled to avoid acting on the wrong object.");
206 if (event.event == "protected-unlink")
207 return event.verdict == "blocked"
208 ? _("The removal was denied; the file is still present and no restore is required.")
209 : _("The file was removed in audit mode. Automatic restore is impossible without a trusted backup or package copy.");
210 if (event.event == "protected-rename")
211 return _("Automatic recovery is unavailable for rename events. Restore the file from a trusted package or backup.");
212 if (event.event == "protected-hardlink")
213 return _("No automatic action is offered for hard-link events. Review the source and destination manually.");
214 return {};
215}

References _, BastionGuard::RootGuard::Event::event, has_exact_path(), recovery_note(), and BastionGuard::RootGuard::Event::rule_id.

Referenced by recovery_note().

◆ remove_available()

bool anonymous_namespace{RootGuardPage.cpp}::remove_available ( const BastionGuard::RootGuard::Event & event)

Definition at line 184 of file RootGuardPage.cpp.

185{
186 if (event.rule_id == 0 || !has_exact_path(event))
187 return false;
188
189 constexpr std::uint32_t kProtectedMissing = 1U << 21;
190 if ((event.reason_flags & kProtectedMissing) != 0)
191 return false;
192
193 return event.event == "permission-change" ||
194 event.event == "owner-change" ||
195 event.event == "xattr-change" ||
196 event.event == "acl-change" ||
197 event.event == "integrity-drift";
198}

References has_exact_path(), BastionGuard::RootGuard::Event::reason_flags, remove_available(), and BastionGuard::RootGuard::Event::rule_id.

Referenced by remove_available().

◆ restore_available()

bool anonymous_namespace{RootGuardPage.cpp}::restore_available ( const BastionGuard::RootGuard::Event & event)

Definition at line 169 of file RootGuardPage.cpp.

170{
171 if (event.rule_id == 0 || !has_exact_path(event))
172 return false;
173
174 constexpr std::uint32_t kBaselineFileReplaced = 1U << 20;
175 constexpr std::uint32_t kProtectedMissing = 1U << 21;
176 if ((event.reason_flags & (kBaselineFileReplaced | kProtectedMissing)) != 0)
177 return false;
178 return event.event == "permission-change" ||
179 event.event == "owner-change" ||
180 event.event == "integrity-drift" ||
181 event.event == "service-blocked";
182}

References has_exact_path(), BastionGuard::RootGuard::Event::reason_flags, restore_available(), and BastionGuard::RootGuard::Event::rule_id.

Referenced by restore_available().

◆ rules_signature()

std::string anonymous_namespace{RootGuardPage.cpp}::rules_signature ( const BastionGuard::RootGuard::ApplicationRules & rules)

Definition at line 258 of file RootGuardPage.cpp.

259{
260 std::ostringstream output;
261 const auto append = [&output](const char marker,
262 const std::vector<std::string>& values) {
263 output << marker << ':' << values.size() << '\n';
264 for (const auto& value : values)
265 output << value << '\n';
266 };
267 append('A', rules.trustedApplications);
268 append('T', rules.trustedExecutables);
269 append('D', rules.deniedExecutables);
270 return output.str();
271}
std::vector< std::string > deniedExecutables
std::vector< std::string > trustedExecutables
std::vector< std::string > trustedApplications

References BastionGuard::RootGuard::ApplicationRules::deniedExecutables, rules_signature(), BastionGuard::RootGuard::ApplicationRules::trustedApplications, and BastionGuard::RootGuard::ApplicationRules::trustedExecutables.

Referenced by rules_signature().

◆ trim_copy()

std::string anonymous_namespace{RootGuardPage.cpp}::trim_copy ( std::string value)

Definition at line 249 of file RootGuardPage.cpp.

250{
251 const auto first = value.find_first_not_of(" \t\r\n");
252 if (first == std::string::npos)
253 return {};
254 const auto last = value.find_last_not_of(" \t\r\n");
255 return value.substr(first, last - first + 1);
256}

References trim_copy().

Referenced by trim_copy().