From 848cad38da6c727c91f0fcb8052f9402de598737 Mon Sep 17 00:00:00 2001
From: Zhang Tianxing <zhangtianxing3@huawei.com>
Date: Mon, 13 Sep 2021 17:32:11 +0800
Subject: [PATCH] fix lsetxattr error in container

The digest list plugin in rpm will set security.ima xattr to IMA digest lists
when installing or updating an rpm package. However, in a container without
CAP_SYS_ADMIN, we'll get error messages when calling lsetxattr.

This patch is to skip lsetxattr when CAP_SYS_ADMIN is missing.

Signed-off-by: Zhang Tianxing <zhangtianxing3@huawei.com>
---
 plugins/digest_list.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/plugins/digest_list.c b/plugins/digest_list.c
index 6bc9415..2d14463 100644
--- a/plugins/digest_list.c
+++ b/plugins/digest_list.c
@@ -12,6 +12,7 @@
 #include <sys/stat.h>
 #include <openssl/sha.h>
 #include <sys/xattr.h>
+#include <sys/capability.h>
 #include <linux/xattr.h>
 #include <asm/byteorder.h>
 #include <sys/wait.h>
@@ -370,6 +371,10 @@ static int process_digest_list(rpmte te, int parser)
 	int digest_list_signed = 0;
 	struct stat st;
 	ssize_t size;
+	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;
+	cap_user_data_t cap_data = &cap_data_data;
 	rpmRC ret = RPMRC_OK;
 
 	path = malloc(PATH_MAX);
@@ -435,7 +440,21 @@ static int process_digest_list(rpmte te, int parser)
 				ret = RPMRC_FAIL;
 				goto out;
 			}
+		}
 
+		/* don't call lsetxattr without CAP_SYS_ADMIN */
+		cap_header->pid = getpid();
+		cap_header->version = _LINUX_CAPABILITY_VERSION_1;
+		if (capget(cap_header, cap_data) < 0) {
+			ret = -ENOENT;
+			goto out;
+		}
+		if (!(cap_data->effective & CAP_TO_MASK(CAP_SYS_ADMIN))) {
+			ret = -EPERM;
+			goto out;
+		}
+
+		if (!digest_list_signed) {
 			/* Write RPM header sig to security.ima */
 			ret = write_rpm_digest_list_ima_xattr(te, path);
 		} else {
-- 
2.27.0

