Blame SOURCES/openscap-1.3.2-canonical_path_in_rpmverifyfile_probe.patch

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