Skip to content

Commit 5fe4bd4

Browse files
authored
Optimize rpm_packages and rpm_package_files use of query context (osquery#8537)
Currently the RPM table is being generated by initializing the RPM db with all packages, or a single package by name with query context. I've changed this table to start using `rpmdbSetIteratorRE` with string compare, by iterating through all values given in query context, and adding those regex patterns to the RPM iterator selector. RPM API `rpmdbSetIteratorRE`: https://ftp.osuosl.org/pub/rpm/api/4.4.2.2/group__rpmdb.html#g9f84dbc47d1d432f4ffe83b713fb47c9 This allows the table to generate results with all values from query context at once. I've confirmed that the columns can support these changes by querying the tables with an IN constraint on the optimized columns. I validated the expected results by comparing returned values from osquery 5.13.1 (before IN optimization existed), 5.14.1, and 5.14.1 containing these spec file changes. With each query I included a NULL, '' (empty string), and some non-existent values in my IN constraint. Tests were ran on CentOS Linux release 7.9.2009 (Core)
1 parent 080833e commit 5fe4bd4

File tree

3 files changed

+25
-12
lines changed

3 files changed

+25
-12
lines changed

osquery/tables/system/linux/rpm_packages.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,18 @@ QueryData genRpmPackagesImpl(QueryContext& context, Logger& logger) {
145145
}
146146

147147
rpmts ts = rpmtsCreate();
148-
rpmdbMatchIterator matches;
148+
rpmdbMatchIterator matches = rpmtsInitIterator(ts, RPMTAG_NAME, nullptr, 0);
149+
149150
if (context.constraints["name"].exists(EQUALS)) {
150-
auto name = (*context.constraints["name"].getAll(EQUALS).begin());
151-
matches = rpmtsInitIterator(ts, RPMTAG_NAME, name.c_str(), name.size());
152-
} else {
153-
matches = rpmtsInitIterator(ts, RPMTAG_NAME, nullptr, 0);
151+
auto names = context.constraints["name"].getAll(EQUALS);
152+
for (const auto& name : names) {
153+
// Limit RPM iterator to constraint values
154+
if (rpmdbSetIteratorRE(
155+
matches, RPMTAG_NAME, RPMMIRE_STRCMP, name.c_str()) != 0) {
156+
logger.vlog(
157+
1, "Cannot add pattern: (" + name + ") to RPM iterator selector");
158+
}
159+
}
154160
}
155161

156162
Header header;
@@ -210,12 +216,19 @@ void genRpmPackageFiles(RowYield& yield, QueryContext& context) {
210216
}
211217

212218
rpmts ts = rpmtsCreate();
213-
rpmdbMatchIterator matches;
219+
rpmdbMatchIterator matches = rpmtsInitIterator(ts, RPMTAG_NAME, nullptr, 0);
220+
214221
if (context.constraints["package"].exists(EQUALS)) {
215-
auto name = (*context.constraints["package"].getAll(EQUALS).begin());
216-
matches = rpmtsInitIterator(ts, RPMTAG_NAME, name.c_str(), name.size());
217-
} else {
218-
matches = rpmtsInitIterator(ts, RPMTAG_NAME, nullptr, 0);
222+
auto packages = context.constraints["package"].getAll(EQUALS);
223+
for (const auto& package : packages) {
224+
// Limit RPM iterator to constraint values
225+
if (rpmdbSetIteratorRE(
226+
matches, RPMTAG_NAME, RPMMIRE_STRCMP, package.c_str()) != 0) {
227+
logger.vlog(
228+
1,
229+
"Cannot add pattern: (" + package + ") to RPM iterator selector");
230+
}
231+
}
219232
}
220233

221234
Header header;

specs/linux/rpm_package_files.table

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
table_name("rpm_package_files")
22
description("RPM packages that are currently installed on the host system.")
33
schema([
4-
Column("package", TEXT, "RPM package name", index=True),
4+
Column("package", TEXT, "RPM package name", index=True, optimized=True),
55
Column("path", TEXT, "File path within the package", index=True),
66
Column("username", TEXT, "File default username from info DB"),
77
Column("groupname", TEXT, "File default groupname from info DB"),

specs/linux/rpm_packages.table

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
table_name("rpm_packages")
22
description("RPM packages that are currently installed on the host system.")
33
schema([
4-
Column("name", TEXT, "RPM package name", index=True),
4+
Column("name", TEXT, "RPM package name", index=True, optimized=True),
55
Column("version", TEXT, "Package version" ,index=True, collate="version_rhel"),
66
Column("release", TEXT, "Package release", index=True),
77
Column("source", TEXT, "Source RPM package name (optional)"),

0 commit comments

Comments
 (0)