Skip to content

Commit 0b0c5fe

Browse files
author
Teddy Reed
authored
tables: Add device_firmware to darwin (osquery#3499)
1 parent 8ba9a54 commit 0b0c5fe

File tree

2 files changed

+86
-13
lines changed

2 files changed

+86
-13
lines changed

osquery/tables/system/darwin/iokit_registry.cpp

Lines changed: 78 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,61 @@
1616
namespace osquery {
1717
namespace tables {
1818

19+
/// A set of common IOKit properties used to store firmware versions.
20+
const std::set<std::string> kFirmwareProperties{
21+
"Firmware Revision", "IOFirmwareVersion", "FirmwareVersionString",
22+
};
23+
24+
/**
25+
* @brief A callback for each entry in the IOKit registry.
26+
*
27+
* An enumerator should fill in the table's results.
28+
*/
29+
using IOKitEnumerator = std::function<void(const io_service_t& device,
30+
const io_service_t& parent,
31+
const io_name_t plane,
32+
int depth,
33+
QueryData& results)>;
34+
35+
static inline void genFirmware(const void* key, const void* value, void* r) {
36+
auto* r2 = (Row*)r;
37+
if (key == nullptr || value == nullptr || r2->count("version") != 0) {
38+
return;
39+
}
40+
41+
auto prop = stringFromCFString((CFStringRef)key);
42+
if (kFirmwareProperties.find(prop) != kFirmwareProperties.end()) {
43+
(*r2)["version"] = prop;
44+
}
45+
}
46+
47+
void genIOKitFirmware(const io_service_t& device,
48+
const io_service_t& parent,
49+
const io_name_t plane,
50+
int depth,
51+
QueryData& results) {
52+
Row r;
53+
io_name_t name;
54+
auto kr = IORegistryEntryGetName(device, name);
55+
if (kr == KERN_SUCCESS) {
56+
r["device"] = std::string(name);
57+
}
58+
59+
CFMutableDictionaryRef details;
60+
IORegistryEntryCreateCFProperties(
61+
device, &details, kCFAllocatorDefault, kNilOptions);
62+
CFDictionaryApplyFunction(details, &genFirmware, &r);
63+
if (r.count("version") != 0) {
64+
// If the version is filled in from the dictionary walk callback then
65+
// the value of the property name contains the firmware version.
66+
r["version"] = getIOKitProperty(details, r["version"]);
67+
r["type"] = getIOKitProperty(details, "IOProviderClass");
68+
results.push_back(r);
69+
}
70+
71+
CFRelease(details);
72+
}
73+
1974
void genIOKitDevice(const io_service_t& device,
2075
const io_service_t& parent,
2176
const io_name_t plane,
@@ -82,7 +137,8 @@ void genIOKitDevice(const io_service_t& device,
82137
results.push_back(r);
83138
}
84139

85-
void genIOKitDeviceChildren(const io_registry_entry_t& service,
140+
void genIOKitDeviceChildren(IOKitEnumerator enumerator,
141+
const io_registry_entry_t& service,
86142
const io_name_t plane,
87143
int depth,
88144
QueryData& results) {
@@ -95,38 +151,47 @@ void genIOKitDeviceChildren(const io_registry_entry_t& service,
95151
io_service_t device;
96152
while ((device = IOIteratorNext(it))) {
97153
// Use this entry as the parent, and generate a result row.
98-
genIOKitDevice(device, service, plane, depth, results);
99-
genIOKitDeviceChildren(device, plane, depth + 1, results);
154+
enumerator(device, service, plane, depth, results);
155+
genIOKitDeviceChildren(enumerator, device, plane, depth + 1, results);
100156
IOObjectRelease(device);
101157
}
102158

103159
IOObjectRelease(it);
104160
}
105161

162+
QueryData genDeviceFirmware(QueryContext& context) {
163+
QueryData qd;
164+
165+
// Start with the services root node.
166+
auto service = IORegistryGetRootEntry(kIOMasterPortDefault);
167+
genIOKitDeviceChildren(&genIOKitFirmware, service, kIOServicePlane, 0, qd);
168+
IOObjectRelease(service);
169+
170+
return qd;
171+
}
172+
106173
QueryData genIOKitDeviceTree(QueryContext& context) {
107-
QueryData results;
174+
QueryData qd;
108175

109176
// Get the IO registry root node.
110177
auto service = IORegistryGetRootEntry(kIOMasterPortDefault);
111-
112178
// Begin recursing along the IODeviceTree "plane".
113-
genIOKitDeviceChildren(service, kIODeviceTreePlane, 0, results);
114-
179+
genIOKitDeviceChildren(&genIOKitDevice, service, kIODeviceTreePlane, 0, qd);
115180
IOObjectRelease(service);
116-
return results;
181+
182+
return qd;
117183
}
118184

119185
QueryData genIOKitRegistry(QueryContext& context) {
120-
QueryData results;
186+
QueryData qd;
121187

122188
// Get the IO registry root node.
123189
auto service = IORegistryGetRootEntry(kIOMasterPortDefault);
124-
125190
// Begin recursing along the IODeviceTree "plane".
126-
genIOKitDeviceChildren(service, kIOServicePlane, 0, results);
127-
191+
genIOKitDeviceChildren(&genIOKitDevice, service, kIOServicePlane, 0, qd);
128192
IOObjectRelease(service);
129-
return results;
193+
194+
return qd;
130195
}
131196
}
132197
}

specs/darwin/device_firmware.table

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
table_name("device_firmware")
2+
description("A best-effort list of discovered firmware versions.")
3+
schema([
4+
Column("type", TEXT, "Type of device"),
5+
Column("device", TEXT, "The device name", index=True),
6+
Column("version", TEXT, "Firmware version"),
7+
])
8+
implementation("device_firmware@genDeviceFirmware")

0 commit comments

Comments
 (0)