Received: by 2002:a05:6a10:1a4d:0:0:0:0 with SMTP id nk13csp3609170pxb; Fri, 11 Feb 2022 03:58:43 -0800 (PST) X-Google-Smtp-Source: ABdhPJyN6hyu5o8SVkRUIbiSlR6GA1Qq23KPjyUSODiNGy4OBGMjeS7ocjyR14qwkHz1mBRJzo5d X-Received: by 2002:a17:906:dc92:: with SMTP id cs18mr1118884ejc.656.1644580723199; Fri, 11 Feb 2022 03:58:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1644580723; cv=none; d=google.com; s=arc-20160816; b=sDI6si91DxP3lKNBGsTvFrOtuFwnVt+nvvQ6yS0uYgpJ2fLy00tL6zbH3H0yeA0Nl2 Re9FuoXUxwt/0Udc227CHSei3qRItvBk6U8EGh9Rwrtel910sucWaROavZf9d4qOeVJ2 t4oFUW8iE6zPE49OrkTMk2X7eDKiEeBOnhUGCDlhPDDqGepvsfL59r3azVL1EKlUQamR Fkp5tf5f4TtKNsgBy1n2cPzDZ+SV4wMa8Ud7dNf8JZK6pAR2bOUEuco+QIZfcdcAqcCL 6Uuf+0y/z+lWSmWir9siCPgtyFoNLCuzEZT452yjOqdFx3t4TNp588J8iDSJZIEft+T4 pyEw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=Hgk9AW7jztZlbl6FqNobOhQg228Tsn6TVNz5MhlwcDA=; b=z1NXTiPxxM2e838FS7bJ4qa1T6Qa/HTc3ZBDSqs2t3nHvDhnBo1HJGWAMy7M69apJm dV9gRcYe/KegAgY55gajSjfa98pxsa37TWFqpYZy92GndZzclMkatP9sUbRLhWGw34Nw MoHxHfNOge9DSh06gX8xkHp8uWHUhuHKEmi2S7BY0r3Xs9KuKTHyfXwzOulxiCSPUCQ2 5UEY6a0ODcUHOL0ZHMnZlEExATMYp1brTh8kbt2HNGK6A5q/2nl3bFR4ggLNbQmqIuSw 4FYYB3qjHHaTkim03orYZ1Ipx5vxDUOk5OQsDnaJt3RRbcnGEKrnKAiOqg8eKlYqA3MK Sg5w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id g30si11133410edf.431.2022.02.11.03.58.18; Fri, 11 Feb 2022 03:58:43 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1349194AbiBKKss (ORCPT + 99 others); Fri, 11 Feb 2022 05:48:48 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53944 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238232AbiBKKsp (ORCPT ); Fri, 11 Feb 2022 05:48:45 -0500 Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 822E5D64; Fri, 11 Feb 2022 02:48:43 -0800 (PST) Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.206]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4Jw9MM6swQz687Jc; Fri, 11 Feb 2022 18:48:31 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.63.22) by fraeml714-chm.china.huawei.com (10.206.15.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.21; Fri, 11 Feb 2022 11:48:40 +0100 From: Roberto Sassu To: , , , , , CC: , , , , , , Roberto Sassu Subject: [PATCH] ima: Calculate digest in ima_inode_hash() if not available Date: Fri, 11 Feb 2022 11:48:28 +0100 Message-ID: <20220211104828.4061334-1-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.32.0 MIME-Version: 1.0 Content-Transfer-Encoding: 7BIT Content-Type: text/plain; charset=US-ASCII X-Originating-IP: [10.204.63.22] X-ClientProxiedBy: lhreml753-chm.china.huawei.com (10.201.108.203) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org __ima_inode_hash() checks if a digest has been already calculated by looking for the integrity_iint_cache structure associated to the passed inode. Users of ima_file_hash() and ima_inode_hash() (e.g. eBPF) might be interested in obtaining the information without having to setup an IMA policy so that the digest is always available at the time they call one of those functions. Open a new file descriptor in __ima_inode_hash(), so that this function could invoke ima_collect_measurement() to calculate the digest if it is not available. Still return -EOPNOTSUPP if the calculation failed. Instead of opening a new file descriptor, the one from ima_file_hash() could have been used. However, since ima_inode_hash() was created to obtain the digest when the file descriptor is not available, it could benefit from this change too. Also, the opened file descriptor might be not suitable for use (file descriptor opened not for reading). This change does not cause memory usage increase, due to using a temporary integrity_iint_cache structure for the digest calculation, and due to freeing the ima_digest_data structure inside integrity_iint_cache before exiting from __ima_inode_hash(). Finally, update the test by removing ima_setup.sh (it is not necessary anymore to set an IMA policy) and by directly executing /bin/true. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima_main.c | 46 ++++++- tools/testing/selftests/bpf/Makefile | 1 - tools/testing/selftests/bpf/ima_setup.sh | 123 ------------------ .../selftests/bpf/prog_tests/test_ima.c | 25 +--- 4 files changed, 43 insertions(+), 152 deletions(-) delete mode 100755 tools/testing/selftests/bpf/ima_setup.sh diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 8c6e4514d494..44df3f990950 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "ima.h" @@ -521,15 +522,43 @@ EXPORT_SYMBOL_GPL(ima_file_check); static int __ima_inode_hash(struct inode *inode, char *buf, size_t buf_size) { - struct integrity_iint_cache *iint; - int hash_algo; + struct integrity_iint_cache *iint = NULL, tmp_iint; + struct file *file; + struct path root, path; + int rc, hash_algo; + + if (ima_policy_flag) + iint = integrity_iint_find(inode); + + if (!iint) { + memset(&tmp_iint, 0, sizeof(tmp_iint)); + tmp_iint.inode = inode; + iint = &tmp_iint; + + path.dentry = d_find_alias(inode); + if (!path.dentry) + return -EOPNOTSUPP; + + get_fs_root(current->fs, &root); + path.mnt = root.mnt; + + file = dentry_open(&path, O_RDONLY, current_cred()); + if (IS_ERR(file)) { + dput(path.dentry); + path_put(&root); + return -EOPNOTSUPP; + } - if (!ima_policy_flag) - return -EOPNOTSUPP; + rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo, + NULL); - iint = integrity_iint_find(inode); - if (!iint) - return -EOPNOTSUPP; + fput(file); + dput(path.dentry); + path_put(&root); + + if (rc != 0) + return -EOPNOTSUPP; + } mutex_lock(&iint->mutex); @@ -551,6 +580,9 @@ static int __ima_inode_hash(struct inode *inode, char *buf, size_t buf_size) hash_algo = iint->ima_hash->algo; mutex_unlock(&iint->mutex); + if (iint == &tmp_iint) + kfree(iint->ima_hash); + return hash_algo; } diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 42ffc24e9e71..f7f850b2cf26 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -480,7 +480,6 @@ TRUNNER_EXTRA_SOURCES := test_progs.c cgroup_helpers.c trace_helpers.c \ network_helpers.c testing_helpers.c \ btf_helpers.c flow_dissector_load.h TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read $(OUTPUT)/bpf_testmod.ko \ - ima_setup.sh \ $(wildcard progs/btf_dump_test_case_*.c) TRUNNER_BPF_BUILD_RULE := CLANG_BPF_BUILD_RULE TRUNNER_BPF_CFLAGS := $(BPF_CFLAGS) $(CLANG_CFLAGS) -DENABLE_ATOMICS_TESTS diff --git a/tools/testing/selftests/bpf/ima_setup.sh b/tools/testing/selftests/bpf/ima_setup.sh deleted file mode 100755 index 8e62581113a3..000000000000 --- a/tools/testing/selftests/bpf/ima_setup.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: GPL-2.0 - -set -e -set -u -set -o pipefail - -IMA_POLICY_FILE="/sys/kernel/security/ima/policy" -TEST_BINARY="/bin/true" -VERBOSE="${SELFTESTS_VERBOSE:=0}" -LOG_FILE="$(mktemp /tmp/ima_setup.XXXX.log)" - -usage() -{ - echo "Usage: $0 " - exit 1 -} - -ensure_mount_securityfs() -{ - local securityfs_dir=$(grep "securityfs" /proc/mounts | awk '{print $2}') - - if [ -z "${securityfs_dir}" ]; then - securityfs_dir=/sys/kernel/security - mount -t securityfs security "${securityfs_dir}" - fi - - if [ ! -d "${securityfs_dir}" ]; then - echo "${securityfs_dir}: securityfs is not mounted" && exit 1 - fi -} - -setup() -{ - local tmp_dir="$1" - local mount_img="${tmp_dir}/test.img" - local mount_dir="${tmp_dir}/mnt" - local copied_bin_path="${mount_dir}/$(basename ${TEST_BINARY})" - mkdir -p ${mount_dir} - - dd if=/dev/zero of="${mount_img}" bs=1M count=10 - - losetup -f "${mount_img}" - local loop_device=$(losetup -a | grep ${mount_img:?} | cut -d ":" -f1) - - mkfs.ext2 "${loop_device:?}" - mount "${loop_device}" "${mount_dir}" - - cp "${TEST_BINARY}" "${mount_dir}" - local mount_uuid="$(blkid ${loop_device} | sed 's/.*UUID="\([^"]*\)".*/\1/')" - - ensure_mount_securityfs - echo "measure func=BPRM_CHECK fsuuid=${mount_uuid}" > ${IMA_POLICY_FILE} -} - -cleanup() { - local tmp_dir="$1" - local mount_img="${tmp_dir}/test.img" - local mount_dir="${tmp_dir}/mnt" - - local loop_devices=$(losetup -a | grep ${mount_img:?} | cut -d ":" -f1) - - for loop_dev in "${loop_devices}"; do - losetup -d $loop_dev - done - - umount ${mount_dir} - rm -rf ${tmp_dir} -} - -run() -{ - local tmp_dir="$1" - local mount_dir="${tmp_dir}/mnt" - local copied_bin_path="${mount_dir}/$(basename ${TEST_BINARY})" - - exec "${copied_bin_path}" -} - -catch() -{ - local exit_code="$1" - local log_file="$2" - - if [[ "${exit_code}" -ne 0 ]]; then - cat "${log_file}" >&3 - fi - - rm -f "${log_file}" - exit ${exit_code} -} - -main() -{ - [[ $# -ne 2 ]] && usage - - local action="$1" - local tmp_dir="$2" - - [[ ! -d "${tmp_dir}" ]] && echo "Directory ${tmp_dir} doesn't exist" && exit 1 - - if [[ "${action}" == "setup" ]]; then - setup "${tmp_dir}" - elif [[ "${action}" == "cleanup" ]]; then - cleanup "${tmp_dir}" - elif [[ "${action}" == "run" ]]; then - run "${tmp_dir}" - else - echo "Unknown action: ${action}" - exit 1 - fi -} - -trap 'catch "$?" "${LOG_FILE}"' EXIT - -if [[ "${VERBOSE}" -eq 0 ]]; then - # Save the stderr to 3 so that we can output back to - # it incase of an error. - exec 3>&2 1>"${LOG_FILE}" 2>&1 -fi - -main "$@" -rm -f "${LOG_FILE}" diff --git a/tools/testing/selftests/bpf/prog_tests/test_ima.c b/tools/testing/selftests/bpf/prog_tests/test_ima.c index 97d8a6f84f4a..82427549f45a 100644 --- a/tools/testing/selftests/bpf/prog_tests/test_ima.c +++ b/tools/testing/selftests/bpf/prog_tests/test_ima.c @@ -13,15 +13,14 @@ #include "ima.skel.h" -static int run_measured_process(const char *measured_dir, u32 *monitored_pid) +static int run_measured_process(u32 *monitored_pid) { int child_pid, child_status; child_pid = fork(); if (child_pid == 0) { *monitored_pid = getpid(); - execlp("./ima_setup.sh", "./ima_setup.sh", "run", measured_dir, - NULL); + execlp("/bin/true", "/bin/true", NULL); exit(errno); } else if (child_pid > 0) { @@ -42,10 +41,7 @@ static int process_sample(void *ctx, void *data, size_t len) void test_test_ima(void) { - char measured_dir_template[] = "/tmp/ima_measuredXXXXXX"; struct ring_buffer *ringbuf = NULL; - const char *measured_dir; - char cmd[256]; int err, duration = 0; struct ima *skel = NULL; @@ -63,27 +59,14 @@ void test_test_ima(void) if (CHECK(err, "attach", "attach failed: %d\n", err)) goto close_prog; - measured_dir = mkdtemp(measured_dir_template); - if (CHECK(measured_dir == NULL, "mkdtemp", "err %d\n", errno)) - goto close_prog; - - snprintf(cmd, sizeof(cmd), "./ima_setup.sh setup %s", measured_dir); - err = system(cmd); - if (CHECK(err, "failed to run command", "%s, errno = %d\n", cmd, errno)) - goto close_clean; - - err = run_measured_process(measured_dir, &skel->bss->monitored_pid); + err = run_measured_process(&skel->bss->monitored_pid); if (CHECK(err, "run_measured_process", "err = %d\n", err)) - goto close_clean; + goto close_prog; err = ring_buffer__consume(ringbuf); ASSERT_EQ(err, 1, "num_samples_or_err"); ASSERT_NEQ(ima_hash_from_bpf, 0, "ima_hash"); -close_clean: - snprintf(cmd, sizeof(cmd), "./ima_setup.sh cleanup %s", measured_dir); - err = system(cmd); - CHECK(err, "failed to run command", "%s, errno = %d\n", cmd, errno); close_prog: ring_buffer__free(ringbuf); ima__destroy(skel); -- 2.32.0