Blame SOURCES/0003-libsemanage-fsync-final-files-before-rename.patch

abd501
From dc4f1d03d6e17d851283f9b10b2faeeca9b10e14 Mon Sep 17 00:00:00 2001
abd501
From: Stephen Smalley <stephen.smalley.work@gmail.com>
abd501
Date: Wed, 13 May 2020 15:34:19 -0400
abd501
Subject: [PATCH] libsemanage: fsync final files before rename
abd501
abd501
Prior to rename(2)'ing the final selinux policy files into place,
abd501
fsync(2) them to ensure the contents will be fully written prior to
abd501
rename.  While we are here, also fix checking of write(2) to detect
abd501
short writes and treat them as an error.  This code could be more
abd501
generally improved but keeping to the minimal changes required to fix
abd501
this bug.
abd501
abd501
Fixes: https://github.com/SELinuxProject/selinux/issues/237
abd501
Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com>
abd501
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
abd501
abd501
Source:
abd501
https://github.com/SELinuxProject/selinux/commit/331a109f91ea46473fd858c2494f6eab1ef43f66
abd501
---
abd501
 libsemanage/src/direct_api.c     | 10 +++++-----
abd501
 libsemanage/src/semanage_store.c | 20 +++++++++++++++-----
abd501
 libsemanage/src/semanage_store.h |  4 +++-
abd501
 3 files changed, 23 insertions(+), 11 deletions(-)
abd501
abd501
diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
abd501
index 8e4d116d..abc3a4cb 100644
abd501
--- a/libsemanage/src/direct_api.c
abd501
+++ b/libsemanage/src/direct_api.c
abd501
@@ -1188,7 +1188,7 @@ cleanup:
abd501
  * overwrite it. If source doesn't exist then return success.
abd501
  * Returns 0 on success, -1 on error. */
abd501
 static int copy_file_if_exists(const char *src, const char *dst, mode_t mode){
abd501
-	int rc = semanage_copy_file(src, dst, mode);
abd501
+	int rc = semanage_copy_file(src, dst, mode, false);
abd501
 	return (rc < 0 && errno != ENOENT) ? rc : 0;
abd501
 }
abd501
 
abd501
@@ -1481,7 +1481,7 @@ rebuild:
abd501
 			retval = semanage_copy_file(path,
abd501
 						    semanage_path(SEMANAGE_TMP,
abd501
 								  SEMANAGE_STORE_SEUSERS),
abd501
-						    0);
abd501
+						    0, false);
abd501
 			if (retval < 0)
abd501
 				goto cleanup;
abd501
 			pseusers->dtable->drop_cache(pseusers->dbase);
abd501
@@ -1499,7 +1499,7 @@ rebuild:
abd501
 			retval = semanage_copy_file(path,
abd501
 						    semanage_path(SEMANAGE_TMP,
abd501
 								  SEMANAGE_USERS_EXTRA),
abd501
-						    0);
abd501
+						    0, false);
abd501
 			if (retval < 0)
abd501
 				goto cleanup;
abd501
 			pusers_extra->dtable->drop_cache(pusers_extra->dbase);
abd501
@@ -1588,7 +1588,7 @@ rebuild:
abd501
 
abd501
 	retval = semanage_copy_file(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL),
abd501
 			semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL),
abd501
-			sh->conf->file_mode);
abd501
+			sh->conf->file_mode, false);
abd501
 	if (retval < 0) {
abd501
 		goto cleanup;
abd501
 	}
abd501
@@ -1627,7 +1627,7 @@ rebuild:
abd501
 			retval = semanage_copy_file(
abd501
 						semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_HOMEDIRS),
abd501
 						semanage_final_path(SEMANAGE_FINAL_TMP,	SEMANAGE_FC_HOMEDIRS),
abd501
-						sh->conf->file_mode);
abd501
+						sh->conf->file_mode, false);
abd501
 			if (retval < 0) {
abd501
 				goto cleanup;
abd501
 			}
