IMA digest list plugin support signature within IMA header
This commit is contained in:
parent
9f6b740ac0
commit
827d222f02
@ -1,22 +1,56 @@
|
||||
From e49074a4e4bd0699d2c4a5bb3a0dc5ca45e19e12 Mon Sep 17 00:00:00 2001
|
||||
From a73dd3e60daf96ee2519495bce2c7d62134e582f Mon Sep 17 00:00:00 2001
|
||||
From: Roberto Sassu <roberto.sassu@huawei.com>
|
||||
Date: Wed, 26 Feb 2020 15:54:24 +0100
|
||||
Subject: [PATCH 2/3] Add digest list plugin
|
||||
Subject: [PATCH] Add digest list plugin
|
||||
|
||||
Add RPM plugin for IMA digest list uploading and removing.
|
||||
|
||||
v1:
|
||||
call process_digest_list after files are added
|
||||
|
||||
v2:
|
||||
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.
|
||||
|
||||
v3:
|
||||
Add license to digest_list.c
|
||||
|
||||
v4:
|
||||
Check rpm parser
|
||||
|
||||
v5:
|
||||
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.
|
||||
|
||||
v6:
|
||||
call process_digest_list after files are added
|
||||
|
||||
v7:
|
||||
dont remove ima xattr of parser when upgrading
|
||||
|
||||
v8:
|
||||
support add the signature within a IMA header
|
||||
|
||||
Signed-off-by: Huaxin Lu <luhuaxin1@huawei.com>
|
||||
---
|
||||
macros.in | 1 +
|
||||
plugins/Makefile.am | 4 +
|
||||
plugins/digest_list.c | 498 ++++++++++++++++++++++++++++++++++++++++++
|
||||
plugins/digest_list.c | 624 ++++++++++++++++++++++++++++++++++++++++++
|
||||
rpmio/digest.h | 1 +
|
||||
rpmio/rpmpgp.c | 3 +
|
||||
5 files changed, 507 insertions(+)
|
||||
5 files changed, 633 insertions(+)
|
||||
create mode 100644 plugins/digest_list.c
|
||||
|
||||
diff --git a/macros.in b/macros.in
|
||||
index 402749362..8619c1323 100644
|
||||
index 4531fcb..643b02b 100644
|
||||
--- a/macros.in
|
||||
+++ b/macros.in
|
||||
@@ -1184,6 +1184,7 @@ package or when debugging this package.\
|
||||
@@ -1150,6 +1150,7 @@ package or when debugging this package.\
|
||||
%__transaction_prioreset %{__plugindir}/prioreset.so
|
||||
%__transaction_audit %{__plugindir}/audit.so
|
||||
%__transaction_dbus_announce %{__plugindir}/dbus_announce.so
|
||||
@ -25,10 +59,10 @@ index 402749362..8619c1323 100644
|
||||
#------------------------------------------------------------------------------
|
||||
# Macros for further automated spec %setup and patch application
|
||||
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
|
||||
index d4ef039ed..07aa3585b 100644
|
||||
index 3a929d0..fd9be81 100644
|
||||
--- a/plugins/Makefile.am
|
||||
+++ b/plugins/Makefile.am
|
||||
@@ -48,3 +48,7 @@ audit_la_sources = audit.c
|
||||
@@ -69,3 +69,7 @@ audit_la_sources = audit.c
|
||||
audit_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la @WITH_AUDIT_LIB@
|
||||
plugins_LTLIBRARIES += audit.la
|
||||
endif
|
||||
@ -38,10 +72,24 @@ index d4ef039ed..07aa3585b 100644
|
||||
+plugins_LTLIBRARIES += digest_list.la
|
||||
diff --git a/plugins/digest_list.c b/plugins/digest_list.c
|
||||
new file mode 100644
|
||||
index 000000000..beb397309
|
||||
index 0000000..c1864c7
|
||||
--- /dev/null
|
||||
+++ b/plugins/digest_list.c
|
||||
@@ -0,0 +1,499 @@
|
||||
@@ -0,0 +1,624 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2020-2021 Huawei Technologies Duesseldorf GmbH
|
||||
+ *
|
||||
+ * Author: Roberto Sassu <roberto.sassu@huawei.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation, version 2 of the
|
||||
+ * License.
|
||||
+ *
|
||||
+ * File: digest_list.c
|
||||
+ * Plugin to load digest lists in the Linux kernel.
|
||||
+ */
|
||||
+
|
||||
+#include "system.h"
|
||||
+#include "errno.h"
|
||||
+
|
||||
@ -57,6 +105,7 @@ index 000000000..beb397309
|
||||
+#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>
|
||||
@ -70,9 +119,6 @@ index 000000000..beb397309
|
||||
+#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,
|
||||
@ -130,22 +176,11 @@ index 000000000..beb397309
|
||||
+ uint8_t sig[0]; /* signature payload */
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+static int upload_digest_list(char *path, int type, int digest_list_signed)
|
||||
+static int digest_list_count_is_zero(void)
|
||||
+{
|
||||
+ size_t size;
|
||||
+ char buf[21];
|
||||
+ const char *ima_path = DIGEST_LIST_DATA_PATH;
|
||||
+ struct stat st;
|
||||
+ pid_t pid;
|
||||
+ int ret = 0, fd;
|
||||
+ int fd = 0, ret = 0;
|
||||
+ char first = 0;
|
||||
+
|
||||
+ if (type == TR_REMOVED)
|
||||
+ ima_path = DIGEST_LIST_DATA_DEL_PATH;
|
||||
+
|
||||
+ if (stat(ima_path, &st) == -1)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* First determine if kernel interface can accept new digest lists */
|
||||
+ fd = open(DIGEST_LIST_COUNT, O_RDONLY);
|
||||
+ if (fd < 0) {
|
||||
+ rpmlog(RPMLOG_ERR, "digest_list: could not open IMA interface "
|
||||
@ -153,29 +188,50 @@ index 000000000..beb397309
|
||||
+ return -EACCES;
|
||||
+ }
|
||||
+
|
||||
+ ret = read(fd, buf, sizeof(buf));
|
||||
+ close(fd);
|
||||
+
|
||||
+ ret = read(fd, &first, 1);
|
||||
+ if (ret <= 0) {
|
||||
+ rpmlog(RPMLOG_ERR, "digest_list: could not read from IMA "
|
||||
+ "interface '%s': %s\n", DIGEST_LIST_COUNT,
|
||||
+ strerror(errno));
|
||||
+ close(fd);
|
||||
+ return -EACCES;
|
||||
+ }
|
||||
+
|
||||
+ /* Last character is newline */
|
||||
+ buf[ret - 1] = '\0';
|
||||
+ close(fd);
|
||||
+ return (first == '\0');
|
||||
+}
|
||||
+
|
||||
+ rpmlog(RPMLOG_DEBUG, "digest_list: digests count %s\n", buf);
|
||||
+static int upload_digest_list(char *path, int type, int digest_list_signed)
|
||||
+{
|
||||
+ int ret = 0, fd = 0;
|
||||
+ pid_t pid = 0;
|
||||
+ size_t size = 0;
|
||||
+ struct stat st;
|
||||
+ const char *ima_path = NULL;
|
||||
+
|
||||
+ if (*buf == '0') {
|
||||
+ rpmlog(RPMLOG_DEBUG, "digest_list: not uploading '%s' to IMA "
|
||||
+ "interface '%s'\n", path, ima_path);
|
||||
+ ima_path = (type == TR_REMOVED) ? DIGEST_LIST_DATA_DEL_PATH :
|
||||
+ DIGEST_LIST_DATA_PATH;
|
||||
+ if (stat(ima_path, &st) == -1) {
|
||||
+ rpmlog(RPMLOG_DEBUG, "digest_list: '%s' interface "
|
||||
+ "not exist\n", ima_path);
|
||||
+ return RPMRC_OK;
|
||||
+ }
|
||||
+
|
||||
+ /* First determine if kernel interface can accept new digest lists */
|
||||
+ if (digest_list_count_is_zero()) {
|
||||
+ rpmlog(RPMLOG_DEBUG, "digest_list: the count is 0, not "
|
||||
+ "upload '%s' to IMA interface '%s'\n", path, ima_path);
|
||||
+ return RPMRC_OK;
|
||||
+ }
|
||||
+
|
||||
+ /* If the digest list is not signed, execute the RPM parser */
|
||||
+ if (!digest_list_signed) {
|
||||
+ if (stat(RPM_PARSER, &st) == -1) {
|
||||
+ rpmlog(RPMLOG_DEBUG, "digest_list: %s not found, "
|
||||
+ "not uploading digest list\n", RPM_PARSER);
|
||||
+ return RPMRC_OK;
|
||||
+ }
|
||||
+
|
||||
+ if ((pid = fork()) == 0) {
|
||||
+ execlp(RPM_PARSER, RPM_PARSER, (type == TR_ADDED) ?
|
||||
+ "add" : "del", path, NULL);
|
||||
@ -186,12 +242,13 @@ index 000000000..beb397309
|
||||
+ if (ret != 0)
|
||||
+ rpmlog(RPMLOG_ERR, "digest_list: %s returned %d\n",
|
||||
+ RPM_PARSER, ret);
|
||||
+ return 0;
|
||||
+ return RPMRC_OK;
|
||||
+ }
|
||||
+
|
||||
+ /* If the digest list is signed, write path to the IMA interface */
|
||||
+ fd = open(ima_path, O_WRONLY);
|
||||
+ if (fd < 0) {
|
||||
+ rpmlog(RPMLOG_ERR, "digest_list: could not open IMA interface "
|
||||
+ rpmlog(RPMLOG_ERR, "digest_list: rcould not open IMA interface "
|
||||
+ "'%s': %s\n", ima_path, strerror(errno));
|
||||
+ return -EACCES;
|
||||
+ }
|
||||
@ -215,12 +272,11 @@ index 000000000..beb397309
|
||||
+static int write_rpm_digest_list(rpmte te, char *path)
|
||||
+{
|
||||
+ FD_t fd;
|
||||
+ ssize_t written;
|
||||
+ Header rpm = rpmteHeader(te);
|
||||
+ rpmtd immutable;
|
||||
+ int ret = 0;
|
||||
+ ssize_t written = 0;
|
||||
+ Header rpm = rpmteHeader(te);
|
||||
+ rpmtd immutable = rpmtdNew();
|
||||
+
|
||||
+ immutable = rpmtdNew();
|
||||
+ headerGet(rpm, RPMTAG_HEADERIMMUTABLE, immutable, 0);
|
||||
+
|
||||
+ fd = Fopen(path, "w.ufdio");
|
||||
@ -231,7 +287,6 @@ index 000000000..beb397309
|
||||
+
|
||||
+ written = Fwrite(rpm_header_magic, sizeof(uint8_t),
|
||||
+ sizeof(rpm_header_magic), fd);
|
||||
+
|
||||
+ if (written != sizeof(rpm_header_magic)) {
|
||||
+ ret = -EIO;
|
||||
+ goto out;
|
||||
@ -249,20 +304,18 @@ index 000000000..beb397309
|
||||
+
|
||||
+static int write_rpm_digest_list_ima_xattr(rpmte te, char *path)
|
||||
+{
|
||||
+ rpmtd signature;
|
||||
+ ssize_t written;
|
||||
+ FD_t fd;
|
||||
+ ssize_t written = 0;
|
||||
+ int ret = 0, sig_size = 0, sig_size_rounded = 0;
|
||||
+ uint8_t sig[2048] = { 0 };
|
||||
+ pgpDigParams sigp = NULL;
|
||||
+ struct signature_v2_hdr *sig_hdr = (struct signature_v2_hdr *)sig;
|
||||
+ Header rpm = rpmteHeader(te);
|
||||
+ FD_t fd;
|
||||
+ int ret = 0, sig_size, sig_size_rounded;
|
||||
+ rpmtd signature = rpmtdNew();
|
||||
+
|
||||
+ signature = rpmtdNew();
|
||||
+ headerGet(rpm, RPMTAG_RSAHEADER, signature, 0);
|
||||
+ ret = pgpPrtParams(signature->data, signature->count,
|
||||
+ PGPTAG_SIGNATURE, &sigp);
|
||||
+
|
||||
+ if (ret) {
|
||||
+ ret = -ENOENT;
|
||||
+ goto out;
|
||||
@ -333,22 +386,16 @@ index 000000000..beb397309
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int write_digest_list_ima_xattr(rpmte te, char *path, char *path_sig)
|
||||
+static int fill_pgp_signature_header(rpmte te, struct signature_v2_hdr *sig_hdr)
|
||||
+{
|
||||
+ rpmtd signature;
|
||||
+ uint8_t sig[2048] = { 0 };
|
||||
+ int ret = 0;
|
||||
+ pgpDigParams sigp = NULL;
|
||||
+ struct signature_v2_hdr *sig_hdr = (struct signature_v2_hdr *)sig;
|
||||
+ Header rpm = rpmteHeader(te);
|
||||
+ FD_t fd;
|
||||
+ struct stat st;
|
||||
+ int ret = 0, sig_size;
|
||||
+ rpmtd signature = rpmtdNew();
|
||||
+
|
||||
+ signature = rpmtdNew();
|
||||
+ headerGet(rpm, RPMTAG_RSAHEADER, signature, 0);
|
||||
+ ret = pgpPrtParams(signature->data, signature->count,
|
||||
+ PGPTAG_SIGNATURE, &sigp);
|
||||
+
|
||||
+ if (ret) {
|
||||
+ ret = -ENOENT;
|
||||
+ goto out;
|
||||
@ -359,25 +406,42 @@ index 000000000..beb397309
|
||||
+ sig_hdr->hash_algo = HASH_ALGO_SHA256;
|
||||
+ memcpy((void *)&sig_hdr->keyid, sigp->signid + sizeof(uint32_t),
|
||||
+ sizeof(uint32_t));
|
||||
+out:
|
||||
+ pgpDigParamsFree(sigp);
|
||||
+ rpmtdFree(signature);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+ if (stat(path_sig, &st) == -1) {
|
||||
+ ret = -EACCES;
|
||||
+ goto out;
|
||||
+static int write_digest_list_ima_xattr(rpmte te, char *path, char *path_sig)
|
||||
+{
|
||||
+ FD_t fd;
|
||||
+ struct stat st;
|
||||
+ int ret = 0, sig_size, hdr_exist;
|
||||
+ uint8_t sig[2048] = { 0 };
|
||||
+ struct signature_v2_hdr *sig_hdr = (struct signature_v2_hdr *)sig;
|
||||
+
|
||||
+ if (stat(path_sig, &st) == -1)
|
||||
+ return -EACCES;
|
||||
+
|
||||
+ /* Check if the signature has already included a header */
|
||||
+ hdr_exist = (sig_size - sizeof(sig_hdr) % 128) == 0 ? 0 : 1;
|
||||
+ if (!hdr_exist) {
|
||||
+ ret = fill_pgp_signature_header(te, sig_hdr);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (sizeof(sig_hdr) + st.st_size > sizeof(sig)) {
|
||||
+ rpmlog(RPMLOG_ERR, "digest_list: signature in %s too big\n",
|
||||
+ path);
|
||||
+ ret = -E2BIG;
|
||||
+ goto out;
|
||||
+ return -E2BIG;
|
||||
+ }
|
||||
+
|
||||
+ fd = Fopen(path_sig, "r.ufdio");
|
||||
+ if (fd < 0) {
|
||||
+ rpmlog(RPMLOG_ERR, "digest_list: could not open '%s': %s\n",
|
||||
+ path_sig, strerror(errno));
|
||||
+ ret = -EACCES;
|
||||
+ goto out;
|
||||
+ return -EACCES;
|
||||
+ }
|
||||
+
|
||||
+ sig_size = Fread(sig_hdr->sig, sizeof(uint8_t), st.st_size, fd);
|
||||
@ -385,36 +449,42 @@ index 000000000..beb397309
|
||||
+ rpmlog(RPMLOG_ERR, "digest_list: could not read '%s': %s\n",
|
||||
+ path_sig, strerror(errno));
|
||||
+ Fclose(fd);
|
||||
+ ret = -EIO;
|
||||
+ goto out;
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ sig_hdr->sig_size = __cpu_to_be16(sig_size);
|
||||
+
|
||||
+ Fclose(fd);
|
||||
+ rpmlog(RPMLOG_DEBUG,
|
||||
+ "digest_list: read signature of %d bytes from '%s'\n",
|
||||
+ sig_size, path_sig);
|
||||
+
|
||||
+ ret = lsetxattr(path, XATTR_NAME_IMA,
|
||||
+ sig, sizeof(*sig_hdr) + sig_size, 0);
|
||||
+ /* The signature may include the header */
|
||||
+ if (hdr_exist)
|
||||
+ ret = lsetxattr(path, XATTR_NAME_IMA, sig_hdr->sig, sig_size, 0);
|
||||
+ else
|
||||
+ ret = lsetxattr(path, XATTR_NAME_IMA, sig, sizeof(*sig_hdr) + sig_size, 0);
|
||||
+
|
||||
+ if (ret < 0)
|
||||
+ rpmlog(RPMLOG_ERR, "digest_list: could not apply security.ima "
|
||||
+ "on '%s': %s\n", path, strerror(errno));
|
||||
+ else
|
||||
+ rpmlog(RPMLOG_DEBUG, "digest_list: security.ima successfully "
|
||||
+ "applied on '%s'\n", path);
|
||||
+out:
|
||||
+ pgpDigParamsFree(sigp);
|
||||
+ rpmtdFree(signature);
|
||||
+
|
||||
+ 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;
|
||||
+ cap_user_data_t cap_data = &cap_data_data;
|
||||
+ rpmRC ret = RPMRC_OK;
|
||||
+
|
||||
+ path = malloc(PATH_MAX);
|
||||
@ -439,11 +509,17 @@ index 000000000..beb397309
|
||||
+ DIGEST_LIST_DEFAULT_PATH, rpmteN(te), rpmteV(te),
|
||||
+ rpmteR(te), rpmteA(te));
|
||||
+
|
||||
+ if (!stat(path_sig, &st))
|
||||
+ if (!stat(path_sig, &st)) {
|
||||
+ digest_list_signed = 1;
|
||||
+ rpmlog(RPMLOG_DEBUG, "digest_list: digest_list_signed = 1\n");
|
||||
+ } else {
|
||||
+ rpmlog(RPMLOG_DEBUG, "digest_list: digest_list_signed = 0\n");
|
||||
+ }
|
||||
+
|
||||
+ if (parser && !digest_list_signed)
|
||||
+ if (parser && !digest_list_signed) {
|
||||
+ rpmlog(RPMLOG_DEBUG, "digest_list: parser has to be signed!");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (parser)
|
||||
+ snprintf(path, PATH_MAX, "%s/0-parser_list-compact-libexec",
|
||||
@ -454,8 +530,10 @@ index 000000000..beb397309
|
||||
+ DIGEST_LIST_DEFAULT_PATH, rpmteN(te), rpmteV(te),
|
||||
+ rpmteR(te), rpmteA(te));
|
||||
+
|
||||
+ if (stat(path, &st) == -1)
|
||||
+ if (stat(path, &st) == -1) {
|
||||
+ rpmlog(RPMLOG_DEBUG, "digest_list: failed to find digest list file path!");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (!parser && !digest_list_signed)
|
||||
+ snprintf(path, PATH_MAX, "%s/0-metadata_list-rpm-%s-%s-%s.%s",
|
||||
@ -464,15 +542,7 @@ index 000000000..beb397309
|
||||
+
|
||||
+ 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);
|
||||
@ -480,7 +550,21 @@ index 000000000..beb397309
|
||||
+ 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 {
|
||||
@ -491,24 +575,22 @@ index 000000000..beb397309
|
||||
+ 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;
|
||||
+ }
|
||||
+
|
||||
+ ret = lremovexattr(path, XATTR_NAME_IMA);
|
||||
+ if (ret < 0)
|
||||
+ rpmlog(RPMLOG_ERR, "digest_list: cannot remove "
|
||||
+ "security.ima from '%s'\n", path);
|
||||
+ else
|
||||
+ rpmlog(RPMLOG_DEBUG, "digest_list: security.ima "
|
||||
+ "successfully removed from '%s'\n", path);
|
||||
+ }
|
||||
+out:
|
||||
+ free(path);
|
||||
@ -516,36 +598,113 @@ index 000000000..beb397309
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+rpmte cur_te;
|
||||
+int digest_list_counter;
|
||||
+
|
||||
+static rpmRC digest_list_psm_pre(rpmPlugin plugin, rpmte te)
|
||||
+{
|
||||
+ process_digest_list(te, 0);
|
||||
+ if (!strcmp(rpmteN(te), "digest-list-tools"))
|
||||
+ process_digest_list(te, 1);
|
||||
+ Header rpm = rpmteHeader(te);
|
||||
+ rpmtd dirnames, dirindexes;
|
||||
+ int i = -1;
|
||||
+
|
||||
+ digest_list_counter = 0;
|
||||
+
|
||||
+ dirnames = rpmtdNew();
|
||||
+ headerGet(rpm, RPMTAG_DIRNAMES, dirnames, 0);
|
||||
+
|
||||
+ while ((i = rpmtdNext(dirnames)) >= 0) {
|
||||
+ char *dirname = (char *) rpmtdGetString(dirnames);
|
||||
+
|
||||
+ if (!strncmp(dirname, DIGEST_LIST_DEFAULT_PATH,
|
||||
+ sizeof(DIGEST_LIST_DEFAULT_PATH) - 1) &&
|
||||
+ dirname[sizeof(DIGEST_LIST_DEFAULT_PATH) - 1] == '/')
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rpmtdFree(dirnames);
|
||||
+
|
||||
+ if (i == -1)
|
||||
+ return RPMRC_OK;
|
||||
+
|
||||
+ dirindexes = rpmtdNew();
|
||||
+ headerGet(rpm, RPMTAG_DIRINDEXES, dirindexes, 0);
|
||||
+ while (rpmtdNext(dirindexes) >= 0)
|
||||
+ if (rpmtdGetNumber(dirindexes) == i)
|
||||
+ digest_list_counter++;
|
||||
+
|
||||
+ rpmtdFree(dirindexes);
|
||||
+
|
||||
+ cur_te = te;
|
||||
+ return RPMRC_OK;
|
||||
+}
|
||||
+
|
||||
+static rpmRC digest_list_file_common(rpmPlugin plugin, rpmfi fi,
|
||||
+ const char* path, mode_t file_mode,
|
||||
+ rpmFsmOp op, int pre, int res)
|
||||
+{
|
||||
+ rpmFileAction action = XFO_ACTION(op);
|
||||
+
|
||||
+ if (!digest_list_counter)
|
||||
+ return RPMRC_OK;
|
||||
+
|
||||
+ if (!cur_te)
|
||||
+ return RPMRC_OK;
|
||||
+
|
||||
+ if (!pre && res != RPMRC_OK)
|
||||
+ return res;
|
||||
+
|
||||
+ 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,
|
||||
+ sizeof(DIGEST_LIST_DEFAULT_PATH) - 1) ||
|
||||
+ path[sizeof(DIGEST_LIST_DEFAULT_PATH) - 1] != '/')
|
||||
+ return RPMRC_OK;
|
||||
+
|
||||
+ if (!pre && --digest_list_counter)
|
||||
+ return RPMRC_OK;
|
||||
+
|
||||
+ rpmlog(RPMLOG_DEBUG, "process ima digest, pre: %d, action: %d, teType: %d\n",
|
||||
+ pre, action, rpmteType(cur_te));
|
||||
+ process_digest_list(cur_te, 0, pre);
|
||||
+ if (!strcmp(rpmteN(cur_te), "digest-list-tools")) {
|
||||
+ if (pre && rpmteType(cur_te) == TR_REMOVED)
|
||||
+ return RPMRC_OK;
|
||||
+
|
||||
+ rpmlog(RPMLOG_DEBUG, "process parser digest\n");
|
||||
+ process_digest_list(cur_te, 1, pre);
|
||||
+ }
|
||||
+
|
||||
+ return RPMRC_OK;
|
||||
+}
|
||||
+
|
||||
+static rpmRC digest_list_psm_post(rpmPlugin plugin, rpmte te, int res)
|
||||
+static rpmRC digest_list_file_pre(rpmPlugin plugin, rpmfi fi,
|
||||
+ const char* path, mode_t file_mode,
|
||||
+ rpmFsmOp op)
|
||||
+{
|
||||
+ if (res != RPMRC_OK)
|
||||
+ return RPMRC_OK;
|
||||
+ return digest_list_file_common(plugin, fi, path, file_mode, op, 1, 0);
|
||||
+}
|
||||
+
|
||||
+ process_digest_list(te, 0);
|
||||
+ if (!strcmp(rpmteN(te), "digest-list-tools"))
|
||||
+ process_digest_list(te, 1);
|
||||
+
|
||||
+ return RPMRC_OK;
|
||||
+static rpmRC digest_list_file_post(rpmPlugin plugin, rpmfi fi,
|
||||
+ const char* path, mode_t file_mode,
|
||||
+ rpmFsmOp op, int res)
|
||||
+{
|
||||
+ return digest_list_file_common(plugin, fi, path, file_mode, op, 0, res);
|
||||
+}
|
||||
+
|
||||
+struct rpmPluginHooks_s digest_list_hooks = {
|
||||
+ .psm_pre = digest_list_psm_pre,
|
||||
+ .psm_post = digest_list_psm_post,
|
||||
+ .fsm_file_pre = digest_list_file_pre,
|
||||
+ .fsm_file_post = digest_list_file_post,
|
||||
+};
|
||||
diff --git a/rpmio/digest.h b/rpmio/digest.h
|
||||
index 9e0cde3b9..01ca10d92 100644
|
||||
index ec7f339..0d11d80 100644
|
||||
--- a/rpmio/digest.h
|
||||
+++ b/rpmio/digest.h
|
||||
@@ -24,6 +24,7 @@ struct pgpDigAlg_s {
|
||||
@@ -25,6 +25,7 @@ struct pgpDigAlg_s {
|
||||
struct pgpDigParams_s {
|
||||
char * userid;
|
||||
uint8_t * hash;
|
||||
@ -554,10 +713,10 @@ index 9e0cde3b9..01ca10d92 100644
|
||||
|
||||
uint8_t version; /*!< version number. */
|
||||
diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
|
||||
index 46cd0f31a..3c6b18b53 100644
|
||||
index d36bd62..e508062 100644
|
||||
--- a/rpmio/rpmpgp.c
|
||||
+++ b/rpmio/rpmpgp.c
|
||||
@@ -600,6 +600,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
|
||||
@@ -627,6 +627,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
|
||||
}
|
||||
|
||||
p = ((uint8_t *)v) + sizeof(*v);
|
||||
@ -565,7 +724,7 @@ index 46cd0f31a..3c6b18b53 100644
|
||||
rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
|
||||
} break;
|
||||
case 4:
|
||||
@@ -658,6 +659,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
|
||||
@@ -689,6 +690,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
|
||||
if (p > hend)
|
||||
return 1;
|
||||
|
||||
@ -573,7 +732,7 @@ index 46cd0f31a..3c6b18b53 100644
|
||||
rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
|
||||
} break;
|
||||
default:
|
||||
@@ -745,6 +747,7 @@ static int pgpPrtKey(pgpTag tag, const uint8_t *h, size_t hlen,
|
||||
@@ -804,6 +806,7 @@ static int pgpPrtKey(pgpTag tag, const uint8_t *h, size_t hlen,
|
||||
}
|
||||
|
||||
p = ((uint8_t *)v) + sizeof(*v);
|
||||
@ -582,5 +741,5 @@ index 46cd0f31a..3c6b18b53 100644
|
||||
}
|
||||
} break;
|
||||
--
|
||||
2.27.GIT
|
||||
2.33.0
|
||||
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
From 676cd4c0b90043b745a39b43446e42e80948c643 Mon Sep 17 00:00:00 2001
|
||||
From: Roberto Sassu <roberto.sassu@huawei.com>
|
||||
Date: Fri, 12 Mar 2021 10:57:24 +0100
|
||||
Subject: [PATCH 5/5] Add license to digest_list.c
|
||||
|
||||
---
|
||||
plugins/digest_list.c | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/plugins/digest_list.c b/plugins/digest_list.c
|
||||
index cfde5cd1d..992a7e81a 100644
|
||||
--- a/plugins/digest_list.c
|
||||
+++ b/plugins/digest_list.c
|
||||
@@ -1,3 +1,17 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2020-2021 Huawei Technologies Duesseldorf GmbH
|
||||
+ *
|
||||
+ * Author: Roberto Sassu <roberto.sassu@huawei.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation, version 2 of the
|
||||
+ * License.
|
||||
+ *
|
||||
+ * File: digest_list.c
|
||||
+ * Plugin to load digest lists in the Linux kernel.
|
||||
+ */
|
||||
+
|
||||
#include "system.h"
|
||||
#include "errno.h"
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
From 18df7feaf512cf4d7548121e1f04d4e7066fb324 Mon Sep 17 00:00:00 2001
|
||||
From: Roberto Sassu <roberto.sassu@huawei.com>
|
||||
Date: Wed, 10 Mar 2021 12:23:32 +0100
|
||||
Subject: [PATCH 2/5] Check rpm parser
|
||||
|
||||
---
|
||||
plugins/digest_list.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/plugins/digest_list.c b/plugins/digest_list.c
|
||||
index bb778c57f..c62f8c22f 100644
|
||||
--- a/plugins/digest_list.c
|
||||
+++ b/plugins/digest_list.c
|
||||
@@ -131,6 +131,12 @@ static int upload_digest_list(char *path, int type, int digest_list_signed)
|
||||
|
||||
/* If the digest list is not signed, execute the RPM parser */
|
||||
if (!digest_list_signed) {
|
||||
+ if (stat(RPM_PARSER, &st) == -1) {
|
||||
+ rpmlog(RPMLOG_DEBUG, "digest_list: %s not found, "
|
||||
+ "not uploading digest list\n", RPM_PARSER);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
if ((pid = fork()) == 0) {
|
||||
execlp(RPM_PARSER, RPM_PARSER, (type == TR_ADDED) ?
|
||||
"add" : "del", path, NULL);
|
||||
--
|
||||
2.26.2
|
||||
|
||||
@ -1,81 +0,0 @@
|
||||
From 8ecd5fc6884ae165e38e16b900cc4da90665b9db Mon Sep 17 00:00:00 2001
|
||||
From: Roberto Sassu <roberto.sassu@huawei.com>
|
||||
Date: Wed, 10 Mar 2021 12:22:39 +0100
|
||||
Subject: [PATCH 1/5] Fix digest_list_counter
|
||||
|
||||
---
|
||||
plugins/digest_list.c | 38 +++++++++++++++++++++++---------------
|
||||
1 file changed, 23 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/plugins/digest_list.c b/plugins/digest_list.c
|
||||
index 2dfa21e35..bb778c57f 100644
|
||||
--- a/plugins/digest_list.c
|
||||
+++ b/plugins/digest_list.c
|
||||
@@ -477,8 +477,8 @@ int digest_list_counter;
|
||||
static rpmRC digest_list_psm_pre(rpmPlugin plugin, rpmte te)
|
||||
{
|
||||
Header rpm = rpmteHeader(te);
|
||||
- rpmtd dirnames;
|
||||
- int i;
|
||||
+ rpmtd dirnames, dirindexes;
|
||||
+ int i = -1;
|
||||
|
||||
digest_list_counter = 0;
|
||||
|
||||
@@ -487,13 +487,26 @@ static rpmRC digest_list_psm_pre(rpmPlugin plugin, rpmte te)
|
||||
|
||||
while ((i = rpmtdNext(dirnames)) >= 0) {
|
||||
char *dirname = (char *) rpmtdGetString(dirnames);
|
||||
+
|
||||
if (!strncmp(dirname, DIGEST_LIST_DEFAULT_PATH,
|
||||
- sizeof(DIGEST_LIST_DEFAULT_PATH) - 1))
|
||||
- digest_list_counter++;
|
||||
+ sizeof(DIGEST_LIST_DEFAULT_PATH) - 1) &&
|
||||
+ dirname[sizeof(DIGEST_LIST_DEFAULT_PATH) - 1] == '/')
|
||||
+ break;
|
||||
}
|
||||
|
||||
rpmtdFree(dirnames);
|
||||
|
||||
+ if (i == -1)
|
||||
+ return RPMRC_OK;
|
||||
+
|
||||
+ dirindexes = rpmtdNew();
|
||||
+ headerGet(rpm, RPMTAG_DIRINDEXES, dirindexes, 0);
|
||||
+ while (rpmtdNext(dirindexes) >= 0)
|
||||
+ if (rpmtdGetNumber(dirindexes) == i)
|
||||
+ digest_list_counter++;
|
||||
+
|
||||
+ rpmtdFree(dirindexes);
|
||||
+
|
||||
cur_te = te;
|
||||
return RPMRC_OK;
|
||||
}
|
||||
@@ -517,18 +530,13 @@ static rpmRC digest_list_file_common(rpmPlugin plugin, rpmfi fi,
|
||||
(!pre && action != FA_CREATE))
|
||||
return RPMRC_OK;
|
||||
|
||||
- if (digest_list_counter) {
|
||||
- if (!pre) {
|
||||
- if (!strncmp(path, DIGEST_LIST_DEFAULT_PATH,
|
||||
- sizeof(DIGEST_LIST_DEFAULT_PATH) - 1))
|
||||
- digest_list_counter--;
|
||||
- } else {
|
||||
- digest_list_counter = 0;
|
||||
- }
|
||||
+ if (strncmp(path, DIGEST_LIST_DEFAULT_PATH,
|
||||
+ sizeof(DIGEST_LIST_DEFAULT_PATH) - 1) ||
|
||||
+ path[sizeof(DIGEST_LIST_DEFAULT_PATH) - 1] != '/')
|
||||
+ return RPMRC_OK;
|
||||
|
||||
- if (digest_list_counter)
|
||||
- return RPMRC_OK;
|
||||
- }
|
||||
+ if (!pre && --digest_list_counter)
|
||||
+ return RPMRC_OK;
|
||||
|
||||
process_digest_list(cur_te, 0);
|
||||
if (!strcmp(rpmteN(cur_te), "digest-list-tools"))
|
||||
--
|
||||
2.26.2
|
||||
|
||||
@ -1,106 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,115 +0,0 @@
|
||||
From 641ec5a50cb5057e02c4cfe7bd537a32fafdd665 Mon Sep 17 00:00:00 2001
|
||||
From: Roberto Sassu <roberto.sassu@huawei.com>
|
||||
Date: Mon, 26 Oct 2020 12:10:31 +0800
|
||||
Subject: [PATCH] call process_digest_list after files are added
|
||||
|
||||
Signed-off-by: Anakin Zhang <benjamin93@163.com>
|
||||
---
|
||||
plugins/digest_list.c | 78 ++++++++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 69 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/plugins/digest_list.c b/plugins/digest_list.c
|
||||
index 9fcb5c4..7213b41 100644
|
||||
--- a/plugins/digest_list.c
|
||||
+++ b/plugins/digest_list.c
|
||||
@@ -479,28 +479,88 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+rpmte cur_te;
|
||||
+int digest_list_counter;
|
||||
+
|
||||
static rpmRC digest_list_psm_pre(rpmPlugin plugin, rpmte te)
|
||||
{
|
||||
- process_digest_list(te, 0);
|
||||
- if (!strcmp(rpmteN(te), "digest-list-tools"))
|
||||
- process_digest_list(te, 1);
|
||||
+ Header rpm = rpmteHeader(te);
|
||||
+ rpmtd dirnames;
|
||||
+ int i;
|
||||
+
|
||||
+ digest_list_counter = 0;
|
||||
+
|
||||
+ dirnames = rpmtdNew();
|
||||
+ headerGet(rpm, RPMTAG_DIRNAMES, dirnames, 0);
|
||||
+
|
||||
+ while ((i = rpmtdNext(dirnames)) >= 0) {
|
||||
+ char *dirname = (char *) rpmtdGetString(dirnames);
|
||||
+ if (!strncmp(dirname, DIGEST_LIST_DEFAULT_PATH,
|
||||
+ sizeof(DIGEST_LIST_DEFAULT_PATH) - 1))
|
||||
+ digest_list_counter++;
|
||||
+ }
|
||||
|
||||
+ rpmtdFree(dirnames);
|
||||
+
|
||||
+ cur_te = te;
|
||||
return RPMRC_OK;
|
||||
}
|
||||
|
||||
-static rpmRC digest_list_psm_post(rpmPlugin plugin, rpmte te, int res)
|
||||
+static rpmRC digest_list_file_common(rpmPlugin plugin, rpmfi fi,
|
||||
+ const char* path, mode_t file_mode,
|
||||
+ rpmFsmOp op, int pre, int res)
|
||||
{
|
||||
- if (res != RPMRC_OK)
|
||||
+ rpmFileAction action = XFO_ACTION(op);
|
||||
+
|
||||
+ if (!digest_list_counter)
|
||||
+ return RPMRC_OK;
|
||||
+
|
||||
+ if (!cur_te)
|
||||
+ return RPMRC_OK;
|
||||
+
|
||||
+ if (!pre && res != RPMRC_OK)
|
||||
+ return res;
|
||||
+
|
||||
+ if ((pre && action != FA_ERASE) ||
|
||||
+ (!pre && action != FA_CREATE))
|
||||
return RPMRC_OK;
|
||||
|
||||
- process_digest_list(te, 0);
|
||||
- if (!strcmp(rpmteN(te), "digest-list-tools"))
|
||||
- process_digest_list(te, 1);
|
||||
+ if (digest_list_counter) {
|
||||
+ if (!pre) {
|
||||
+ if (!strncmp(path, DIGEST_LIST_DEFAULT_PATH,
|
||||
+ sizeof(DIGEST_LIST_DEFAULT_PATH) - 1))
|
||||
+ digest_list_counter--;
|
||||
+ } else {
|
||||
+ digest_list_counter = 0;
|
||||
+ }
|
||||
+
|
||||
+ if (digest_list_counter)
|
||||
+ return RPMRC_OK;
|
||||
+ }
|
||||
+
|
||||
+ process_digest_list(cur_te, 0);
|
||||
+ if (!strcmp(rpmteN(cur_te), "digest-list-tools"))
|
||||
+ process_digest_list(cur_te, 1);
|
||||
|
||||
return RPMRC_OK;
|
||||
}
|
||||
|
||||
+static rpmRC digest_list_file_pre(rpmPlugin plugin, rpmfi fi,
|
||||
+ const char* path, mode_t file_mode,
|
||||
+ rpmFsmOp op)
|
||||
+{
|
||||
+ return digest_list_file_common(plugin, fi, path, file_mode, op, 1, 0);
|
||||
+}
|
||||
+
|
||||
+static rpmRC digest_list_file_post(rpmPlugin plugin, rpmfi fi,
|
||||
+ const char* path, mode_t file_mode,
|
||||
+ rpmFsmOp op, int res)
|
||||
+{
|
||||
+ return digest_list_file_common(plugin, fi, path, file_mode, op, 0, res);
|
||||
+}
|
||||
+
|
||||
struct rpmPluginHooks_s digest_list_hooks = {
|
||||
.psm_pre = digest_list_psm_pre,
|
||||
- .psm_post = digest_list_psm_post,
|
||||
+ .fsm_file_pre = digest_list_file_pre,
|
||||
+ .fsm_file_post = digest_list_file_post,
|
||||
};
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
From 2c27c71952ce3ac61afeabd3ef4e1d182574e905 Mon Sep 17 00:00:00 2001
|
||||
From: luhuaxin <luhuaxin1@huawei.com>
|
||||
Date: Tue, 15 Mar 2022 20:54:06 +0800
|
||||
Subject: [PATCH] dont remove ima xattr of parser when upgrading
|
||||
|
||||
Signed-off-by: luhuaxin <luhuaxin1@huawei.com>
|
||||
---
|
||||
plugins/digest_list.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/plugins/digest_list.c b/plugins/digest_list.c
|
||||
index 0692b5b..1d7ef92 100644
|
||||
--- a/plugins/digest_list.c
|
||||
+++ b/plugins/digest_list.c
|
||||
@@ -576,9 +576,16 @@ static rpmRC digest_list_file_common(rpmPlugin plugin, rpmfi fi,
|
||||
if (!pre && --digest_list_counter)
|
||||
return RPMRC_OK;
|
||||
|
||||
+ rpmlog(RPMLOG_DEBUG, "process ima digest, pre: %d, action: %d, teType: %d\n",
|
||||
+ pre, action, rpmteType(cur_te));
|
||||
process_digest_list(cur_te, 0, pre);
|
||||
- if (!strcmp(rpmteN(cur_te), "digest-list-tools"))
|
||||
+ if (!strcmp(rpmteN(cur_te), "digest-list-tools")) {
|
||||
+ if (pre && rpmteType(cur_te) == TR_REMOVED)
|
||||
+ return RPMRC_OK;
|
||||
+
|
||||
+ rpmlog(RPMLOG_DEBUG, "process parser digest\n");
|
||||
process_digest_list(cur_te, 1, pre);
|
||||
+ }
|
||||
|
||||
return RPMRC_OK;
|
||||
}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -1,64 +0,0 @@
|
||||
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
|
||||
|
||||
28
rpm.spec
28
rpm.spec
@ -1,6 +1,6 @@
|
||||
Name: rpm
|
||||
Version: 4.17.0
|
||||
Release: 38
|
||||
Release: 39
|
||||
Summary: RPM Package Manager
|
||||
License: GPLv2+
|
||||
URL: http://www.rpm.org/
|
||||
@ -16,20 +16,13 @@ Patch7: Generate-digest-lists.patch
|
||||
Patch8: Add-digest-list-plugin.patch
|
||||
Patch9: Don-t-add-dist-to-release-if-it-is-already-there.patch
|
||||
Patch10: Generate-digest-lists-before-calling-genCpioListAndH.patch
|
||||
Patch11: call-process_digest_list-after-files-are-added.patch
|
||||
Patch12: fix-lsetxattr-error-in-container.patch
|
||||
Patch13: rpm-selinux-plugin-check-context-file-exist.patch
|
||||
Patch14: get-in-use-of-ndb.patch
|
||||
Patch15: still-in-use-of-python-scripts-from-old-version.patch
|
||||
Patch16: Add-loongarch-architecture-support.patch
|
||||
Patch17: Fix-digest_list_counter.patch
|
||||
Patch18: Check-rpm-parser.patch
|
||||
Patch19: Remove-digest-list-from-the-kernel-during-package-re.patch
|
||||
Patch20: Add-license-to-digest_list.c.patch
|
||||
Patch21: Avoid-generating-digest-lists-if-they-are-already-pa.patch
|
||||
Patch22: dont-remove-ima-xattr-of-parser-when-upgrading.patch
|
||||
Patch23: rpm-Add-sw64-architecture.patch
|
||||
Patch24: 0001-add-default-machine-name-to-support-loongarch.patch
|
||||
Patch11: rpm-selinux-plugin-check-context-file-exist.patch
|
||||
Patch12: get-in-use-of-ndb.patch
|
||||
Patch13: still-in-use-of-python-scripts-from-old-version.patch
|
||||
Patch14: Add-loongarch-architecture-support.patch
|
||||
Patch15: Avoid-generating-digest-lists-if-they-are-already-pa.patch
|
||||
Patch16: rpm-Add-sw64-architecture.patch
|
||||
Patch17: 0001-add-default-machine-name-to-support-loongarch.patch
|
||||
|
||||
Patch6000: backport-Use-root-as-default-UID_0_USER-and-UID_0_GROUP.patch
|
||||
Patch6001: backport-Check-file-iterator-for-being-NULL-consistently.patch
|
||||
@ -206,7 +199,7 @@ Obsoletes: apidocs
|
||||
%prep
|
||||
%autosetup -n %{name}-%{version} -p1
|
||||
%ifnarch sw_64
|
||||
%patch23 -R -p1
|
||||
%patch16 -R -p1
|
||||
%endif
|
||||
|
||||
%build
|
||||
@ -418,6 +411,9 @@ make check || (cat tests/rpmtests.log; exit 0)
|
||||
%{_mandir}/man1/gendiff.1*
|
||||
|
||||
%changelog
|
||||
* Fri Jul 05 2024 luhuaxin <luhuaxin1@huawei.com> - 4.17.0-39
|
||||
- IMA digest list plugin support signature within IMA header
|
||||
|
||||
* Tue Jun 04 2024 Zhao Mengmeng <zhaomengmeng@kylinos.cn> - 4.17.0-38
|
||||
- Don't segfault on missing priority tag
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user