Skip to content

Commit

Permalink
tables: implement ibridge table to report on T1/T2 chip for mac noteb…
Browse files Browse the repository at this point in the history
…ooks (osquery#5707)
  • Loading branch information
sharvilshah authored and theopolis committed Aug 19, 2019
1 parent 1af15ed commit d9fdc5b
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 0 deletions.
1 change: 1 addition & 0 deletions osquery/tables/system/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ osquery_cxx_library(
"darwin/firewall.cpp",
"darwin/gatekeeper.cpp",
"darwin/homebrew_packages.cpp",
"darwin/ibridge.cpp",
"darwin/iokit_registry.cpp",
"darwin/kernel_extensions.cpp",
"darwin/kernel_info.cpp",
Expand Down
1 change: 1 addition & 0 deletions osquery/tables/system/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ function(generateOsqueryTablesSystemSystemtable)
darwin/firewall.cpp
darwin/gatekeeper.cpp
darwin/homebrew_packages.cpp
darwin/ibridge.cpp
darwin/iokit_registry.cpp
darwin/kernel_extensions.cpp
darwin/kernel_info.cpp
Expand Down
126 changes: 126 additions & 0 deletions osquery/tables/system/darwin/ibridge.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/**
* This source code is licensed in accordance with the terms specified in
* the LICENSE file found in the root directory of this source tree.
*/

#include <osquery/logger.h>
#include <osquery/tables.h>
#include <osquery/utils/conversions/darwin/iokit.h>

namespace osquery {
namespace tables {

#define kIODeviceEfiPath_ ":/efi/platform"
#define kIODeviceChosenPath_ ":/chosen"
#define kEmbeddedOSClass_ "AppleEmbeddedOSSupportHost"
#define kAppleCoprocessorVersionKey_ "apple-coprocessor-version"

/// as defined in
/// /System/Library/Frameworks/Kernel.framework/Headers/IOKit/IOPlatformExpert.h
static const std::unordered_map<uint32_t, std::string> kCoprocessorVersions = {
{0x00000000, ""},
{0x00010000, "Apple T1 Chip"},
{0x00020000, "Apple T2 Chip"},
};

static inline void genBootUuid(Row& r) {
auto chosen = IORegistryEntryFromPath(
kIOMasterPortDefault, kIODeviceTreePlane kIODeviceChosenPath_);
if (chosen == MACH_PORT_NULL) {
return;
}

CFMutableDictionaryRef properties = nullptr;
auto kr = IORegistryEntryCreateCFProperties(
chosen, &properties, kCFAllocatorDefault, kNilOptions);
IOObjectRelease(chosen);

if (kr != KERN_SUCCESS) {
LOG(WARNING) << "Cannot get EFI properties";
if (properties != nullptr) {
CFRelease(properties);
}
return;
}

r["boot_uuid"] = getIOKitProperty(properties, "boot-uuid");
CFRelease(properties);
}

static inline void genAppleCoprocessorVersion(Row& r) {
auto asoc = IORegistryEntryFromPath(kIOMasterPortDefault,
kIODeviceTreePlane kIODeviceEfiPath_);
if (asoc == MACH_PORT_NULL) {
LOG(WARNING) << "Cannot open EFI Device Tree";
return;
}

CFMutableDictionaryRef properties = nullptr;
auto kr = IORegistryEntryCreateCFProperties(
asoc, &properties, kCFAllocatorDefault, kNilOptions);
IOObjectRelease(asoc);

if (kr != KERN_SUCCESS) {
LOG(WARNING) << "Cannot get EFI properties";
if (properties != nullptr) {
CFRelease(properties);
}
return;
}

if (CFDictionaryContainsKey(properties,
CFSTR(kAppleCoprocessorVersionKey_))) {
auto version_data = (CFDataRef)CFDictionaryGetValue(
properties, CFSTR(kAppleCoprocessorVersionKey_));
auto range = CFRangeMake(0, CFDataGetLength(version_data));

auto buffer = std::vector<unsigned char>(range.length + 1, 0);
CFDataGetBytes(version_data, range, &buffer[0]);

uint32_t version = 0;
memcpy(&version, buffer.data(), sizeof(uint32_t));
r["coprocessor_version"] = (kCoprocessorVersions.count(version) > 0)
? kCoprocessorVersions.at(version)
: "unknown";
}
CFRelease(properties);
}

QueryData genIBridgeInfo(QueryContext& context) {
QueryData results;
Row r;

genAppleCoprocessorVersion(r);
genBootUuid(r);

auto eos = IOServiceNameMatching(kEmbeddedOSClass_);
if (eos == nullptr) {
LOG(WARNING)
<< "EmbeddedOS class not found. Perhaps this mac doesn't have T* chip";
return results;
}

auto service = IOServiceGetMatchingService(kIOMasterPortDefault, eos);
CFMutableDictionaryRef properties = nullptr;
auto kr = IORegistryEntryCreateCFProperties(
service, &properties, kCFAllocatorDefault, kNilOptions);
IOObjectRelease(service);

if (kr != KERN_SUCCESS) {
LOG(WARNING) << "Cannot get EmbeddedOS properties";
if (properties != nullptr) {
CFRelease(properties);
}
return results;
}

r["unique_chip_id"] = getIOKitProperty(properties, "DeviceUniqueChipID");
r["firmware_version"] = getIOKitProperty(properties, "DeviceBuildVersion");

CFRelease(properties);

results.push_back(std::move(r));
return results;
}
} // namespace tables
} // namespace osquery
4 changes: 4 additions & 0 deletions specs/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ osquery_gentable_cxx_library(
"darwin/homebrew_packages.table",
"macos",
),
(
"darwin/ibridge_info.table",
"macos",
),
(
"darwin/iokit_devicetree.table",
"macos",
Expand Down
1 change: 1 addition & 0 deletions specs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ function(generateNativeTables)
"darwin/gatekeeper.table:macos"
"darwin/gatekeeper_approved_apps.table:macos"
"darwin/homebrew_packages.table:macos"
"darwin/ibridge_info.table:macos"
"darwin/iokit_devicetree.table:macos"
"darwin/iokit_registry.table:macos"
"darwin/kernel_extensions.table:macos"
Expand Down
10 changes: 10 additions & 0 deletions specs/darwin/ibridge_info.table
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
table_name("ibridge_info")
description("Information about the Apple iBridge hardware controller.")
schema([
Column("boot_uuid", TEXT, "Boot UUID of the iBridge controller"),
Column("coprocessor_version", TEXT, "The manufacturer and chip version"),
Column("firmware_version", TEXT, "The build version of the firmware"),
Column("unique_chip_id", TEXT, "Unique id of the iBridge controller"),
])
attributes(cacheable=True)
implementation("system/ibridge@genIBridgeInfo")
1 change: 1 addition & 0 deletions tests/integration/tables/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ osquery_cxx_test(
"gatekeeper.cpp",
"gatekeeper_approved_apps.cpp",
"homebrew_packages.cpp",
"ibridge.cpp",
"iokit_devicetree.cpp",
"iokit_registry.cpp",
"kernel_extensions.cpp",
Expand Down
1 change: 1 addition & 0 deletions tests/integration/tables/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ function(generateTestsIntegrationTablesTestsTest)
gatekeeper.cpp
gatekeeper_approved_apps.cpp
homebrew_packages.cpp
ibridge.cpp
iokit_devicetree.cpp
iokit_registry.cpp
kernel_extensions.cpp
Expand Down
39 changes: 39 additions & 0 deletions tests/integration/tables/ibridge.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* This source code is licensed in accordance with the terms specified in
* the LICENSE file found in the root directory of this source tree.
*/

// Sanity check integration test for ibridge
// Spec file: specs/darwin/ibridge_info.table

#include <osquery/logger.h>
#include <osquery/tests/integration/tables/helper.h>

namespace osquery {
namespace table_tests {

class IBridgeTest : public testing::Test {
protected:
void SetUp() override {
setUpEnvironment();
}
};

TEST_F(IBridgeTest, test_sanity) {
auto rows = execute_query("select * from ibridge_info");
if (rows.empty()) {
VLOG(1) << "Empty result for table: ibridge, skipping test";
} else {
ASSERT_EQ(rows.size(), 1ul);
ValidatatioMap validation_map = {
{"boot_uuid", NormalType},
{"coprocessor_version", NonEmptyString},
{"firmware_version", NonEmptyString},
{"unique_chip_id", NonEmptyString},
};
validate_rows(rows, validation_map);
}
}

} // namespace table_tests
} // namespace osquery

0 comments on commit d9fdc5b

Please sign in to comment.