Blame SOURCES/openscap-1.3.7-PR-1846-file-permissions.patch

4ef38b
From d000375944e8ec965486cf019c3f75f4c06a4e10 Mon Sep 17 00:00:00 2001
4ef38b
From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= <jcerny@redhat.com>
4ef38b
Date: Thu, 3 Feb 2022 14:14:21 +0100
4ef38b
Subject: [PATCH 1/5] Prevent file permissions errors
4ef38b
4ef38b
The sysctl setting `fs.protected_regular` doesn't allow `O_CREAT` open
4ef38b
on regular files that we don't own in world writable sticky directories
4ef38b
(think `/tmp`). This causes permission denied error when writing HTML
4ef38b
report to a temporary files created by the `mktemp` command executed as
4ef38b
a normal user and then executing `sudo oscap`.
4ef38b
4ef38b
See https://bugzilla.redhat.com/show_bug.cgi?id=2048571
4ef38b
4ef38b
If OpenSCAP fails to open the file because of permissions, it will retry
4ef38b
to open the file without O_CREAT flag.
4ef38b
4ef38b
This fixes only creation of the HTML report using the `--report` option,
4ef38b
We will have to create a similar patch also for other output options
4ef38b
such as `--results` or `--results-arf`.
4ef38b
---
4ef38b
 src/source/xslt.c | 40 ++++++++++++++++++++++++++++------------
4ef38b
 1 file changed, 28 insertions(+), 12 deletions(-)
4ef38b
4ef38b
diff --git a/src/source/xslt.c b/src/source/xslt.c
4ef38b
index 24c4c46e9..7a3a3f328 100644
4ef38b
--- a/src/source/xslt.c
4ef38b
+++ b/src/source/xslt.c
4ef38b
@@ -22,6 +22,7 @@
4ef38b
 #include <config.h>
4ef38b
 #endif
4ef38b
 
4ef38b
+#include <fcntl.h>
4ef38b
 #include <libxml/parser.h>
4ef38b
 #include <libxslt/xslt.h>
4ef38b
 #include <libxslt/xsltInternals.h>
4ef38b
@@ -82,23 +83,38 @@ static int xccdf_ns_xslt_workaround(xmlDocPtr doc, xmlNodePtr node)
4ef38b
 
4ef38b
 static inline int save_stylesheet_result_to_file(xmlDoc *resulting_doc, xsltStylesheet *stylesheet, const char *outfile)
