Blame SOURCES/openscap-1.3.2-canonical_path_in_rpmverifyfile_probe.patch

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