diff options
Diffstat (limited to 'Add-digest-list-plugin.patch')
-rw-r--r-- | Add-digest-list-plugin.patch | 700 |
1 files changed, 700 insertions, 0 deletions
diff --git a/Add-digest-list-plugin.patch b/Add-digest-list-plugin.patch new file mode 100644 index 0000000..14c89b5 --- /dev/null +++ b/Add-digest-list-plugin.patch @@ -0,0 +1,700 @@ +From 3b2fb7d5a40d25c3295e02eb3695a45189342369 Mon Sep 17 00:00:00 2001 +From: zhoushuiqing <zhoushuiqing2@huawei.com> +Date: Fri, 16 Jun 2023 11:21:37 +0800 +Subject: [PATCH] Add-digest-list-plugin + +Signed-off-by: Huaxin Lu <luhuaxin1@huawei.com> +--- + plugins/digest_list.c | 680 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 680 insertions(+) + create mode 100644 plugins/digest_list.c + +diff --git a/plugins/digest_list.c b/plugins/digest_list.c +new file mode 100644 +index 0000000..715b8d6 +--- /dev/null ++++ b/plugins/digest_list.c +@@ -0,0 +1,680 @@ ++/* ++ * 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" ++ ++#include <fcntl.h> ++#include <rpm/rpmlog.h> ++#include <rpm/rpmts.h> ++#include <rpm/header.h> ++#include <rpm/rpmpgp.h> ++#include "rpmio/rpmpgp_internal.h" ++#include <rpm/rpmfileutil.h> ++#include "lib/rpmplugin.h" ++#include <netinet/in.h> ++#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> ++ ++#include "debug.h" ++ ++#define IMA_DIR "/sys/kernel/security/ima" ++#define DIGEST_LIST_DATA_PATH IMA_DIR "/digest_list_data" ++#define DIGEST_LIST_DATA_DEL_PATH IMA_DIR "/digest_list_data_del" ++#define DIGEST_LIST_COUNT IMA_DIR "/digests_count" ++#define DIGEST_LIST_DEFAULT_PATH "/etc/ima/digest_lists" ++#define RPM_PARSER "/usr/libexec/rpm_parser" ++ ++enum hash_algo { ++ HASH_ALGO_MD4, ++ HASH_ALGO_MD5, ++ HASH_ALGO_SHA1, ++ HASH_ALGO_RIPE_MD_160, ++ HASH_ALGO_SHA256, ++ HASH_ALGO_SHA384, ++ HASH_ALGO_SHA512, ++ HASH_ALGO_SHA224, ++ HASH_ALGO_RIPE_MD_128, ++ HASH_ALGO_RIPE_MD_256, ++ HASH_ALGO_RIPE_MD_320, ++ HASH_ALGO_WP_256, ++ HASH_ALGO_WP_384, ++ HASH_ALGO_WP_512, ++ HASH_ALGO_TGR_128, ++ HASH_ALGO_TGR_160, ++ HASH_ALGO_TGR_192, ++ HASH_ALGO_SM3_256, ++ HASH_ALGO__LAST ++}; ++ ++#define PGPHASHALGO__LAST PGPHASHALGO_SHA224 + 1 ++enum hash_algo pgp_algo_mapping[PGPHASHALGO__LAST] = { ++ [PGPHASHALGO_MD5] = HASH_ALGO_MD5, ++ [PGPHASHALGO_SHA1] = HASH_ALGO_SHA1, ++ [PGPHASHALGO_SHA224] = HASH_ALGO_SHA224, ++ [PGPHASHALGO_SHA256] = HASH_ALGO_SHA256, ++ [PGPHASHALGO_SHA384] = HASH_ALGO_SHA384, ++ [PGPHASHALGO_SHA512] = HASH_ALGO_SHA512, ++}; ++ ++/* from integrity.h */ ++enum evm_ima_xattr_type { ++ IMA_XATTR_DIGEST = 0x01, ++ EVM_XATTR_HMAC, ++ EVM_IMA_XATTR_DIGSIG, ++ IMA_XATTR_DIGEST_NG, ++ EVM_XATTR_PORTABLE_DIGSIG, ++ EVM_IMA_XATTR_DIGEST_LIST, ++ IMA_XATTR_LAST ++}; ++ ++struct evm_ima_xattr_data { ++ uint8_t type; ++ uint8_t digest[SHA512_DIGEST_LENGTH + 1]; ++} __attribute__((packed)); ++ ++struct signature_v2_hdr { ++ uint8_t type; /* xattr type */ ++ uint8_t version; /* signature format version */ ++ uint8_t hash_algo; /* Digest algorithm [enum hash_algo] */ ++ __be32 keyid; /* IMA key identifier - not X509/PGP specific */ ++ __be16 sig_size; /* signature size */ ++ uint8_t sig[0]; /* signature payload */ ++} __attribute__((packed)); ++ ++static int digest_list_count_is_zero(void) ++{ ++ int fd = 0, ret = 0; ++ char first = 0; ++ ++ fd = open(DIGEST_LIST_COUNT, O_RDONLY); ++ if (fd < 0) { ++ rpmlog(RPMLOG_ERR, "digest_list: could not open IMA interface " ++ "'%s': %s\n", DIGEST_LIST_COUNT, strerror(errno)); ++ return -EACCES; ++ } ++ ++ 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; ++ } ++ ++ close(fd); ++ return (first == '0'); ++} ++ ++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; ++ ++ 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); ++ _exit(EXIT_FAILURE); ++ } ++ ++ waitpid(pid, &ret, 0); ++ if (ret != 0) ++ rpmlog(RPMLOG_ERR, "digest_list: %s returned %d\n", ++ RPM_PARSER, ret); ++ 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: rcould not open IMA interface " ++ "'%s': %s\n", ima_path, strerror(errno)); ++ return -EACCES; ++ } ++ ++ /* Write the path of the digest list to securityfs */ ++ size = write(fd, path, strlen(path)); ++ if (size != strlen(path)) { ++ rpmlog(RPMLOG_ERR, "digest_list: could not write '%s' to IMA " ++ "interface '%s': %s\n", path, ima_path, strerror(errno)); ++ ret = -EIO; ++ goto out; ++ } ++ ++ rpmlog(RPMLOG_DEBUG, "digest_list: written '%s' to '%s'\n", path, ++ ima_path); ++out: ++ close(fd); ++ return ret; ++} ++ ++static int write_rpm_digest_list(rpmte te, char *path) ++{ ++ FD_t fd; ++ int ret = 0; ++ ssize_t written = 0; ++ Header rpm = rpmteHeader(te); ++ rpmtd immutable = rpmtdNew(); ++ ++ headerGet(rpm, RPMTAG_HEADERIMMUTABLE, immutable, 0); ++ ++ fd = Fopen(path, "w.ufdio"); ++ if (fd == NULL || Ferror(fd)) { ++ ret = -EACCES; ++ goto out; ++ } ++ ++ written = Fwrite(rpm_header_magic, sizeof(uint8_t), ++ sizeof(rpm_header_magic), fd); ++ if (written != sizeof(rpm_header_magic)) { ++ ret = -EIO; ++ goto out; ++ } ++ ++ written = Fwrite(immutable->data, sizeof(uint8_t), ++ immutable->count, fd); ++ if (written != immutable->count || Ferror(fd)) ++ ret = -EIO; ++out: ++ Fclose(fd); ++ rpmtdFree(immutable); ++ return ret; ++} ++ ++static int write_rpm_digest_list_ima_xattr(rpmte te, char *path) ++{ ++ 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); ++ rpmtd signature = rpmtdNew(); ++ ++ headerGet(rpm, RPMTAG_RSAHEADER, signature, 0); ++ ret = pgpPrtParams(signature->data, signature->count, ++ PGPTAG_SIGNATURE, &sigp); ++ if (ret) { ++ ret = -ENOENT; ++ goto out; ++ } ++ ++ fd = Fopen(path, "a.ufdio"); ++ if (fd == NULL || Ferror(fd)) { ++ ret = -EACCES; ++ goto out; ++ } ++ ++ written = Fwrite(sigp->hash, sizeof(uint8_t), ++ sigp->hashlen, fd); ++ if (written != sigp->hashlen || Ferror(fd)) { ++ ret = -EIO; ++ goto out; ++ } ++ ++ if (sigp->version == 4) { ++ /* V4 trailer is six octets long (rfc4880) */ ++ uint8_t trailer[6]; ++ uint32_t nb = sigp->hashlen; ++ nb = htonl(nb); ++ trailer[0] = sigp->version; ++ trailer[1] = 0xff; ++ memcpy(trailer+2, &nb, 4); ++ ++ written = Fwrite(trailer, sizeof(uint8_t), sizeof(trailer), fd); ++ if (written != sizeof(trailer) || Ferror(fd)) { ++ ret = -EIO; ++ goto out; ++ } ++ } ++ ++ Fclose(fd); ++ ++ sig_hdr->type = EVM_IMA_XATTR_DIGSIG; ++ sig_hdr->version = 2; ++ sig_hdr->hash_algo = pgp_algo_mapping[sigp->hash_algo]; ++ memcpy((void *)&sig_hdr->keyid, sigp->signid + sizeof(uint32_t), ++ sizeof(uint32_t)); ++ ++ sig_size = (pgpMpiBits(sigp->data) + 7) >> 3; ++ if (sizeof(sig_hdr) + sig_size > sizeof(sig)) { ++ rpmlog(RPMLOG_ERR, ++ "digest_list: signature in %s too big\n", path); ++ ret = -E2BIG; ++ goto out; ++ } ++ ++ sig_size_rounded = ((sig_size + 7) >> 3) * 8; ++ sig_hdr->sig_size = __cpu_to_be16(sig_size_rounded); ++ ++ memcpy(sig_hdr->sig + sig_size_rounded - sig_size, ++ (uint8_t *)sigp->data + 2, sig_size); ++ ++ ret = lsetxattr(path, XATTR_NAME_IMA, ++ sig, sizeof(*sig_hdr) + sig_size_rounded, 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 fill_pgp_signature_header(rpmte te, struct signature_v2_hdr *sig_hdr) ++{ ++ int ret = 0; ++ pgpDigParams sigp = NULL; ++ Header rpm = rpmteHeader(te); ++ rpmtd signature = rpmtdNew(); ++ ++ headerGet(rpm, RPMTAG_RSAHEADER, signature, 0); ++ ret = pgpPrtParams(signature->data, signature->count, ++ PGPTAG_SIGNATURE, &sigp); ++ if (ret) { ++ ret = -ENOENT; ++ goto out; ++ } ++ ++ sig_hdr->type = EVM_IMA_XATTR_DIGSIG; ++ sig_hdr->version = 2; ++ 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; ++} ++ ++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 = st.st_size % 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); ++ 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)); ++ return -EACCES; ++ } ++ ++ sig_size = Fread(sig_hdr->sig, sizeof(uint8_t), st.st_size, fd); ++ if (sig_size != st.st_size || Ferror(fd)) { ++ rpmlog(RPMLOG_ERR, "digest_list: could not read '%s': %s\n", ++ path_sig, strerror(errno)); ++ Fclose(fd); ++ 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); ++ ++ /* 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); ++ ++ return ret; ++} ++ ++static int check_append_signature(const char *path) ++{ ++ const char *magic_str="~Module signature appended~"; ++ int magic_len = strlen(magic_str); ++ char buf[magic_len + 1]; ++ FILE *fp = NULL; ++ struct stat st; ++ int file_size = 0; ++ int ret = 0; ++ long offset = 0; ++ ++ if (stat(path, &st) == -1) ++ return 0; ++ ++ file_size = st.st_size; ++ ++ /* the character \0xa is append to MAGIC */ ++ offset = magic_len + 1; ++ if (file_size < offset) { ++ rpmlog(RPMLOG_DEBUG, "digest_list: not have sig, do nothing\n"); ++ return 0; ++ } ++ ++ fp = fopen(path, "rb+"); ++ if (!fp) { ++ rpmlog(RPMLOG_ERR, "digest_list: could not open '%s': %s\n", path, strerror(errno)); ++ return 0; ++ } ++ ++ ret = fseek(fp, (-offset), SEEK_END); ++ if (ret) { ++ rpmlog(RPMLOG_ERR, "digest_list: seek file fail with %s\n", strerror(errno)); ++ fclose(fp); ++ return 0; ++ } ++ ++ ret = fread(buf, 1, magic_len, fp); ++ if (ret == magic_len) { ++ if (strncmp(buf, magic_str, magic_len) == 0) { ++ fclose(fp); ++ return 1; ++ } ++ } ++ ++ fclose(fp); ++ return 0; ++} ++ ++static int process_digest_list(rpmte te, int parser, int pre) ++{ ++ char *path = NULL, *path_sig = NULL; ++ int digest_list_signed = 0; ++ int digest_list_signed_append = 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); ++ if (!path) { ++ ret = RPMRC_FAIL; ++ goto out; ++ } ++ ++ path_sig = malloc(PATH_MAX); ++ if (!path_sig) { ++ ret = RPMRC_FAIL; ++ goto out; ++ } ++ ++ if (parser) ++ snprintf(path_sig, PATH_MAX, ++ "%s.sig/0-parser_list-compact-libexec.sig", ++ DIGEST_LIST_DEFAULT_PATH); ++ else ++ snprintf(path_sig, PATH_MAX, ++ "%s.sig/0-metadata_list-compact-%s-%s-%s.%s.sig", ++ DIGEST_LIST_DEFAULT_PATH, rpmteN(te), rpmteV(te), ++ rpmteR(te), rpmteA(te)); ++ ++ 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) { ++ rpmlog(RPMLOG_DEBUG, "digest_list: parser has to be signed!"); ++ goto out; ++ } ++ ++ if (parser) ++ snprintf(path, PATH_MAX, "%s/0-parser_list-compact-libexec", ++ DIGEST_LIST_DEFAULT_PATH); ++ else ++ snprintf(path, PATH_MAX, ++ "%s/0-metadata_list-compact-%s-%s-%s.%s", ++ DIGEST_LIST_DEFAULT_PATH, rpmteN(te), rpmteV(te), ++ rpmteR(te), rpmteA(te)); ++ ++ if (stat(path, &st) == -1) { ++ rpmlog(RPMLOG_DEBUG, "digest_list: failed to find digest list file path!"); ++ goto out; ++ } ++ ++ if (!digest_list_signed && check_append_signature(path)) { ++ digest_list_signed = 1; ++ digest_list_signed_append = 1; ++ } ++ ++ if (!parser && !digest_list_signed) ++ snprintf(path, PATH_MAX, "%s/0-metadata_list-rpm-%s-%s-%s.%s", ++ DIGEST_LIST_DEFAULT_PATH, rpmteN(te), rpmteV(te), ++ rpmteR(te), rpmteA(te)); ++ ++ size = lgetxattr(path, XATTR_NAME_IMA, NULL, 0); ++ ++ if (type == TR_ADDED && !pre && size < 0) { ++ if (!digest_list_signed) { ++ /* Write RPM header to the disk */ ++ ret = write_rpm_digest_list(te, path); ++ if (ret < 0) { ++ 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 if (digest_list_signed_append) { ++ ret = RPMRC_OK; ++ } else { ++ ret = write_digest_list_ima_xattr(te, path, path_sig); ++ } ++ ++ if (ret < 0) { ++ 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, type, digest_list_signed); ++ ++ if (type == TR_REMOVED) { ++ if (!digest_list_signed) { ++ unlink(path); ++ goto out; ++ } ++ } ++out: ++ free(path); ++ free(path_sig); ++ return ret; ++} ++ ++rpmte cur_te; ++int digest_list_counter; ++ ++static rpmRC digest_list_psm_pre(rpmPlugin plugin, rpmte te) ++{ ++ 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 (path == NULL || 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_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, ++ .fsm_file_pre = digest_list_file_pre, ++ .fsm_file_post = digest_list_file_post, ++}; +-- +2.46.0 + |