|
|
d7b4b6 |
From 3b269a5e6d0901adc58ce27b9eae51deba679788 Mon Sep 17 00:00:00 2001
|
|
|
d7b4b6 |
From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= <jcerny@redhat.com>
|
|
|
d7b4b6 |
Date: Wed, 23 Oct 2019 17:30:19 +0200
|
|
|
d7b4b6 |
Subject: [PATCH] Use and return canonical paths in rpmverifyfile probe
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
This is done to prevent false positives in implementation of rules
|
|
|
d7b4b6 |
file_permissions_unauthorized_suid and
|
|
|
d7b4b6 |
file_permissions_unauthorized_sgid proposed in ComplianceAsCode
|
|
|
d7b4b6 |
in https://github.com/ComplianceAsCode/content/pull/4648
|
|
|
d7b4b6 |
caused by inconsistent symlink usage in rpmdb.
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
Also improves logic when an exact file path is defined in
|
|
|
d7b4b6 |
rpmverifyfile_object we don't have to iterate over all RPMs in the
|
|
|
d7b4b6 |
rpmdb but we query the rpmdb directly.
|
|
|
d7b4b6 |
---
|
|
|
d7b4b6 |
src/OVAL/probes/unix/linux/rpmverifyfile.c | 45 ++++++++++++++++------
|
|
|
d7b4b6 |
1 file changed, 34 insertions(+), 11 deletions(-)
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
diff --git a/src/OVAL/probes/unix/linux/rpmverifyfile.c b/src/OVAL/probes/unix/linux/rpmverifyfile.c
|
|
|
d7b4b6 |
index c13e3a629..e17f1612b 100644
|
|
|
d7b4b6 |
--- a/src/OVAL/probes/unix/linux/rpmverifyfile.c
|
|
|
d7b4b6 |
+++ b/src/OVAL/probes/unix/linux/rpmverifyfile.c
|
|
|
d7b4b6 |
@@ -137,6 +137,7 @@ static int rpmverify_collect(probe_ctx *ctx,
|
|
|
d7b4b6 |
Header pkgh;
|
|
|
d7b4b6 |
pcre *re = NULL;
|
|
|
d7b4b6 |
int ret = -1;
|
|
|
d7b4b6 |
+ char *file_realpath = NULL;
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
/* pre-compile regex if needed */
|
|
|
d7b4b6 |
if (file_op == OVAL_OPERATION_PATTERN_MATCH) {
|
|
|
d7b4b6 |
@@ -153,7 +154,16 @@ static int rpmverify_collect(probe_ctx *ctx,
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
RPMVERIFY_LOCK;
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
- match = rpmtsInitIterator (g_rpm.rpmts, RPMDBI_PACKAGES, NULL, 0);
|
|
|
d7b4b6 |
+ if (file != NULL && file_op == OVAL_OPERATION_EQUALS) {
|
|
|
d7b4b6 |
+ /*
|
|
|
d7b4b6 |
+ * When we know the exact file path we look for, we don't need to
|
|
|
d7b4b6 |
+ * filter all RPM packages, but we can ask the rpmdb directly for
|
|
|
d7b4b6 |
+ * the package which provides this file, similar to `rpm -q -f`.
|
|
|
d7b4b6 |
+ */
|
|
|
d7b4b6 |
+ match = rpmtsInitIterator(g_rpm.rpmts, RPMDBI_INSTFILENAMES, file, 0);
|
|
|
d7b4b6 |
+ } else {
|
|
|
d7b4b6 |
+ match = rpmtsInitIterator(g_rpm.rpmts, RPMDBI_PACKAGES, NULL, 0);
|
|
|
d7b4b6 |
+ }
|
|
|
d7b4b6 |
if (match == NULL) {
|
|
|
d7b4b6 |
ret = 0;
|
|
|
d7b4b6 |
goto ret;
|
|
|
d7b4b6 |
@@ -183,6 +193,8 @@ static int rpmverify_collect(probe_ctx *ctx,
|
|
|
d7b4b6 |
assume_d(RPMTAG_BASENAMES != 0, -1);
|
|
|
d7b4b6 |
assume_d(RPMTAG_DIRNAMES != 0, -1);
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
+ file_realpath = realpath(file, NULL);
|
|
|
d7b4b6 |
+
|
|
|
d7b4b6 |
while ((pkgh = rpmdbNextIterator (match)) != NULL) {
|
|
|
d7b4b6 |
SEXP_t *ent;
|
|
|
d7b4b6 |
rpmfi fi;
|
|
|
d7b4b6 |
@@ -190,6 +202,8 @@ static int rpmverify_collect(probe_ctx *ctx,
|
|
|
d7b4b6 |
struct rpmverify_res res;
|
|
|
d7b4b6 |
errmsg_t rpmerr;
|
|
|
d7b4b6 |
int i;
|
|
|
d7b4b6 |
+ const char *current_file;
|
|
|
d7b4b6 |
+ char *current_file_realpath;
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
/*
|
|
|
d7b4b6 |
+SEXP_t *probe_ent_from_cstr(const char *name, oval_datatype_t type,
|
|
|
d7b4b6 |
@@ -231,43 +245,51 @@ static int rpmverify_collect(probe_ctx *ctx,
|
|
|
d7b4b6 |
fi = rpmfiNew(g_rpm.rpmts, pkgh, tag[i], 1);
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
while (rpmfiNext(fi) != -1) {
|
|
|
d7b4b6 |
- res.file = oscap_strdup(rpmfiFN(fi));
|
|
|
d7b4b6 |
+ current_file = rpmfiFN(fi);
|
|
|
d7b4b6 |
+ current_file_realpath = realpath(current_file, NULL);
|
|
|
d7b4b6 |
res.fflags = rpmfiFFlags(fi);
|
|
|
d7b4b6 |
res.oflags = omit;
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
if (((res.fflags & RPMFILE_CONFIG) && (flags & RPMVERIFY_SKIP_CONFIG)) ||
|
|
|
d7b4b6 |
((res.fflags & RPMFILE_GHOST) && (flags & RPMVERIFY_SKIP_GHOST))) {
|
|
|
d7b4b6 |
- free(res.file);
|
|
|
d7b4b6 |
+ free(current_file_realpath);
|
|
|
d7b4b6 |
continue;
|
|
|
d7b4b6 |
}
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
switch(file_op) {
|
|
|
d7b4b6 |
case OVAL_OPERATION_EQUALS:
|
|
|
d7b4b6 |
- if (strcmp(res.file, file) != 0) {
|
|
|
d7b4b6 |
- free(res.file);
|
|
|
d7b4b6 |
+ if (strcmp(current_file, file) != 0 &&
|
|
|
d7b4b6 |
+ current_file_realpath && file_realpath &&
|
|
|
d7b4b6 |
+ strcmp(current_file_realpath, file_realpath) != 0) {
|
|
|
d7b4b6 |
+ free(current_file_realpath);
|
|
|
d7b4b6 |
continue;
|
|
|
d7b4b6 |
}
|
|
|
d7b4b6 |
+ res.file = oscap_strdup(file);
|
|
|
d7b4b6 |
break;
|
|
|
d7b4b6 |
case OVAL_OPERATION_NOT_EQUAL:
|
|
|
d7b4b6 |
- if (strcmp(res.file, file) == 0) {
|
|
|
d7b4b6 |
- free(res.file);
|
|
|
d7b4b6 |
+ if (strcmp(current_file, file) == 0 ||
|
|
|
d7b4b6 |
+ (current_file_realpath && file_realpath &&
|
|
|
d7b4b6 |
+ strcmp(current_file_realpath, file_realpath) == 0)) {
|
|
|
d7b4b6 |
+ free(current_file_realpath);
|
|
|
d7b4b6 |
continue;
|
|
|
d7b4b6 |
}
|
|
|
d7b4b6 |
+ res.file = current_file_realpath ? current_file_realpath : strdup(current_file);
|
|
|
d7b4b6 |
break;
|
|
|
d7b4b6 |
case OVAL_OPERATION_PATTERN_MATCH:
|
|
|
d7b4b6 |
- ret = pcre_exec(re, NULL, res.file, strlen(res.file), 0, 0, NULL, 0);
|
|
|
d7b4b6 |
+ ret = pcre_exec(re, NULL, current_file, strlen(current_file), 0, 0, NULL, 0);
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
switch(ret) {
|
|
|
d7b4b6 |
case 0: /* match */
|
|
|
d7b4b6 |
+ res.file = strdup(current_file);
|
|
|
d7b4b6 |
break;
|
|
|
d7b4b6 |
case -1:
|
|
|
d7b4b6 |
/* mismatch */
|
|
|
d7b4b6 |
- free(res.file);
|
|
|
d7b4b6 |
+ free(current_file_realpath);
|
|
|
d7b4b6 |
continue;
|
|
|
d7b4b6 |
default:
|
|
|
d7b4b6 |
dE("pcre_exec() failed!");
|
|
|
d7b4b6 |
ret = -1;
|
|
|
d7b4b6 |
- free(res.file);
|
|
|
d7b4b6 |
+ free(current_file_realpath);
|
|
|
d7b4b6 |
goto ret;
|
|
|
d7b4b6 |
}
|
|
|
d7b4b6 |
break;
|
|
|
d7b4b6 |
@@ -275,7 +297,7 @@ static int rpmverify_collect(probe_ctx *ctx,
|
|
|
d7b4b6 |
/* unsupported operation */
|
|
|
d7b4b6 |
dE("Operation \"%d\" on `filepath' not supported", file_op);
|
|
|
d7b4b6 |
ret = -1;
|
|
|
d7b4b6 |
- free(res.file);
|
|
|
d7b4b6 |
+ free(current_file_realpath);
|
|
|
d7b4b6 |
goto ret;
|
|
|
d7b4b6 |
}
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
@@ -301,6 +323,7 @@ ret:
|
|
|
d7b4b6 |
pcre_free(re);
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
RPMVERIFY_UNLOCK;
|
|
|
d7b4b6 |
+ free(file_realpath);
|
|
|
d7b4b6 |
return (ret);
|
|
|
d7b4b6 |
}
|
|
|
d7b4b6 |
|
|
|
d7b4b6 |
--
|
|
|
d7b4b6 |
2.21.0
|
|
|
d7b4b6 |
|