4ef38b
 {
4ef38b
-	FILE *f = NULL;
4ef38b
-	if (outfile)
4ef38b
-		f = fopen(outfile, "w");
4ef38b
-	else
4ef38b
-		f = stdout;
4ef38b
-
4ef38b
-	if (f == NULL) {
4ef38b
-		oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not open output file '%s'", outfile ? outfile : "stdout");
4ef38b
-		return -1;
4ef38b
+	int fd = STDOUT_FILENO;
4ef38b
+	if (outfile) {
4ef38b
+#ifdef OS_WINDOWS
4ef38b
+		fd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE);
4ef38b
+#else
4ef38b
+		fd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
4ef38b
+#endif
4ef38b
+		if (fd == -1) {
4ef38b
+			if (errno == EACCES) {
4ef38b
+				/* File already exists and we aren't allowed to create a new one
4ef38b
+				with the same name */
4ef38b
+#ifdef OS_WINDOWS
4ef38b
+				fd = open(outfile, O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE);
4ef38b
+#else
4ef38b
+				fd = open(outfile, O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
4ef38b
+#endif
4ef38b
+			}
4ef38b
+			if (fd == -1) {
4ef38b
+				oscap_seterr(OSCAP_EFAMILY_OSCAP,
4ef38b
+					"Could not open output file '%s': %s",
4ef38b
+					outfile, strerror(errno));
4ef38b
+				return -1;
4ef38b
+			}
4ef38b
+		}
4ef38b
 	}
4ef38b
 
4ef38b
-	int ret = xsltSaveResultToFile(f, resulting_doc, stylesheet);
4ef38b
+	int ret = xsltSaveResultToFd(fd, resulting_doc, stylesheet);
4ef38b
 	if (ret < 0) {
4ef38b
 		oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not save result document");
4ef38b
 	}
4ef38b
-	if (outfile && f)
4ef38b
-		fclose(f);
4ef38b
+	if (fd != STDOUT_FILENO)
4ef38b
+		close(fd);
4ef38b
 	return ret;
4ef38b
 }
4ef38b
 
4ef38b
4ef38b
From ad3c89a72c0aeb6c6ceab0873c51b07deba45701 Mon Sep 17 00:00:00 2001
4ef38b
From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= <jcerny@redhat.com>
4ef38b
Date: Thu, 3 Feb 2022 15:08:52 +0100
4ef38b
Subject: [PATCH 2/5] Prevent permission access issues
4ef38b
4ef38b
Very similar to the previous commit, but this time for saving XML
4ef38b
documents.
4ef38b
---
4ef38b
 src/common/elements.c | 19 ++++++++++++++++---
4ef38b
 1 file changed, 16 insertions(+), 3 deletions(-)
4ef38b
4ef38b
diff --git a/src/common/elements.c b/src/common/elements.c
4ef38b
index e512f5e3d..d0d9170f1 100644
4ef38b
--- a/src/common/elements.c
4ef38b
+++ b/src/common/elements.c
4ef38b
@@ -233,9 +233,22 @@ int oscap_xml_save_filename(const char *filename, xmlDocPtr doc)
4ef38b
 		int fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY,
4ef38b
 				S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
4ef38b
 #endif
4ef38b
-		if (fd < 0) {
4ef38b
-			oscap_seterr(OSCAP_EFAMILY_GLIBC, "%s '%s'", strerror(errno), filename);
4ef38b
-			return -1;
4ef38b
+		if (fd == -1) {
4ef38b
+			if (errno == EACCES) {
4ef38b
+				/* File already exists and we aren't allowed to create a new one
4ef38b
+				with the same name */
4ef38b
+#ifdef OS_WINDOWS
4ef38b
+				fd = open(filename, O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE);
4ef38b
+#else
4ef38b
+				fd = open(filename, O_WRONLY|O_TRUNC,
4ef38b
+						S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
4ef38b
+#endif
4ef38b
+			}
4ef38b
+			if (fd == -1) {
4ef38b
+				oscap_seterr(OSCAP_EFAMILY_GLIBC,
4ef38b
+						"%s '%s'", strerror(errno), filename);
4ef38b
+				return -1;
4ef38b
+			}
4ef38b
 		}
4ef38b
 
4ef38b
 		buff = xmlOutputBufferCreateFd(fd, NULL);
4ef38b
4ef38b
From b2dc90fb80419e30d05676660a2069050693078d Mon Sep 17 00:00:00 2001
4ef38b
From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= <jcerny@redhat.com>
4ef38b
Date: Thu, 3 Feb 2022 15:37:31 +0100
4ef38b
Subject: [PATCH 3/5] Add a missing include
4ef38b
4ef38b
---
4ef38b
 src/source/xslt.c | 2 ++
4ef38b
 1 file changed, 2 insertions(+)
4ef38b
4ef38b
diff --git a/src/source/xslt.c b/src/source/xslt.c
4ef38b
index 7a3a3f328..a763d6b59 100644
4ef38b
--- a/src/source/xslt.c
4ef38b
+++ b/src/source/xslt.c
4ef38b
@@ -30,6 +30,8 @@
4ef38b
 #include <libxslt/xsltutils.h>
4ef38b
 #include <libexslt/exslt.h>
4ef38b
 #include <string.h>
4ef38b
+#include <sys/stat.h>
4ef38b
+
4ef38b
 #ifdef OS_WINDOWS
4ef38b
 #include <io.h>
4ef38b
 #else
4ef38b
4ef38b
From 13ff98bd744ea542bc782e388fdedb5b7f66e54b Mon Sep 17 00:00:00 2001
4ef38b
From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= <jcerny@redhat.com>
4ef38b
Date: Thu, 3 Feb 2022 16:22:56 +0100
4ef38b
Subject: [PATCH 4/5] Fix missing STDOUT_FILENO on Windows
4ef38b
4ef38b
---
4ef38b
 src/source/xslt.c | 8 ++++++++
4ef38b
 1 file changed, 8 insertions(+)
4ef38b
4ef38b
diff --git a/src/source/xslt.c b/src/source/xslt.c
4ef38b
index a763d6b59..799d5170d 100644
4ef38b
--- a/src/source/xslt.c
4ef38b
+++ b/src/source/xslt.c
4ef38b
@@ -85,7 +85,11 @@ static int xccdf_ns_xslt_workaround(xmlDocPtr doc, xmlNodePtr node)
4ef38b
 
4ef38b
 static inline int save_stylesheet_result_to_file(xmlDoc *resulting_doc, xsltStylesheet *stylesheet, const char *outfile)
4ef38b
 {
4ef38b
+#ifdef OS_WINDOWS
4ef38b
+	int fd = _fileno(stdout);
4ef38b
+#else
4ef38b
 	int fd = STDOUT_FILENO;
4ef38b
+#endif
4ef38b
 	if (outfile) {
4ef38b
 #ifdef OS_WINDOWS
4ef38b
 		fd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE);
4ef38b
@@ -115,7 +119,11 @@ static inline int save_stylesheet_result_to_file(xmlDoc *resulting_doc, xsltStyl
4ef38b
 	if (ret < 0) {
4ef38b
 		oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not save result document");
4ef38b
 	}
4ef38b
+#ifdef OS_WINDOWS
4ef38b
+	if (fd != _fileno(stdout))
4ef38b
+#else
4ef38b
 	if (fd != STDOUT_FILENO)
4ef38b
+#endif
4ef38b
 		close(fd);
4ef38b
 	return ret;
4ef38b
 }
4ef38b
4ef38b
From f00831513ec2cdde13c12820ff6cc0eef8105c65 Mon Sep 17 00:00:00 2001
4ef38b
From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= <jcerny@redhat.com>
4ef38b
Date: Fri, 4 Feb 2022 12:19:50 +0100
4ef38b
Subject: [PATCH 5/5] Refactor: extract function oscap_open_writable
4ef38b
4ef38b
---
4ef38b
 src/common/elements.c                         | 26 ++--------------
4ef38b
 src/common/util.c                             | 31 +++++++++++++++++++
4ef38b
 src/common/util.h                             | 14 ++++++++-
4ef38b
 src/source/xslt.c                             | 27 ++--------------
4ef38b
 tests/API/XCCDF/unittests/CMakeLists.txt      |  2 ++
4ef38b
 tests/API/XCCDF/unittests/test_oscap_common.c |  1 +
4ef38b
 6 files changed, 53 insertions(+), 48 deletions(-)
4ef38b
4ef38b
diff --git a/src/common/elements.c b/src/common/elements.c
4ef38b
index d0d9170f1..de4be88f1 100644
4ef38b
--- a/src/common/elements.c
4ef38b
+++ b/src/common/elements.c
4ef38b
@@ -227,29 +227,9 @@ int oscap_xml_save_filename(const char *filename, xmlDocPtr doc)
4ef38b
 		xmlCode = xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1);
4ef38b
 	}
4ef38b
 	else {
4ef38b
-#ifdef OS_WINDOWS
4ef38b
-		int fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, S_IREAD|S_IWRITE);
4ef38b
-#else
4ef38b
-		int fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY,
4ef38b
-				S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
4ef38b
-#endif
4ef38b
-		if (fd == -1) {
4ef38b
-			if (errno == EACCES) {
4ef38b
-				/* File already exists and we aren't allowed to create a new one
4ef38b
-				with the same name */
4ef38b
-#ifdef OS_WINDOWS
4ef38b
-				fd = open(filename, O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE);
4ef38b
-#else
4ef38b
-				fd = open(filename, O_WRONLY|O_TRUNC,
4ef38b
-						S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
4ef38b
-#endif
4ef38b
-			}
4ef38b
-			if (fd == -1) {
4ef38b
-				oscap_seterr(OSCAP_EFAMILY_GLIBC,
4ef38b
-						"%s '%s'", strerror(errno), filename);
4ef38b
-				return -1;
4ef38b
-			}
4ef38b
-		}
4ef38b
+		int fd = oscap_open_writable(filename);
4ef38b
+		if (fd == -1)
4ef38b
+			return -1;
4ef38b
 
4ef38b
 		buff = xmlOutputBufferCreateFd(fd, NULL);
4ef38b
 		if (buff == NULL) {
4ef38b
diff --git a/src/common/util.c b/src/common/util.c
4ef38b
index 8f9f751e2..8ca2ad130 100644
4ef38b
--- a/src/common/util.c
4ef38b
+++ b/src/common/util.c
4ef38b
@@ -25,12 +25,14 @@
4ef38b
 #include <config.h>
4ef38b
 #endif
4ef38b
 
4ef38b
+#include <fcntl.h>
4ef38b
 #include <string.h>
4ef38b
 #include <ctype.h>
4ef38b
 #include <limits.h>
4ef38b
 #include <stdarg.h>
4ef38b
 #include <math.h>
4ef38b
 #include <pcre.h>
4ef38b
+#include <sys/stat.h>
4ef38b
 
4ef38b
 #include "util.h"
4ef38b
 #include "_error.h"
4ef38b
@@ -482,3 +484,32 @@ char *oscap_windows_error_message(unsigned long error_code)
4ef38b
 	return error_message;
4ef38b
 }
4ef38b
 #endif
4ef38b
+
4ef38b
+int oscap_open_writable(const char *filename)
4ef38b
+{
4ef38b
+#ifdef OS_WINDOWS
4ef38b
+	int fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE);
4ef38b
+#else
4ef38b
+	int fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC,
4ef38b
+			S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
4ef38b
+#endif
4ef38b
+	if (fd == -1) {
4ef38b
+		if (errno == EACCES) {
4ef38b
+			/* File already exists and we aren't allowed to create a new one
4ef38b
+			with the same name */
4ef38b
+#ifdef OS_WINDOWS
4ef38b
+			fd = open(filename, O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE);
4ef38b
+#else
4ef38b
+			fd = open(filename, O_WRONLY|O_TRUNC,
4ef38b
+					S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
4ef38b
+#endif
4ef38b
+		}
4ef38b
+		if (fd == -1) {
4ef38b
+			oscap_seterr(OSCAP_EFAMILY_OSCAP,
4ef38b
+					"Could not open output file '%s': %s",
4ef38b
+					filename, strerror(errno));
4ef38b
+			return -1;
4ef38b
+		}
4ef38b
+	}
4ef38b
+	return fd;
4ef38b
+}
4ef38b
diff --git a/src/common/util.h b/src/common/util.h
4ef38b
index c48d92a52..5712f2f0b 100644
4ef38b
--- a/src/common/util.h
4ef38b
+++ b/src/common/util.h
4ef38b
@@ -524,4 +524,16 @@ wchar_t *oscap_windows_str_to_wstr(const char *str);
4ef38b
 char *oscap_windows_error_message(unsigned long error_code);
4ef38b
 #endif
4ef38b
 
4ef38b
-#endif				/* OSCAP_UTIL_H_ */
4ef38b
+/**
4ef38b
+ * Open a file for writing.
4ef38b
+ * The main difference from fopen() is that if the file exists but its opening
4ef38b
+ * for writing fails as permission denied, it will attempt to open it again
4ef38b
+ * without the O_CREAT flag. This is useful when writing to world-writeable
4ef38b
+ * directories with sticky bit such as /tmp on systems with fs.protected_regular
4ef38b
+ * turned on.
4ef38b
+ * @param filename name of the file to be opened
4ef38b
+ * @return file descriptor or -1 on error
4ef38b
+ */
4ef38b
+int oscap_open_writable(const char *filename);
4ef38b
+
4ef38b
+#endif              /* OSCAP_UTIL_H_ */
4ef38b
diff --git a/src/source/xslt.c b/src/source/xslt.c
4ef38b
index 799d5170d..906bfabdb 100644
4ef38b
--- a/src/source/xslt.c
4ef38b
+++ b/src/source/xslt.c
4ef38b
@@ -22,7 +22,6 @@
4ef38b
 #include <config.h>
4ef38b
 #endif
4ef38b
 
4ef38b
-#include <fcntl.h>
4ef38b
 #include <libxml/parser.h>
4ef38b
 #include <libxslt/xslt.h>
4ef38b
 #include <libxslt/xsltInternals.h>
4ef38b
@@ -30,7 +29,6 @@
4ef38b
 #include <libxslt/xsltutils.h>
4ef38b
 #include <libexslt/exslt.h>
4ef38b
 #include <string.h>
4ef38b
-#include <sys/stat.h>
4ef38b
 
4ef38b
 #ifdef OS_WINDOWS
4ef38b
 #include <io.h>
4ef38b
@@ -91,29 +89,10 @@ static inline int save_stylesheet_result_to_file(xmlDoc *resulting_doc, xsltStyl
4ef38b
 	int fd = STDOUT_FILENO;
4ef38b
 #endif
4ef38b
 	if (outfile) {
4ef38b
-#ifdef OS_WINDOWS
4ef38b
-		fd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE);
4ef38b
-#else
4ef38b
-		fd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
4ef38b
-#endif
4ef38b
-		if (fd == -1) {
4ef38b
-			if (errno == EACCES) {
4ef38b
-				/* File already exists and we aren't allowed to create a new one
4ef38b
-				with the same name */
4ef38b
-#ifdef OS_WINDOWS
4ef38b
-				fd = open(outfile, O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE);
4ef38b
-#else
4ef38b
-				fd = open(outfile, O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
4ef38b
-#endif
4ef38b
-			}
4ef38b
-			if (fd == -1) {
4ef38b
-				oscap_seterr(OSCAP_EFAMILY_OSCAP,
4ef38b
-					"Could not open output file '%s': %s",
4ef38b
-					outfile, strerror(errno));
4ef38b
-				return -1;
4ef38b
-			}
4ef38b
-		}
4ef38b
+		fd = oscap_open_writable(outfile);
4ef38b
 	}
4ef38b
+	if (fd == -1)
4ef38b
+		return -1;
4ef38b
 
4ef38b
 	int ret = xsltSaveResultToFd(fd, resulting_doc, stylesheet);
4ef38b
 	if (ret < 0) {
4ef38b
diff --git a/tests/API/XCCDF/unittests/CMakeLists.txt b/tests/API/XCCDF/unittests/CMakeLists.txt
4ef38b
index 97e1ab09f..a1c7da67f 100644
4ef38b
--- a/tests/API/XCCDF/unittests/CMakeLists.txt
4ef38b
+++ b/tests/API/XCCDF/unittests/CMakeLists.txt
4ef38b
@@ -2,6 +2,8 @@ add_oscap_test_executable(test_oscap_common
4ef38b
 	"test_oscap_common.c"
4ef38b
 	${CMAKE_SOURCE_DIR}/src/common/util.c
4ef38b
 	${CMAKE_SOURCE_DIR}/src/common/list.c
4ef38b
+	${CMAKE_SOURCE_DIR}/src/common/error.c
4ef38b
+	${CMAKE_SOURCE_DIR}/src/common/err_queue.c
4ef38b
 )
4ef38b
 
4ef38b
 add_oscap_test_executable(test_xccdf_overrides
4ef38b
diff --git a/tests/API/XCCDF/unittests/test_oscap_common.c b/tests/API/XCCDF/unittests/test_oscap_common.c
4ef38b
index 26ff51d48..939ba8750 100644
4ef38b
--- a/tests/API/XCCDF/unittests/test_oscap_common.c
4ef38b
+++ b/tests/API/XCCDF/unittests/test_oscap_common.c
4ef38b
@@ -28,6 +28,7 @@
4ef38b
 #include <string.h>
4ef38b
 #include "common/list.h"
4ef38b
 #include "common/util.h"
4ef38b
+#include "common/_error.h"
4ef38b
 #include "oscap_assert.h"
4ef38b
 
4ef38b
 #define SEEN_LEN 9