abd501
diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
abd501
index 58dded6e..733df8da 100644
abd501
--- a/libsemanage/src/semanage_store.c
abd501
+++ b/libsemanage/src/semanage_store.c
abd501
@@ -707,7 +707,8 @@ static int semanage_filename_select(const struct dirent *d)
abd501
 
abd501
 /* Copies a file from src to dst.  If dst already exists then
abd501
  * overwrite it.  Returns 0 on success, -1 on error. */
abd501
-int semanage_copy_file(const char *src, const char *dst, mode_t mode)
abd501
+int semanage_copy_file(const char *src, const char *dst, mode_t mode,
abd501
+		bool syncrequired)
abd501
 {
abd501
 	int in, out, retval = 0, amount_read, n, errsv = errno;
abd501
 	char tmp[PATH_MAX];
abd501
@@ -735,8 +736,11 @@ int semanage_copy_file(const char *src, const char *dst, mode_t mode)
abd501
 	}
abd501
 	umask(mask);
abd501
 	while (retval == 0 && (amount_read = read(in, buf, sizeof(buf))) > 0) {
abd501
-		if (write(out, buf, amount_read) < 0) {
abd501
-			errsv = errno;
abd501
+		if (write(out, buf, amount_read) != amount_read) {
abd501
+			if (errno)
abd501
+				errsv = errno;
abd501
+			else
abd501
+				errsv = EIO;
abd501
 			retval = -1;
abd501
 		}
abd501
 	}
abd501
@@ -745,6 +749,10 @@ int semanage_copy_file(const char *src, const char *dst, mode_t mode)
abd501
 		retval = -1;
abd501
 	}
abd501
 	close(in);
abd501
+	if (syncrequired && fsync(out) < 0) {
abd501
+		errsv = errno;
abd501
+		retval = -1;
abd501
+	}
abd501
 	if (close(out) < 0) {
abd501
 		errsv = errno;
abd501
 		retval = -1;
abd501
@@ -811,7 +819,8 @@ static int semanage_copy_dir_flags(const char *src, const char *dst, int flag)
abd501
 			umask(mask);
abd501
 		} else if (S_ISREG(sb.st_mode) && flag == 1) {
abd501
 			mask = umask(0077);
abd501
-			if (semanage_copy_file(path, path2, sb.st_mode) < 0) {
abd501
+			if (semanage_copy_file(path, path2, sb.st_mode,
abd501
+						false) < 0) {
abd501
 				umask(mask);
abd501
 				goto cleanup;
abd501
 			}
abd501
@@ -1640,7 +1649,8 @@ static int semanage_install_final_tmp(semanage_handle_t * sh)
abd501
 			goto cleanup;
abd501
 		}
abd501
 
abd501
-		ret = semanage_copy_file(src, dst, sh->conf->file_mode);
abd501
+		ret = semanage_copy_file(src, dst, sh->conf->file_mode,
abd501
+					true);
abd501
 		if (ret < 0) {
abd501
 			ERR(sh, "Could not copy %s to %s.", src, dst);
abd501
 			goto cleanup;
abd501
diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
abd501
index 34bf8523..b9ec5664 100644
abd501
--- a/libsemanage/src/semanage_store.h
abd501
+++ b/libsemanage/src/semanage_store.h
abd501
@@ -24,6 +24,7 @@
abd501
 #ifndef SEMANAGE_MODULE_STORE_H
abd501
 #define SEMANAGE_MODULE_STORE_H
abd501
 
abd501
+#include <stdbool.h>
abd501
 #include <sys/time.h>
abd501
 #include <sepol/module.h>
abd501
 #include <sepol/cil/cil.h>
abd501
@@ -162,6 +163,7 @@ int semanage_nc_sort(semanage_handle_t * sh,
abd501
 		     size_t buf_len,
abd501
 		     char **sorted_buf, size_t * sorted_buf_len);
abd501
 
abd501
-int semanage_copy_file(const char *src, const char *dst, mode_t mode);
abd501
+int semanage_copy_file(const char *src, const char *dst, mode_t mode,
abd501
+		bool syncrequired);
abd501
 
abd501
 #endif
abd501
-- 
abd501
2.25.4
abd501