From: Yeoreum Yun <yeoreum.yun@arm.com>
To: linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
Eric Snowberg <eric.snowberg@oracle.com>,
linux-integrity@vger.kernel.org,
linux-security-module@vger.kernel.org
Cc: Dan Williams <djbw@kernel.org>, Mimi Zohar <zohar@linux.ibm.com>,
Roberto Sassu <roberto.sassu@huawei.com>,
Dmitry Kasatkin <dmitry.kasatkin@gmail.com>,
Paul Moore <paul@paul-moore.com>,
James Morris <jmorris@namei.org>,
"Serge E. Hallyn" <serge@hallyn.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Jason Gunthorpe <jgg@ziepe.ca>,
Suzuki Poulose <suzuki.poulose@arm.com>,
Steven Price <steven.price@arm.com>,
Sami Mujawar <sami.mujawar@arm.com>,
"Aneesh Kumar K.V" <aneesh.kumar@kernel.org>,
Jiri Pirko <jiri@resnulli.us>, Yeoreum Yun <yeoreum.yun@arm.com>
Subject: [PATCH RFC 1/3] virt: coco: introduce tsm_default_tm() and tsm_mr_read()/write()
Date: Wed, 30 Sep 2026 14:43:59 +0100 [thread overview]
Message-ID: <20260930-ima_tgx_integration_v2-v1-1-722c35370548@arm.com> (raw)
In-Reply-To: <20260930-ima_tgx_integration_v2-v1-0-722c35370548@arm.com>
This is preparatory patch to use tsm measurement registers in IMA.
Introduce tsm_default_tm() and tsm_mr_read()/write() APIs
to read and extend the tsm measurement registers in IMA.
Since IMA is supported only when it's built as built-in,
export those symbols only tsm-mr is built as built-in.
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
drivers/virt/coco/guest/tsm-mr.c | 159 +++++++++++++++++++++++++++++++++------
include/linux/tsm-mr.h | 26 +++++++
2 files changed, 161 insertions(+), 24 deletions(-)
diff --git a/drivers/virt/coco/guest/tsm-mr.c b/drivers/virt/coco/guest/tsm-mr.c
index 657b9c5739d0..9e721348be8d 100644
--- a/drivers/virt/coco/guest/tsm-mr.c
+++ b/drivers/virt/coco/guest/tsm-mr.c
@@ -7,9 +7,15 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
+
#define CREATE_TRACE_POINTS
#include <trace/events/tsm_mr.h>
+#define TM_NUM_CTX (64 * HASH_ALGO__LAST)
+
+DEFINE_IDR(tm_ctx_idr);
+static DEFINE_MUTEX(idr_lock);
+
/*
* struct tm_context - contains everything necessary to implement sysfs
* attributes for MRs.
@@ -42,21 +48,16 @@ struct tm_context {
struct bin_attribute mrs[];
};
-static ssize_t tm_digest_read(struct file *filp, struct kobject *kobj,
- const struct bin_attribute *attr, char *buffer,
- loff_t off, size_t count)
+static ssize_t __tsm_mr_read(struct tm_context *ctx,
+ const struct tsm_measurement_register *mr,
+ char *buffer, loff_t off, size_t count)
{
- struct tm_context *ctx;
- const struct tsm_measurement_register *mr;
int rc;
- ctx = attr->private;
rc = down_read_interruptible(&ctx->rwsem);
if (rc)
return rc;
- mr = &ctx->tm->mrs[attr - ctx->mrs];
-
/*
* @ctx->in_sync indicates if the MR cache is stale. It is a global
* instead of a per-MR flag for simplicity, as most (if not all) archs
@@ -88,20 +89,11 @@ static ssize_t tm_digest_read(struct file *filp, struct kobject *kobj,
return rc ?: count;
}
-static ssize_t tm_digest_write(struct file *filp, struct kobject *kobj,
- const struct bin_attribute *attr, char *buffer,
- loff_t off, size_t count)
+static ssize_t __tsm_mr_write(struct tm_context *ctx,
+ const struct tsm_measurement_register *mr,
+ char *buffer, size_t count)
{
- struct tm_context *ctx;
- const struct tsm_measurement_register *mr;
- ssize_t rc;
-
- /* partial writes are not supported */
- if (off != 0 || count != attr->size)
- return -EINVAL;
-
- ctx = attr->private;
- mr = &ctx->tm->mrs[attr - ctx->mrs];
+ int rc;
rc = down_write_killable(&ctx->rwsem);
if (rc)
@@ -119,6 +111,36 @@ static ssize_t tm_digest_write(struct file *filp, struct kobject *kobj,
return rc ?: count;
}
+static ssize_t tm_digest_read(struct file *filp, struct kobject *kobj,
+ const struct bin_attribute *attr, char *buffer,
+ loff_t off, size_t count)
+{
+ struct tm_context *ctx;
+ const struct tsm_measurement_register *mr;
+
+ ctx = attr->private;
+ mr = &ctx->tm->mrs[attr - ctx->mrs];
+
+ return __tsm_mr_read(ctx, mr, buffer, off, count);
+}
+
+static ssize_t tm_digest_write(struct file *filp, struct kobject *kobj,
+ const struct bin_attribute *attr, char *buffer,
+ loff_t off, size_t count)
+{
+ struct tm_context *ctx;
+ const struct tsm_measurement_register *mr;
+
+ /* partial writes are not supported */
+ if (off != 0 || count != attr->size)
+ return -EINVAL;
+
+ ctx = attr->private;
+ mr = &ctx->tm->mrs[attr - ctx->mrs];
+
+ return __tsm_mr_write(ctx, mr, buffer, count);
+}
+
/**
* tsm_mr_create_attribute_group() - creates an attribute group for measurement
* registers (MRs)
@@ -138,8 +160,7 @@ static ssize_t tm_digest_write(struct file *filp, struct kobject *kobj,
* * %-ENOMEM - Out of memory.
*/
const struct attribute_group *
-tsm_mr_create_attribute_group(const struct tsm_measurements *tm)
-{
+tsm_mr_create_attribute_group(const struct tsm_measurements *tm) {
size_t nlen;
if (!tm || !tm->mrs)
@@ -230,6 +251,15 @@ tsm_mr_create_attribute_group(const struct tsm_measurements *tm)
ctx->agrp.name = "measurements";
ctx->agrp.bin_attrs = no_free_ptr(attrs);
ctx->tm = tm;
+
+ guard(mutex)(&idr_lock);
+ ((struct tsm_measurements *)tm)->ctx_id = idr_alloc(&tm_ctx_idr, ctx, 0,
+ TM_NUM_CTX, GFP_KERNEL);
+ if (tm->ctx_id < 0) {
+ kfree(ctx->agrp.bin_attrs);
+ return ERR_PTR(tm->ctx_id);
+ }
+
return &no_free_ptr(ctx)->agrp;
}
EXPORT_SYMBOL_GPL(tsm_mr_create_attribute_group);
@@ -243,9 +273,90 @@ EXPORT_SYMBOL_GPL(tsm_mr_create_attribute_group);
*/
void tsm_mr_free_attribute_group(const struct attribute_group *attr_grp)
{
+ struct tm_context *ctx;
+
if (!IS_ERR_OR_NULL(attr_grp)) {
+ ctx = container_of(attr_grp, struct tm_context, agrp);
+ scoped_guard(mutex, &idr_lock)
+ idr_remove(&tm_ctx_idr, ctx->tm->ctx_id);
kfree(attr_grp->bin_attrs);
- kfree(container_of(attr_grp, struct tm_context, agrp));
+ kfree(ctx);
}
}
EXPORT_SYMBOL_GPL(tsm_mr_free_attribute_group);
+
+#if defined(CONFIG_TSM_MEASUREMENTS)
+const struct tsm_measurements *tsm_default_tm(void)
+{
+ struct tm_context *ctx;
+ int next_id = 0;
+
+ guard(mutex)(&idr_lock);
+
+ ctx = idr_get_next(&tm_ctx_idr, &next_id);
+ if (!ctx)
+ return NULL;
+
+ return ctx->tm;
+}
+EXPORT_SYMBOL_GPL(tsm_default_tm);
+
+int tsm_mr_read(const struct tsm_measurements *tm, int idx,
+ u8 *digest, u32 digest_size)
+{
+ struct tm_context *ctx;
+ const struct tsm_measurement_register *mr;
+ int rc;
+
+ scoped_guard(mutex, &idr_lock)
+ ctx = idr_find(&tm_ctx_idr, tm->ctx_id);
+
+ if (IS_ERR_OR_NULL(ctx))
+ return -ENODEV;
+
+ if (!digest || (idx >= ctx->tm->nr_mrs) ||
+ (ctx->tm->mrs[idx].mr_size > digest_size) ||
+ !(ctx->tm->mrs[idx].mr_flags & TSM_MR_F_READABLE))
+ return -EINVAL;
+
+ mr = &ctx->tm->mrs[idx];
+
+ rc = __tsm_mr_read(ctx, mr, (char *)digest, 0, mr->mr_size);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tsm_mr_read);
+
+int tsm_mr_write(const struct tsm_measurements *tm, int idx,
+ u8 *digest, u32 digest_size)
+{
+ struct tm_context *ctx;
+ const struct tsm_measurement_register *mr;
+ int rc;
+
+ scoped_guard(mutex, &idr_lock)
+ ctx = idr_find(&tm_ctx_idr, tm->ctx_id);
+
+ if (IS_ERR_OR_NULL(ctx))
+ return -ENODEV;
+
+ if (!digest || (idx >= ctx->tm->nr_mrs) ||
+ !(ctx->tm->mrs[idx].mr_flags & TSM_MR_F_WRITABLE))
+ return -EINVAL;
+
+ /* partial writes are not supported */
+ if (ctx->tm->mrs[idx].mr_size != digest_size)
+ return -EINVAL;
+
+ mr = &ctx->tm->mrs[idx];
+
+ rc = __tsm_mr_write(ctx, mr, (char *)digest, mr->mr_size);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tsm_mr_write);
+#endif
diff --git a/include/linux/tsm-mr.h b/include/linux/tsm-mr.h
index 50a521f4ac97..43a0f761cd96 100644
--- a/include/linux/tsm-mr.h
+++ b/include/linux/tsm-mr.h
@@ -80,10 +80,36 @@ struct tsm_measurements {
int (*refresh)(const struct tsm_measurements *tm);
int (*write)(const struct tsm_measurements *tm,
const struct tsm_measurement_register *mr, const u8 *data);
+ int ctx_id;
};
const struct attribute_group *
tsm_mr_create_attribute_group(const struct tsm_measurements *tm);
void tsm_mr_free_attribute_group(const struct attribute_group *attr_grp);
+#if defined(CONFIG_TSM_MEASUREMENTS)
+const struct tsm_measurements *tsm_default_tm(void);
+int tsm_mr_read(const struct tsm_measurements *tm, int idx,
+ u8 *digest, u32 digest_size);
+int tsm_mr_write(const struct tsm_measurements *tm, int idx,
+ u8 *digest, u32 digest_size);
+#else
+static inline const struct tsm_measurements *tsm_default_tm(void)
+{
+ return NULL;
+}
+
+static inline int tsm_mr_read(const struct tsm_measurements *tm, int idx,
+ u8 *digest, u32 digest_size)
+{
+ return 0;
+}
+
+static inline int tsm_mr_write(const struct tsm_measurements *tm, int idx,
+ u8 *digest, u32 digest_size)
+{
+ return 0;
+}
+#endif
+
#endif
--
2.43.0
next prev parent reply other threads:[~2026-09-30 13:44 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-30 13:43 [PATCH RFC 0/3] security: ima: support TSM measurement registers Yeoreum Yun
2026-09-30 13:43 ` Yeoreum Yun [this message]
2026-09-30 13:55 ` [PATCH RFC 1/3] virt: coco: introduce tsm_default_tm() and tsm_mr_read()/write() sashiko-bot
2026-09-30 13:44 ` [PATCH RFC 2/3] security: IMA: introduce ima_mr structure Yeoreum Yun
2026-09-30 13:55 ` sashiko-bot
2026-09-30 13:44 ` [PATCH RFC 3/3] security: IMA: use TSM measurement registers Yeoreum Yun
2026-09-30 13:59 ` sashiko-bot
2026-10-01 11:27 ` [PATCH RFC 0/3] security: ima: support " Roberto Sassu
2026-10-01 11:45 ` Roberto Sassu
2026-10-01 14:24 ` Yeoreum Yun
2026-10-08 11:10 ` GONG Ruiqi
2026-10-01 15:18 ` Jason Gunthorpe
2026-10-01 16:39 ` Yeoreum Yun
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260930-ima_tgx_integration_v2-v1-1-722c35370548@arm.com \
--to=yeoreum.yun@arm.com \
--cc=aneesh.kumar@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=djbw@kernel.org \
--cc=dmitry.kasatkin@gmail.com \
--cc=eric.snowberg@oracle.com \
--cc=jgg@ziepe.ca \
--cc=jiri@resnulli.us \
--cc=jmorris@namei.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-integrity@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=paul@paul-moore.com \
--cc=roberto.sassu@huawei.com \
--cc=sami.mujawar@arm.com \
--cc=serge@hallyn.com \
--cc=steven.price@arm.com \
--cc=suzuki.poulose@arm.com \
--cc=zohar@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox