From: Jiri Pirko <jiri@resnulli.us>
To: linux-coco@lists.linux.dev
Cc: linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
x86@kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org,
jgg@ziepe.ca, david.quigley@intel.com, lukas@wunner.de,
ksinyuk@kernel.org, rodrigo.vivi@intel.com,
cedric.xing@intel.com, sameo@meta.com, drdeeglaze@gmail.com,
James.Bottomley@HansenPartnership.com, aik@amd.com,
jpiotrowski@nvidia.com, qinkun@google.com, pgonda@google.com,
jic23@kernel.org, alistair.francis@wdc.com, ankita@nvidia.com,
suzuki.poulose@arm.com, kas@kernel.org,
rick.p.edgecombe@intel.com, elena.reshetova@intel.com,
dave.hansen@linux.intel.com,
sathyanarayanan.kuppuswamy@linux.intel.com, peter.fang@intel.com
Subject: [PATCH RFC 17/20] attestation: Add CTLV operation handling
Date: Thu, 15 Oct 2026 16:50:50 +0200 [thread overview]
Message-ID: <20261015145053.3664509-18-jiri@resnulli.us> (raw)
In-Reply-To: <20261015145053.3664509-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@nvidia.com>
Translate CTLV evidence, MR and journal operations to the provider core and
wire the attestation family into the kernel build.
Assisted-by: Cursor: GPT-5.6 Sol
Assisted-by: Cursor: Claude Opus 5.5
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
Documentation/driver-api/attestation.rst | 4 +
drivers/Kconfig | 2 +
drivers/Makefile | 1 +
drivers/attestation/Makefile | 3 +-
drivers/attestation/core/core.c | 2 +
drivers/attestation/core/ctlv.c | 520 +++++++++++++++++++++++
6 files changed, 531 insertions(+), 1 deletion(-)
create mode 100644 drivers/attestation/core/ctlv.c
diff --git a/Documentation/driver-api/attestation.rst b/Documentation/driver-api/attestation.rst
index 3cddd853aaa0..5ce121ded05f 100644
--- a/Documentation/driver-api/attestation.rst
+++ b/Documentation/driver-api/attestation.rst
@@ -35,6 +35,10 @@ and event before invoking ``mr_extend``. A successful callback is followed
only by infallible publication, so userspace observes the same ordered
journal.
+``MR_READ`` uses ``mr_read_generation`` only to validate query continuation;
+the returned ``mr.generation`` is the journal boundary at which the values
+were read.
+
Teardown
========
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 9acc7f74c5c8..971db1f0192c 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -27,6 +27,8 @@ source "drivers/connector/Kconfig"
source "drivers/ctlv/Kconfig"
+source "drivers/attestation/Kconfig"
+
source "drivers/firmware/Kconfig"
source "drivers/fwctl/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index f2c0c3a367ea..2b4dfc8e256b 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -136,6 +136,7 @@ obj-$(CONFIG_INFINIBAND) += infiniband/
obj-y += firmware/
obj-$(CONFIG_FWCTL) += fwctl/
obj-$(CONFIG_CTLV) += ctlv/
+obj-$(CONFIG_ATTESTATION) += attestation/
obj-$(CONFIG_CRYPTO) += crypto/
obj-$(CONFIG_SUPERH) += sh/
obj-y += clocksource/
diff --git a/drivers/attestation/Makefile b/drivers/attestation/Makefile
index e7c9cb2dfec0..e520fee2e90d 100644
--- a/drivers/attestation/Makefile
+++ b/drivers/attestation/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_ATTESTATION) += attestation.o
-attestation-y := core/core.o core/events.o core/mr.o
+attestation-y := core/core.o core/ctlv.o core/events.o core/mr.o \
+ generated/ctlv_attestation_gen.o
diff --git a/drivers/attestation/core/core.c b/drivers/attestation/core/core.c
index 6db8ed093e93..3fb58f344663 100644
--- a/drivers/attestation/core/core.c
+++ b/drivers/attestation/core/core.c
@@ -326,6 +326,7 @@ int ctlv_attestation_op_pre(void *priv, struct ctlv_op_ctx *ctx)
}
return 0;
}
+EXPORT_SYMBOL_NS_GPL(ctlv_attestation_op_pre, "ATTESTATION");
void ctlv_attestation_op_post(void *priv, struct ctlv_op_ctx *ctx)
{
@@ -333,6 +334,7 @@ void ctlv_attestation_op_post(void *priv, struct ctlv_op_ctx *ctx)
mutex_unlock(&att->lock);
}
+EXPORT_SYMBOL_NS_GPL(ctlv_attestation_op_post, "ATTESTATION");
static int __init attestation_module_init(void)
{
diff --git a/drivers/attestation/core/ctlv.c b/drivers/attestation/core/ctlv.c
new file mode 100644
index 000000000000..ff19400843c2
--- /dev/null
+++ b/drivers/attestation/core/ctlv.c
@@ -0,0 +1,520 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <crypto/hash_info.h>
+#include <linux/cleanup.h>
+#include <linux/err.h>
+#include <linux/limits.h>
+#include <linux/slab.h>
+#include <linux/sort.h>
+#include <linux/string.h>
+
+#include "internal.h"
+
+static const struct attestation_evidence_supported_object *
+attestation_evidence_object_find(const struct attestation_evidence_caps *caps, const char *format)
+{
+ size_t index;
+
+ for (index = 0; index < caps->objects_count; index++) {
+ const struct attestation_evidence_supported_object *object = &caps->objects[index];
+
+ if (!strcmp(object->format, format))
+ return object;
+ }
+ return NULL;
+}
+
+static int attestation_device_caps_put(struct attestation *att, struct ctlv_cursor *reply)
+{
+ const struct attestation_provider *provider = att->provider;
+ struct ctlv_cursor caps_nest, group, object;
+ bool ok = true;
+ size_t index;
+ u64 flags;
+
+ if (!ctlv_attestation_device_caps_start(reply, &caps_nest))
+ return -EMSGSIZE;
+ if (provider->evidence_caps) {
+ const struct attestation_evidence_caps *caps = provider->evidence_caps;
+ u64 blob_class = CTLV_ATTESTATION_EVIDENCE_BLOB_CLASS_PRIMARY;
+ u64 representation = CTLV_ATTESTATION_EVIDENCE_REPRESENTATION_RAW;
+ u64 max_output_length = caps->max_total_output_length;
+
+ if (!ctlv_attestation_cap_evidence_start(&caps_nest, &group))
+ return -EMSGSIZE;
+ ok &= ctlv_attestation_cap_min_challenge_length_put(&group,
+ caps->min_challenge_length);
+ ok &= ctlv_attestation_cap_max_challenge_length_put(&group,
+ caps->max_challenge_length);
+ ok &= ctlv_attestation_cap_max_total_output_length_put(&group, max_output_length);
+ for (index = 0; index < caps->objects_count; index++) {
+ const struct attestation_evidence_supported_object *cap =
+ &caps->objects[index];
+
+ if (!ctlv_attestation_cap_object_start(&group, &object)) {
+ ok = false;
+ break;
+ }
+ ok &= ctlv_attestation_cap_blob_class_put(&object, blob_class);
+ ok &= ctlv_attestation_cap_format_put(&object, cap->format);
+ ok &= ctlv_attestation_cap_representation_put(&object, representation);
+ ok &= ctlv_attestation_cap_max_length_put(&object, cap->max_length);
+ ctlv_nest_end(&object);
+ }
+ ctlv_nest_end(&group);
+ }
+ if (provider->mrs_count) {
+ if (!ctlv_attestation_cap_mr_start(&caps_nest, &group))
+ return -EMSGSIZE;
+ flags = 0;
+ if (provider->mr_read)
+ flags |= CTLV_ATTESTATION_MR_DEVICE_CAPS_READ;
+ if (provider->mr_extend)
+ flags |= CTLV_ATTESTATION_MR_DEVICE_CAPS_EXTEND;
+ ok &= ctlv_attestation_cap_mr_flags_put(&group, flags);
+ ctlv_nest_end(&group);
+ }
+ ctlv_nest_end(&caps_nest);
+ return ok ? 0 : -EMSGSIZE;
+}
+
+int ctlv_attestation_device_get_action(void *priv, struct ctlv_op_ctx *ctx,
+ const struct ctlv_cursor *request, struct ctlv_cursor *reply)
+{
+ struct attestation *att = priv;
+ struct ctlv_cursor info;
+ int ret;
+
+ ret = attestation_device_caps_put(att, reply);
+ if (ret)
+ return ret;
+ if (!ctlv_attestation_device_info_start(reply, &info))
+ return -EMSGSIZE;
+ ret = ctlv_stub_fill(ctx, request, &info);
+ ctlv_nest_end(&info);
+ return ret;
+}
+
+static int
+attestation_evidence_decode_objects(struct attestation *att, struct ctlv_op_ctx *ctx,
+ const struct ctlv_cursor *request,
+ struct attestation_evidence_request *decoded,
+ struct attestation_evidence_object_request **objects_out)
+{
+ const struct attestation_evidence_caps *caps = att->provider->evidence_caps;
+ struct attestation_evidence_object_request *objects;
+ struct ctlv_cursor object;
+ size_t count = 0, index = 0, previous;
+
+ ctlv_attestation_evidence_get_evidence_object_for_each(&object, request) count++;
+ objects = kcalloc(count, sizeof(*objects), GFP_KERNEL);
+ if (!objects)
+ return -ENOMEM;
+ ctlv_attestation_evidence_get_evidence_object_for_each(&object, request)
+ {
+ const struct attestation_evidence_supported_object *supported;
+ const char *format;
+ size_t total = 0;
+
+ format = ctlv_attestation_evidence_get_object_evidence_format_get(&object);
+ supported = attestation_evidence_object_find(caps, format);
+ if (!supported) {
+ kfree(objects);
+ return -EOPNOTSUPP;
+ }
+ for (previous = 0; previous < index; previous++)
+ if (objects[previous].supported_object == supported) {
+ kfree(objects);
+ return -EINVAL;
+ }
+ objects[index].supported_object = supported;
+ objects[index].output =
+ ctlv_attestation_evidence_get_object_evidence_data_resolve(ctx, &object);
+ if (IS_ERR(objects[index].output)) {
+ int ret = PTR_ERR(objects[index].output);
+
+ objects[index].output = NULL;
+ while (index)
+ ctlv_blob_put(objects[--index].output);
+ kfree(objects);
+ return ret;
+ }
+ if (ctlv_blob_len(objects[index].output) < supported->max_length) {
+ for (previous = 0; previous <= index; previous++)
+ ctlv_blob_put(objects[previous].output);
+ kfree(objects);
+ return -EMSGSIZE;
+ }
+ for (previous = 0; previous <= index; previous++) {
+ if (check_add_overflow(total, ctlv_blob_len(objects[previous].output),
+ &total) ||
+ total > caps->max_total_output_length) {
+ for (previous = 0; previous <= index; previous++)
+ ctlv_blob_put(objects[previous].output);
+ kfree(objects);
+ return -E2BIG;
+ }
+ }
+ index++;
+ }
+ decoded->objects = objects;
+ decoded->objects_count = count;
+ *objects_out = objects;
+ return 0;
+}
+
+static int attestation_evidence_request_decode(struct attestation *att, struct ctlv_op_ctx *ctx,
+ const struct ctlv_cursor *request,
+ struct attestation_evidence_request *decoded,
+ struct attestation_evidence_object_request **objects)
+{
+ const struct attestation_evidence_caps *caps = att->provider->evidence_caps;
+ u32 challenge_length;
+
+ decoded->challenge =
+ ctlv_attestation_evidence_get_evidence_challenge_get(request, &challenge_length);
+ decoded->challenge_length = challenge_length;
+ if (challenge_length < caps->min_challenge_length ||
+ challenge_length > caps->max_challenge_length)
+ return -EINVAL;
+ return attestation_evidence_decode_objects(att, ctx, request, decoded, objects);
+}
+
+static void attestation_evidence_request_free(struct attestation_evidence_object_request *objects,
+ size_t count)
+{
+ while (count) {
+ count--;
+ if (objects[count].output)
+ ctlv_blob_put(objects[count].output);
+ }
+ kfree(objects);
+}
+
+int ctlv_attestation_evidence_get_action(void *priv, struct ctlv_op_ctx *ctx,
+ const struct ctlv_cursor *request,
+ struct ctlv_cursor *reply)
+{
+ struct attestation_evidence_object_request *objects = NULL;
+ struct attestation_evidence_request decoded = {};
+ struct attestation_evidence_result result = {};
+ struct attestation *att = priv;
+ bool mr_dependent = false;
+ size_t index;
+ int put_ret;
+ int ret;
+
+ ret = attestation_evidence_request_decode(att, ctx, request, &decoded, &objects);
+ if (ret)
+ goto out;
+ result.object_lengths =
+ kcalloc(decoded.objects_count, sizeof(*result.object_lengths), GFP_KERNEL);
+ if (!result.object_lengths) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ for (index = 0; index < decoded.objects_count; index++)
+ mr_dependent |= decoded.objects[index].supported_object->binds_mrs;
+ ret = att->provider->evidence_get(att, &decoded, &result);
+ if (ret)
+ goto out;
+ for (index = 0; index < decoded.objects_count; index++) {
+ if (result.object_lengths[index] >
+ decoded.objects[index].supported_object->max_length ||
+ result.object_lengths[index] > ctlv_blob_len(decoded.objects[index].output)) {
+ ret = -E2BIG;
+ goto out;
+ }
+ }
+ for (index = 0; index < decoded.objects_count; index++) {
+ put_ret = ctlv_blob_put(decoded.objects[index].output);
+ objects[index].output = NULL;
+ if (!ret)
+ ret = put_ret;
+ }
+ if (ret)
+ goto out;
+ if (mr_dependent && !ctlv_attestation_mr_generation_put(reply, att->log->generation)) {
+ ret = -EMSGSIZE;
+ goto out;
+ }
+ for (index = 0; index < decoded.objects_count; index++)
+ if (!ctlv_attestation_evidence_object_length_put(reply,
+ result.object_lengths[index])) {
+ ret = -EMSGSIZE;
+ goto out;
+ }
+out:
+ kfree(result.object_lengths);
+ attestation_evidence_request_free(objects, decoded.objects_count);
+ return ret;
+}
+
+int ctlv_attestation_mr_get_action(void *priv, struct ctlv_op_ctx *ctx,
+ const struct ctlv_cursor *request, struct ctlv_cursor *reply)
+{
+ struct attestation *att = priv;
+ struct attestation_mr *mr;
+ u64 id = ctlv_attestation_mr_get_mr_id_get(request);
+
+ if (id > UINT_MAX)
+ return -ERANGE;
+ mr = attestation_mr_lookup_live(att, id);
+ return IS_ERR(mr) ? PTR_ERR(mr) : attestation_mr_props_encode(reply, mr, false);
+}
+
+int ctlv_attestation_mr_dump_query(void *priv, struct ctlv_op_ctx *ctx,
+ const struct ctlv_cursor *request, struct ctlv_cursor *reply)
+{
+ struct attestation *att = priv;
+ struct attestation_mr *mr;
+ struct ctlv_cursor nested;
+ unsigned long id;
+ u64 cursor = ctlv_op_query_cursor(ctx);
+ unsigned int generation = att->log->generation;
+ int ret;
+
+ if (cursor && ctlv_op_query_generation(ctx) != generation)
+ return -ESTALE;
+ id = cursor ? cursor - 1 : 0;
+ mr = xa_find(&att->mrs, &id, UINT_MAX, XA_PRESENT);
+ while (mr) {
+ if (!ctlv_attestation_mr_item_start(reply, &nested))
+ return ctlv_op_query_more(ctx, generation, id + 1);
+ ret = attestation_mr_props_encode(&nested, mr, true);
+ ctlv_nest_end(&nested);
+ if (ret)
+ return ret;
+ mr = xa_find_after(&att->mrs, &id, UINT_MAX, XA_PRESENT);
+ }
+ return ctlv_op_query_done(ctx, generation);
+}
+
+static int attestation_mr_values_put(struct ctlv_cursor *reply,
+ const struct attestation_digest_set *values)
+{
+ struct ctlv_cursor nested;
+ size_t index;
+ bool ok;
+
+ for (index = 0; index < values->values_count; index++) {
+ const struct attestation_digest *value = &values->values[index];
+ enum hash_algo algorithm = value->algorithm;
+ size_t length = hash_digest_size[algorithm];
+
+ if (!ctlv_attestation_mr_value_start(reply, &nested))
+ return -EMSGSIZE;
+ ok = ctlv_attestation_mr_hash_algo_put(&nested, algorithm);
+ ok &= ctlv_attestation_mr_data_put(&nested, value->data, length);
+ ctlv_nest_end(&nested);
+ if (!ok)
+ return -EMSGSIZE;
+ }
+ return 0;
+}
+
+int ctlv_attestation_mr_read_query(void *priv, struct ctlv_op_ctx *ctx,
+ const struct ctlv_cursor *request, struct ctlv_cursor *reply)
+{
+ struct attestation_digest_set values = {};
+ struct attestation *att = priv;
+ struct attestation_mr *mr;
+ u64 id;
+ int ret;
+
+ if (ctlv_op_query_cursor(ctx) &&
+ ctlv_op_query_generation(ctx) != att->mr_read_generation)
+ return -ESTALE;
+ id = ctlv_attestation_mr_read_mr_id_get(request);
+ if (id > UINT_MAX)
+ return -ERANGE;
+ mr = attestation_mr_lookup_live(att, id);
+ if (IS_ERR(mr))
+ return PTR_ERR(mr);
+ if (!mr->props->readable)
+ return -EOPNOTSUPP;
+ values.values_count = mr->props->algorithms_count;
+ values.values = kcalloc(values.values_count, sizeof(*values.values), GFP_KERNEL);
+ if (!values.values)
+ return -ENOMEM;
+ for (id = 0; id < values.values_count; id++)
+ values.values[id].algorithm = mr->props->algorithms[id];
+ ret = att->provider->mr_read(att, mr->props->id, &values);
+ if (!ret)
+ ret = attestation_mr_values_validate(mr, &values);
+ if (!ret && !ctlv_attestation_mr_generation_put(reply, att->log->generation))
+ ret = -EMSGSIZE;
+ if (!ret)
+ ret = attestation_mr_values_put(reply, &values);
+ kfree(values.values);
+ if (ret)
+ return ret;
+ return ctlv_op_query_done(ctx, att->mr_read_generation);
+}
+
+static int attestation_digest_compare(const void *left, const void *right)
+{
+ const struct attestation_digest *a = left;
+ const struct attestation_digest *b = right;
+
+ return (int)a->algorithm - (int)b->algorithm;
+}
+
+static int attestation_mr_extend_decode(const struct ctlv_cursor *request,
+ struct attestation_digest_set *values)
+{
+ struct ctlv_cursor item;
+ size_t count = 0, index = 0;
+
+ ctlv_attestation_mr_extend_mr_value_for_each(&item, request) count++;
+ values->values = kcalloc(count, sizeof(*values->values), GFP_KERNEL);
+ if (!values->values)
+ return -ENOMEM;
+ values->values_count = count;
+ ctlv_attestation_mr_extend_mr_value_for_each(&item, request)
+ {
+ struct attestation_digest *value = &values->values[index++];
+ u32 length;
+ const void *data;
+ u64 algorithm;
+
+ algorithm =
+ ctlv_attestation_mr_extend_value_mr_hash_algo_get(&item);
+ if (algorithm >= HASH_ALGO__LAST || !hash_digest_size[algorithm])
+ return -EINVAL;
+ data = ctlv_attestation_mr_extend_value_mr_data_get(&item, &length);
+ if (length != hash_digest_size[algorithm])
+ return -EINVAL;
+ value->algorithm = algorithm;
+ memcpy(value->data, data, length);
+ }
+ sort(values->values, values->values_count, sizeof(*values->values),
+ attestation_digest_compare, NULL);
+ return 0;
+}
+
+int ctlv_attestation_mr_extend_action(void *priv, struct ctlv_op_ctx *ctx,
+ const struct ctlv_cursor *request, struct ctlv_cursor *reply)
+{
+ struct attestation_digest_set values = {};
+ struct attestation_mr_change *change;
+ const struct attestation_mr_log_entry *entry;
+ struct attestation *att = priv;
+ struct attestation_mr *mr;
+ u64 id;
+ int ret;
+
+ id = ctlv_attestation_mr_extend_mr_id_get(request);
+ if (id > UINT_MAX)
+ return -ERANGE;
+ mr = attestation_mr_lookup_live(att, id);
+ if (IS_ERR(mr))
+ return PTR_ERR(mr);
+ if (!mr->props->extendable)
+ return -EOPNOTSUPP;
+ ret = attestation_mr_extend_decode(request, &values);
+ if (ret)
+ goto out_values;
+ ret = attestation_mr_values_validate(mr, &values);
+ if (ret)
+ goto out_values;
+ change = attestation_mr_change_prepare(att, mr, &values);
+ if (IS_ERR(change)) {
+ ret = PTR_ERR(change);
+ goto out_values;
+ }
+ entry = attestation_mr_extend_locked(att, change);
+ if (IS_ERR(entry))
+ ret = PTR_ERR(entry);
+ else if (!ctlv_attestation_mr_generation_put(reply, entry->mr_generation))
+ ret = -EMSGSIZE;
+ attestation_mr_change_free(change);
+out_values:
+ kfree(values.values);
+ return ret;
+}
+
+static bool attestation_log_selected(const unsigned int *ids, size_t count, unsigned int id)
+{
+ size_t index;
+
+ if (!count)
+ return true;
+ for (index = 0; index < count; index++)
+ if (ids[index] == id)
+ return true;
+ return false;
+}
+
+int ctlv_attestation_mr_log_get_query(void *priv, struct ctlv_op_ctx *ctx,
+ const struct ctlv_cursor *request, struct ctlv_cursor *reply)
+{
+ struct attestation *att = priv;
+ struct attestation_mr_log_entry *entry;
+ struct ctlv_cursor item, nested;
+ unsigned int ids[256];
+ size_t ids_count = 0, index;
+ unsigned int start, end;
+ unsigned long xa_index;
+ u64 boundary;
+ u64 cursor = ctlv_op_query_cursor(ctx);
+ int ret;
+
+ ctlv_attestation_mr_log_get_mr_selection_for_each(&item, request)
+ {
+ u64 id = ctlv_attestation_mr_log_get_selection_mr_id_get(&item);
+
+ if (id > UINT_MAX)
+ return -ERANGE;
+ for (index = 0; index < ids_count; index++)
+ if (ids[index] == id)
+ return -EINVAL;
+ ids[ids_count++] = id;
+ }
+ if (cursor)
+ boundary = ctlv_op_query_generation(ctx);
+ else
+ boundary = att->log->generation;
+ if (boundary > UINT_MAX || boundary > att->log->generation)
+ return -ESTALE;
+ end = boundary;
+ if (ctlv_attestation_mr_log_get_mr_end_generation_present(request)) {
+ u64 requested_end = ctlv_attestation_mr_log_get_mr_end_generation_get(request);
+
+ end = min_t(u64, end, requested_end);
+ }
+ start = 1;
+ if (ctlv_attestation_mr_log_get_mr_start_generation_present(request)) {
+ u64 value = ctlv_attestation_mr_log_get_mr_start_generation_get(request);
+
+ if (value > UINT_MAX)
+ return -EINVAL;
+ start = value;
+ }
+ if (att->log->generation && start > end)
+ return -EINVAL;
+ if (!cursor && att->log->generation) {
+ if (!ctlv_attestation_mr_start_generation_put(reply, start) ||
+ !ctlv_attestation_mr_end_generation_put(reply, end))
+ return -EMSGSIZE;
+ }
+ xa_index = cursor ? cursor : start;
+ entry = xa_find(&att->log->entries, &xa_index, end, XA_PRESENT);
+ while (entry && !attestation_log_selected(ids, ids_count, entry->mr_id))
+ entry = xa_find_after(&att->log->entries, &xa_index, end, XA_PRESENT);
+ if (!entry)
+ return ctlv_op_query_done(ctx, boundary);
+ if (!cursor)
+ return ctlv_op_query_more(ctx, boundary, entry->mr_generation);
+ if (!ctlv_attestation_log_entry_start(reply, &nested))
+ return -EMSGSIZE;
+ ret = attestation_mr_log_entry_encode(&nested, entry);
+ ctlv_nest_end(&nested);
+ if (ret)
+ return ret;
+ entry = xa_find_after(&att->log->entries, &xa_index, end, XA_PRESENT);
+ while (entry && !attestation_log_selected(ids, ids_count, entry->mr_id))
+ entry = xa_find_after(&att->log->entries, &xa_index, end, XA_PRESENT);
+ if (entry)
+ return ctlv_op_query_more(ctx, boundary, entry->mr_generation);
+ return ctlv_op_query_done(ctx, boundary);
+}
--
2.56.0
next prev parent reply other threads:[~2026-10-15 14:52 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-15 14:50 [PATCH RFC 00/20] attestation: Add a common subsystem and TDX support Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 01/20] ctlv: Add the schema language and generator Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 02/20] ctlv: Add the UAPI wire format and family API Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 03/20] ctlv: Add the root family specification and generated files Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 04/20] Documentation: ctlv: Add userspace ABI Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 05/20] ctlv: Prepare message input handling Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 06/20] ctlv: Prepare blob descriptor validation Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 07/20] ctlv: Prepare schema validation Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 08/20] ctlv: Prepare message output handling Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 09/20] ctlv: Prepare VA blob handling Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 10/20] ctlv: Prepare event queue support Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 11/20] ctlv: Prepare runtime introspection Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 12/20] ctlv: Add device and operation dispatch Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 13/20] Documentation: ctlv: Describe how to write a family Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 14/20] attestation: Add the base family specification and generated files Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 15/20] attestation: Prepare provider and instance core Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 16/20] attestation: Prepare measurement register journal Jiri Pirko
2026-10-15 14:50 ` Jiri Pirko [this message]
2026-10-15 14:50 ` [PATCH RFC 18/20] tdx-guest: Expose the native attestation service API Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 19/20] attestation: Add the TDX family specification and generated files Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 20/20] attestation: Add the TDX family implementation Jiri Pirko
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=20261015145053.3664509-18-jiri@resnulli.us \
--to=jiri@resnulli.us \
--cc=James.Bottomley@HansenPartnership.com \
--cc=aik@amd.com \
--cc=alistair.francis@wdc.com \
--cc=ankita@nvidia.com \
--cc=cedric.xing@intel.com \
--cc=dave.hansen@linux.intel.com \
--cc=david.quigley@intel.com \
--cc=drdeeglaze@gmail.com \
--cc=elena.reshetova@intel.com \
--cc=jgg@ziepe.ca \
--cc=jic23@kernel.org \
--cc=jpiotrowski@nvidia.com \
--cc=kas@kernel.org \
--cc=ksinyuk@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=linux-api@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lukas@wunner.de \
--cc=peter.fang@intel.com \
--cc=pgonda@google.com \
--cc=qinkun@google.com \
--cc=rick.p.edgecombe@intel.com \
--cc=rodrigo.vivi@intel.com \
--cc=sameo@meta.com \
--cc=sathyanarayanan.kuppuswamy@linux.intel.com \
--cc=suzuki.poulose@arm.com \
--cc=x86@kernel.org \
/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