From patchwork Wed Apr 2 12:47:15 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: steven chen X-Patchwork-Id: 14035941 Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4844223C361; Wed, 2 Apr 2025 12:47:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=13.77.154.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1743598063; cv=none; b=Aa4ZUoloRWjwlZ+SmLqbT7RIEIVJEWq8RQzH1fOyT/gHJ//b+2T4xJLm8S6+HSoDij8HETcTFMhDjrjUgktbEsUF2OH77BS89wMA0cmjA+elPx045hnawsmCHRrBUR5YDcQavSlyx84uYCar8W232n68SWVjDe1mLDocjcKdVsw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1743598063; c=relaxed/simple; bh=SyM0DZtwigOEgpFBa9WxtOXzwXbfno/O0ZN2nxa+6+c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=J5b9TIFRJvlk2Ftphz/2OLa1cuFA9l7ZtQGSsPNt31M+kKyhxhQ7Nzew86e3noTpRQaugjizmBuBPND3DGFdc64wZ8ANNmtcoNcwY+nCtTzt3CNEq2omsRNDAHDEEf4oht1sSKGG9Uzrvmg0LhiOxZ32MNma/WIfWooo7UaiDKE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com; spf=pass smtp.mailfrom=linux.microsoft.com; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b=GBp977W2; arc=none smtp.client-ip=13.77.154.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="GBp977W2" Received: from DESKTOP-VOT081N.hsd1.ga.comcast.net (unknown [20.114.144.49]) by linux.microsoft.com (Postfix) with ESMTPSA id DC82A2041310; Wed, 2 Apr 2025 05:47:38 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com DC82A2041310 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1743598060; bh=c/RS/PAb2CclZX+321SCa66PSDIvCelNRFFOQ2o7wf8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GBp977W2a8y50FQq8iP0ZPDfbqsoMIp55WRJGHcKH9M/umzkVgUBH/FizQPCXl3xf j8etCR89uA+7HKmwJBubkR4vGp+xe1bqwKqmwiYvto8LwzQM0pNLF4e56xmn/LXxes LcV0T0O0+B3gyXnLjvS2XgZJG3/oRu38Ii4RIY9Y= From: steven chen To: zohar@linux.ibm.com, stefanb@linux.ibm.com, roberto.sassu@huaweicloud.com, roberto.sassu@huawei.com, eric.snowberg@oracle.com, ebiederm@xmission.com, paul@paul-moore.com, code@tyhicks.com, bauermann@kolabnow.com, linux-integrity@vger.kernel.org, kexec@lists.infradead.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org Cc: madvenka@linux.microsoft.com, nramas@linux.microsoft.com, James.Bottomley@HansenPartnership.com, bhe@redhat.com, vgoyal@redhat.com, dyoung@redhat.com Subject: [PATCH v11 2/9] ima: define and call ima_alloc_kexec_file_buf() Date: Wed, 2 Apr 2025 05:47:15 -0700 Message-ID: <20250402124725.5601-3-chenste@linux.microsoft.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250402124725.5601-1-chenste@linux.microsoft.com> References: <20250402124725.5601-1-chenste@linux.microsoft.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In the current implementation, the ima_dump_measurement_list() API is called during the kexec "load" phase, where a buffer is allocated and the measurement records are copied. Due to this, new events added after kexec load but before kexec execute are not carried over to the new kernel during kexec operation To allow the buffer allocation and population to be separated into distinct steps, make the function local seq_file "ima_kexec_file" to a file variable. Carrying the IMA measurement list across kexec requires allocating a buffer and copying the measurement records. Separate allocating the buffer and copying the measurement records into separate functions in order to allocate the buffer at kexec 'load' and copy the measurements at kexec 'execute'. Signed-off-by: Tushar Sugandhi Signed-off-by: steven chen Acked-by: Baoquan He --- security/integrity/ima/ima_kexec.c | 46 +++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c index 650beb74346c..b12ac3619b8f 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -15,26 +15,46 @@ #include "ima.h" #ifdef CONFIG_IMA_KEXEC +static struct seq_file ima_kexec_file; + +static void ima_free_kexec_file_buf(struct seq_file *sf) +{ + vfree(sf->buf); + sf->buf = NULL; + sf->size = 0; + sf->read_pos = 0; + sf->count = 0; +} + +static int ima_alloc_kexec_file_buf(size_t segment_size) +{ + ima_free_kexec_file_buf(&ima_kexec_file); + + /* segment size can't change between kexec load and execute */ + ima_kexec_file.buf = vmalloc(segment_size); + if (!ima_kexec_file.buf) + return -ENOMEM; + + ima_kexec_file.size = segment_size; + ima_kexec_file.read_pos = 0; + ima_kexec_file.count = sizeof(struct ima_kexec_hdr); /* reserved space */ + + return 0; +} + static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer, unsigned long segment_size) { - struct seq_file ima_kexec_file; struct ima_queue_entry *qe; struct ima_kexec_hdr khdr; int ret = 0; /* segment size can't change between kexec load and execute */ - ima_kexec_file.buf = vmalloc(segment_size); if (!ima_kexec_file.buf) { - ret = -ENOMEM; - goto out; + pr_err("Kexec file buf not allocated\n"); + return -EINVAL; } - ima_kexec_file.file = NULL; - ima_kexec_file.size = segment_size; - ima_kexec_file.read_pos = 0; - ima_kexec_file.count = sizeof(khdr); /* reserved space */ - memset(&khdr, 0, sizeof(khdr)); khdr.version = 1; /* This is an append-only list, no need to hold the RCU read lock */ @@ -71,8 +91,6 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer, *buffer_size = ima_kexec_file.count; *buffer = ima_kexec_file.buf; out: - if (ret == -EINVAL) - vfree(ima_kexec_file.buf); return ret; } @@ -111,6 +129,12 @@ void ima_add_kexec_buffer(struct kimage *image) return; } + ret = ima_alloc_kexec_file_buf(kexec_segment_size); + if (ret < 0) { + pr_err("Not enough memory for the kexec measurement buffer.\n"); + return; + } + ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer, kexec_segment_size); if (!kexec_buffer) {