-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update linux block_device and disk_encryption source data to simple sysfs implementation #8182
base: master
Are you sure you want to change the base?
Changes from all commits
e2e6e59
94a5b58
3ef2df3
d8a539c
fb654fd
738eee6
f524098
5d19fc9
5eee8db
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,15 +7,11 @@ | |
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only) | ||
*/ | ||
|
||
#include <unistd.h> | ||
|
||
#include <vector> | ||
|
||
#include <osquery/core/core.h> | ||
#include <osquery/core/tables.h> | ||
#include <osquery/logger/logger.h> | ||
#include <osquery/sql/sql.h> | ||
#include <osquery/utils/conversions/join.h> | ||
#include <osquery/utils/linux/block_device_enumeration.h> | ||
|
||
extern "C" { | ||
#include <libcryptsetup.h> | ||
|
@@ -29,19 +25,15 @@ const std::string kEncryptionStatusNotEncrypted = "not encrypted"; | |
|
||
namespace osquery { | ||
namespace tables { | ||
void genFDEStatusForBlockDevice(const Row& block_device, | ||
std::map<std::string, Row>& block_devices, | ||
std::map<std::string, Row>& encrypted_rows) { | ||
const auto name = block_device.at("name"); | ||
const auto parent_name = | ||
(block_device.count("parent") > 0 ? block_device.at("parent") : ""); | ||
|
||
void genFDEStatusForBlockDevice(const BlockDevice& block_device, | ||
std::set<BlockDevice>& block_devices, | ||
std::map<std::string, Row>& encryption_status) { | ||
Row r; | ||
r["name"] = name; | ||
r["uuid"] = (block_device.count("uuid") > 0) ? block_device.at("uuid") : ""; | ||
r["name"] = block_device.name; | ||
r["uuid"] = block_device.uuid; | ||
|
||
struct crypt_device* cd = nullptr; | ||
auto ci = crypt_status(cd, name.c_str()); | ||
auto ci = crypt_status(cd, r["name"].c_str()); | ||
|
||
switch (ci) { | ||
case CRYPT_ACTIVE: | ||
|
@@ -50,15 +42,16 @@ void genFDEStatusForBlockDevice(const Row& block_device, | |
r["encryption_status"] = kEncryptionStatusEncrypted; | ||
r["type"] = ""; | ||
|
||
auto crypt_init = crypt_init_by_name_and_header(&cd, name.c_str(), nullptr); | ||
auto crypt_init = | ||
crypt_init_by_name_and_header(&cd, r["name"].c_str(), nullptr); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
if (crypt_init < 0) { | ||
VLOG(1) << "Unable to initialize crypt device for " << name; | ||
VLOG(1) << "Unable to initialize crypt device for " << r["name"]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
break; | ||
} | ||
|
||
struct crypt_active_device cad; | ||
if (crypt_get_active_device(cd, name.c_str(), &cad) < 0) { | ||
VLOG(1) << "Unable to get active device for " << name; | ||
if (crypt_get_active_device(cd, r["name"].c_str(), &cad) < 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
VLOG(1) << "Unable to get active device for " << r["name"]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
break; | ||
} | ||
|
||
|
@@ -83,39 +76,33 @@ void genFDEStatusForBlockDevice(const Row& block_device, | |
r["type"] = osquery::join(items, "-"); | ||
break; | ||
} | ||
// If there's no good crypt status, use the parent device's crypt status. | ||
default: | ||
// If there is no parent, we are likely at the root of the block device | ||
// tree. Since no good crypt status has been found, we set the empty status | ||
// and exit. All children of this block device will inherit this status if | ||
// they aren't encrypted. | ||
if (parent_name.empty()) { | ||
r["encryption_status"] = kEncryptionStatusNotEncrypted; | ||
r["encrypted"] = "0"; | ||
r["type"] = ""; | ||
break; | ||
} | ||
r["encryption_status"] = kEncryptionStatusNotEncrypted; | ||
r["encrypted"] = "0"; | ||
r["type"] = ""; | ||
|
||
// If there is a parent, let's generate and use its crypt status for this | ||
// device. | ||
if (!encrypted_rows.count(parent_name)) { | ||
genFDEStatusForBlockDevice( | ||
block_devices[parent_name], block_devices, encrypted_rows); | ||
// Set crypt status from parent block device. | ||
if (!block_device.parent.empty()) { | ||
// Since `genFDEStatusForBlockDevice` is recursive, ensure no duplicates. | ||
if (!encryption_status.count(block_device.parent)) { | ||
if (auto parent = block_devices.find(block_device.parent); | ||
parent != block_devices.end()) { | ||
genFDEStatusForBlockDevice(*parent, block_devices, encryption_status); | ||
} | ||
} | ||
|
||
auto parent_row = encryption_status[block_device.parent]; | ||
r["encryption_status"] = parent_row["encryption_status"]; | ||
r["encrypted"] = parent_row["encrypted"]; | ||
r["type"] = parent_row["type"]; | ||
} | ||
|
||
// The recursive calls return back, and each child device takes the | ||
// encryption values of their parent. | ||
auto parent_row = encrypted_rows[parent_name]; | ||
r["encryption_status"] = parent_row["encryption_status"]; | ||
r["encrypted"] = parent_row["encrypted"]; | ||
r["type"] = parent_row["type"]; | ||
} | ||
|
||
encrypted_rows[name] = r; | ||
|
||
if (cd != nullptr) { | ||
crypt_free(cd); | ||
} | ||
|
||
encryption_status[r["name"]] = r; | ||
} | ||
|
||
QueryData genFDEStatus(QueryContext& context) { | ||
|
@@ -126,32 +113,18 @@ QueryData genFDEStatus(QueryContext& context) { | |
return results; | ||
} | ||
|
||
// When a block device doesn't have sufficient crypt status, it needs to be | ||
// able to inherit the crypt status of its parent. | ||
// To do this, we utilize `block_devices` and `encrypted_rows` to cache block | ||
// devices at two different points. The first is when it's queried, and the | ||
// second is after setting crypt status. This helps us avoid O(N^2) issues. | ||
// We can also skip sorting nodes by using recursion. | ||
std::map<std::string, Row> block_devices; | ||
std::map<std::string, Row> encrypted_rows; | ||
|
||
// Ultimately we want to have proper query context here. There are underlying | ||
// issues with udev child->parent relationship on LVM volumes. See #8152. | ||
auto data = SQL::selectAllFrom("block_devices"); | ||
for (const auto& row : data) { | ||
if (row.count("name") > 0) { | ||
block_devices[row.at("name")] = row; | ||
} | ||
} | ||
std::map<std::string, Row> encryption_status; | ||
auto query_context = context.constraints.find("name")->second.getAll(EQUALS); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would just access the value with |
||
auto block_devices = enumerateBlockDevices(query_context, true); | ||
|
||
// Generate and add an encryption row result for each queried block device. | ||
for (const auto& pair : block_devices) { | ||
if (!encrypted_rows.count(pair.first)) { | ||
genFDEStatusForBlockDevice(pair.second, block_devices, encrypted_rows); | ||
for (const auto& block_device : block_devices) { | ||
// Since `genFDEStatusForBlockDevice` is recursive, ensure no duplicates. | ||
if (!encryption_status.count(block_device.name)) { | ||
genFDEStatusForBlockDevice( | ||
block_device, block_devices, encryption_status); | ||
} | ||
|
||
// Copy encrypted rows back to results. | ||
results.push_back(encrypted_rows[pair.first]); | ||
results.push_back(encryption_status[block_device.name]); | ||
} | ||
|
||
return results; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nit: for performance, prefer using the value you have copied from (
block_device.name
) instead of fetching it back from thestd::map
.