From 0f088c5c9efa8ab877455bc273d7e536c763f824 Mon Sep 17 00:00:00 2001
From: Roberto Sassu <roberto.sassu@huawei.com>
Date: Thu, 11 Mar 2021 11:59:45 +0100
Subject: [PATCH] Remove digest list from the kernel during package
 reinstallation

Signed-off-by: luhuaxin <luhuaxin1@huawei.com>
---
 plugins/digest_list.c | 36 +++++++++++++++++-------------------
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/plugins/digest_list.c b/plugins/digest_list.c
index ca77282..63f8f1c 100644
--- a/plugins/digest_list.c
+++ b/plugins/digest_list.c
@@ -27,9 +27,6 @@
 #define DIGEST_LIST_DEFAULT_PATH "/etc/ima/digest_lists"
 #define RPM_PARSER "/usr/libexec/rpm_parser"
 
-#define DIGEST_LIST_OP_ADD 0
-#define DIGEST_LIST_OP_DEL 1
-
 enum hash_algo {
 	HASH_ALGO_MD4,
 	HASH_ALGO_MD5,
@@ -372,12 +369,13 @@ out:
 	return ret;
 }
 
-static int process_digest_list(rpmte te, int parser)
+static int process_digest_list(rpmte te, int parser, int pre)
 {
 	char *path = NULL, *path_sig = NULL;
 	int digest_list_signed = 0;
 	struct stat st;
 	ssize_t size;
+	int type = rpmteType(te);
 	struct __user_cap_header_struct cap_header_data;
 	cap_user_header_t cap_header = &cap_header_data;
 	struct __user_cap_data_struct cap_data_data;
@@ -431,15 +429,7 @@ static int process_digest_list(rpmte te, int parser)
 
 	size = lgetxattr(path, XATTR_NAME_IMA, NULL, 0);
 
-	/* Don't upload again if digest list was already processed */
-	if ((rpmteType(te) == TR_ADDED && size > 0) ||
-	    (rpmteType(te) == TR_REMOVED && size < 0)) {
-		rpmlog(RPMLOG_DEBUG, "digest_list: '%s' already processed, "
-		       "nothing to do\n", path);
-		goto out;
-	}
-
-	if (rpmteType(te) == TR_ADDED) {
+	if (type == TR_ADDED && !pre && size < 0) {
 		if (!digest_list_signed) {
 			/* Write RPM header to the disk */
 			ret = write_rpm_digest_list(te, path);
@@ -472,12 +462,18 @@ static int process_digest_list(rpmte te, int parser)
 			ret = RPMRC_FAIL;
 			goto out;
 		}
+	} else if (type == TR_ADDED && pre) {
+		if (size < 0)
+			goto out;
+
+		/* rpm is overwriting the digest list, remove from the kernel */
+		type = TR_REMOVED;
 	}
 
 	/* Upload digest list to securityfs */
-	upload_digest_list(path, rpmteType(te), digest_list_signed);
+	upload_digest_list(path, type, digest_list_signed);
 
-	if (rpmteType(te) == TR_REMOVED) {
+	if (type == TR_REMOVED) {
 		if (!digest_list_signed) {
 			unlink(path);
 			goto out;
@@ -552,8 +548,10 @@ static rpmRC digest_list_file_common(rpmPlugin plugin, rpmfi fi,
 	if (!pre && res != RPMRC_OK)
 		return res;
 
-	if ((pre && action != FA_ERASE) ||
-	    (!pre && action != FA_CREATE))
+	if (!pre && rpmteType(cur_te) != TR_ADDED)
+		return RPMRC_OK;
+
+	if (pre && action == FA_SKIP)
 		return RPMRC_OK;
 
 	if (strncmp(path, DIGEST_LIST_DEFAULT_PATH,
@@ -564,9 +562,9 @@ static rpmRC digest_list_file_common(rpmPlugin plugin, rpmfi fi,
 	if (!pre && --digest_list_counter)
 		return RPMRC_OK;
 
-	process_digest_list(cur_te, 0);
+	process_digest_list(cur_te, 0, pre);
 	if (!strcmp(rpmteN(cur_te), "digest-list-tools"))
-		process_digest_list(cur_te, 1);
+		process_digest_list(cur_te, 1, pre);
 
 	return RPMRC_OK;
 }
-- 
2.33.0

