new file mode 100644
@@ -0,0 +1,265 @@
+From 0eedd4ddd7c924f9cbb4ac496b3fda699435c3cf Mon Sep 17 00:00:00 2001
+From: Zoltan Fridrich <zfridric@redhat.com>
+Date: Thu, 2 Jul 2026 10:54:47 +0200
+Subject: [PATCH] rpc: add recursion depth limit into RPC attribute parsing
+ (CVE-2026-13757)
+
+A DoS was possible when client sent request to a server with deeply
+nested attributes causing stack exhaustion on the server.
+This patch adds a recursion limit on all server entry points to
+prevent such attacks.
+
+Signed-off-by: Zoltan Fridrich <zfridric@redhat.com>
+
+Upstream-Status: Backport [import from ubuntu p11-kit_0.25.3-4ubuntu2.2.debian.tar.xz
+Upstream commit https://github.com/p11-glue/p11-kit/commit/0eedd4ddd7c924f9cbb4ac496b3fda699435c3cf]
+CVE: CVE-2026-13757
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ p11-kit/rpc-message.c | 39 +++++++++++++++++++++++++++++++++-----
+ p11-kit/rpc-message.h | 10 +++++++++-
+ p11-kit/test-rpc-message.c | 39 ++++++++++++++++++++++++++++++++++++--
+ p11-kit/test-rpc.c | 27 ++++++++++++++++++++++++++
+ 4 files changed, 107 insertions(+), 8 deletions(-)
+
+diff --git a/p11-kit/rpc-message.c b/p11-kit/rpc-message.c
+index 09d7f33..d6f0aad 100644
+--- a/p11-kit/rpc-message.c
++++ b/p11-kit/rpc-message.c
+@@ -903,6 +903,15 @@ map_attribute_to_value_type (CK_ATTRIBUTE_TYPE type)
+ }
+ }
+
++static bool
++p11_rpc_buffer_get_attribute_array_value_wrapper (p11_buffer *buffer,
++ size_t *offset,
++ void *value,
++ CK_ULONG *value_length)
++{
++ return p11_rpc_buffer_get_attribute_array_value (buffer, offset, value, value_length, 0);
++}
++
+ typedef struct {
+ p11_rpc_value_type type;
+ p11_rpc_value_encoder encode;
+@@ -912,7 +921,7 @@ typedef struct {
+ static p11_rpc_attribute_serializer p11_rpc_attribute_serializers[] = {
+ { P11_RPC_VALUE_BYTE, p11_rpc_buffer_add_byte_value, p11_rpc_buffer_get_byte_value },
+ { P11_RPC_VALUE_ULONG, p11_rpc_buffer_add_ulong_value, p11_rpc_buffer_get_ulong_value },
+- { P11_RPC_VALUE_ATTRIBUTE_ARRAY, p11_rpc_buffer_add_attribute_array_value, p11_rpc_buffer_get_attribute_array_value },
++ { P11_RPC_VALUE_ATTRIBUTE_ARRAY, p11_rpc_buffer_add_attribute_array_value, p11_rpc_buffer_get_attribute_array_value_wrapper },
+ { P11_RPC_VALUE_MECHANISM_TYPE_ARRAY, p11_rpc_buffer_add_mechanism_type_array_value, p11_rpc_buffer_get_mechanism_type_array_value },
+ { P11_RPC_VALUE_DATE, p11_rpc_buffer_add_date_value, p11_rpc_buffer_get_date_value },
+ { P11_RPC_VALUE_BYTE_ARRAY, p11_rpc_buffer_add_byte_array_value, p11_rpc_buffer_get_byte_array_value }
+@@ -1142,7 +1151,8 @@ bool
+ p11_rpc_buffer_get_attribute_array_value (p11_buffer *buffer,
+ size_t *offset,
+ void *value,
+- CK_ULONG *value_length)
++ CK_ULONG *value_length,
++ size_t depth)
+ {
+ uint32_t count, i;
+ CK_ATTRIBUTE *attr, temp;
+@@ -1157,7 +1167,7 @@ p11_rpc_buffer_get_attribute_array_value (p11_buffer *buffer,
+ attr = value;
+
+ for (i = 0; i < count; i++) {
+- if (!p11_rpc_buffer_get_attribute (buffer, offset, attr))
++ if (!p11_rpc_buffer_get_attribute_recursive (buffer, offset, attr, depth))
+ return false;
+ if (value)
+ attr++;
+@@ -1255,12 +1265,26 @@ bool
+ p11_rpc_buffer_get_attribute (p11_buffer *buffer,
+ size_t *offset,
+ CK_ATTRIBUTE *attr)
++{
++ return p11_rpc_buffer_get_attribute_recursive (buffer, offset, attr, 0);
++}
++
++bool
++p11_rpc_buffer_get_attribute_recursive (p11_buffer *buffer,
++ size_t *offset,
++ CK_ATTRIBUTE *attr,
++ size_t depth)
+ {
+ uint32_t type, length, decode_length;
+ unsigned char validity;
+ p11_rpc_attribute_serializer *serializer;
+ p11_rpc_value_type value_type;
+
++ if (depth > P11_RPC_MAX_RECURSION_DEPTH) {
++ p11_debug ("recursion depth limit reached");
++ return false;
++ }
++
+ /* The attribute type */
+ if (!p11_rpc_buffer_get_uint32 (buffer, offset, &type))
+ return false;
+@@ -1284,8 +1308,13 @@ p11_rpc_buffer_get_attribute (p11_buffer *buffer,
+ assert (value_type < ELEMS (p11_rpc_attribute_serializers));
+ serializer = &p11_rpc_attribute_serializers[value_type];
+ assert (serializer != NULL);
+- if (!serializer->decode (buffer, offset, attr->pValue, &attr->ulValueLen))
+- return false;
++ if (value_type == P11_RPC_VALUE_ATTRIBUTE_ARRAY) {
++ if (!p11_rpc_buffer_get_attribute_array_value (buffer, offset, attr->pValue, &attr->ulValueLen, depth + 1))
++ return false;
++ } else {
++ if (!serializer->decode (buffer, offset, attr->pValue, &attr->ulValueLen))
++ return false;
++ }
+ if (!attr->pValue) {
+ decode_length = attr->ulValueLen;
+ attr->ulValueLen = length;
+diff --git a/p11-kit/rpc-message.h b/p11-kit/rpc-message.h
+index f171fc4..671a60d 100644
+--- a/p11-kit/rpc-message.h
++++ b/p11-kit/rpc-message.h
+@@ -44,6 +44,8 @@
+ #include "pkcs11.h"
+ #include "pkcs11x.h"
+
++#define P11_RPC_MAX_RECURSION_DEPTH 8
++
+ /* The calls, must be in sync with array below */
+ enum {
+ P11_RPC_CALL_ERROR = 0,
+@@ -441,6 +443,11 @@ bool p11_rpc_buffer_get_attribute (p11_buffer *buffer,
+ size_t *offset,
+ CK_ATTRIBUTE *attr);
+
++bool p11_rpc_buffer_get_attribute_recursive (p11_buffer *buffer,
++ size_t *offset,
++ CK_ATTRIBUTE *attr,
++ size_t depth);
++
+ void p11_rpc_buffer_add_byte_value (p11_buffer *buffer,
+ const void *value,
+ CK_ULONG value_length);
+@@ -468,7 +475,8 @@ bool p11_rpc_buffer_get_attribute_array_value
+ (p11_buffer *buffer,
+ size_t *offset,
+ void *value,
+- CK_ULONG *value_length);
++ CK_ULONG *value_length,
++ size_t depth);
+
+ void p11_rpc_buffer_add_mechanism_type_array_value
+ (p11_buffer *buffer,
+diff --git a/p11-kit/test-rpc-message.c b/p11-kit/test-rpc-message.c
+index 4c11ea5..f00f2f1 100644
+--- a/p11-kit/test-rpc-message.c
++++ b/p11-kit/test-rpc-message.c
+@@ -594,11 +594,11 @@ test_attribute_array_value (void)
+ assert (!p11_buffer_failed (&buffer));
+
+ offset2 = offset;
+- ret = p11_rpc_buffer_get_attribute_array_value(&buffer, &offset, NULL, &val_size);
++ ret = p11_rpc_buffer_get_attribute_array_value(&buffer, &offset, NULL, &val_size, 0);
+ assert_num_eq (true, ret);
+
+ offset = offset2;
+- ret = p11_rpc_buffer_get_attribute_array_value(&buffer, &offset, val, &val_size);
++ ret = p11_rpc_buffer_get_attribute_array_value(&buffer, &offset, val, &val_size, 0);
+ assert_num_eq (true, ret);
+ assert_num_eq (val[0].type, CKA_MODIFIABLE);
+ assert_num_eq (*(CK_BBOOL *)val[0].pValue, CK_TRUE);
+@@ -806,6 +806,40 @@ test_message_write (void)
+ p11_buffer_uninit (&buffer);
+ }
+
++static void
++test_attribute_recursion_limit (void)
++{
++ bool ret;
++ p11_buffer buffer;
++ size_t offset = 0;
++ CK_BBOOL truev = CK_TRUE;
++ CK_ATTRIBUTE attrs_out;
++ CK_ATTRIBUTE attrs[P11_RPC_MAX_RECURSION_DEPTH + 2];
++ for (size_t i = 0; i <= P11_RPC_MAX_RECURSION_DEPTH; i++) {
++ attrs[i].type = CKA_WRAP_TEMPLATE;
++ attrs[i].pValue = &attrs[i + 1];
++ attrs[i].ulValueLen = sizeof (CK_ATTRIBUTE);
++ }
++ attrs[P11_RPC_MAX_RECURSION_DEPTH + 1].type = CKA_ENCRYPT;
++ attrs[P11_RPC_MAX_RECURSION_DEPTH + 1].pValue = &truev;
++ attrs[P11_RPC_MAX_RECURSION_DEPTH + 1].ulValueLen = sizeof (CK_BBOOL);
++
++ ret = p11_buffer_init (&buffer, 0);
++ assert_num_eq (true, ret);
++ p11_rpc_buffer_add_attribute_array_value (&buffer, attrs, ELEMS(attrs));
++ assert_num_eq (true, !p11_buffer_failed (&buffer));
++
++ /* Skip the array count */
++ ret = p11_rpc_buffer_get_uint32(&buffer, &offset, NULL);
++ assert_num_eq (true, ret);
++
++ /* Hit recursion limit */
++ ret = p11_rpc_buffer_get_attribute(&buffer, &offset, &attrs_out);
++ assert_num_eq (false, ret);
++
++ p11_buffer_uninit (&buffer);
++}
++
+ #include "test-mock.c"
+
+ static CK_MECHANISM_TYPE mechanisms[] = {
+@@ -848,6 +882,7 @@ main (int argc,
+ p11_test (test_byte_array_value, "/rpc-message/byte-array-value");
+ p11_test (test_mechanism_value, "/rpc-message/mechanism-value");
+ p11_test (test_message_write, "/rpc-message/message-write");
++ p11_test (test_attribute_recursion_limit, "/rpc-message/attribute-recursion-limit");
+
+ test_mock_add_tests ("/rpc-message", NULL);
+
+diff --git a/p11-kit/test-rpc.c b/p11-kit/test-rpc.c
+index f214509..6059b89 100644
+--- a/p11-kit/test-rpc.c
++++ b/p11-kit/test-rpc.c
+@@ -700,6 +700,32 @@ test_mechanism_unsupported (void *module)
+ teardown_mock_module (rpc_module);
+ }
+
++static void
++test_recursion_limit (void *module)
++{
++ CK_FUNCTION_LIST_PTR rpc_module;
++ CK_SESSION_HANDLE session;
++ CK_RV rv;
++ CK_BBOOL val;
++ CK_ATTRIBUTE attrs[P11_RPC_MAX_RECURSION_DEPTH + 2];
++ for (size_t i = 0; i <= P11_RPC_MAX_RECURSION_DEPTH; i++) {
++ attrs[i].type = CKA_WRAP_TEMPLATE;
++ attrs[i].pValue = &attrs[i + 1];
++ attrs[i].ulValueLen = sizeof (CK_ATTRIBUTE);
++ }
++ attrs[P11_RPC_MAX_RECURSION_DEPTH + 1].type = CKA_ENCRYPT;
++ attrs[P11_RPC_MAX_RECURSION_DEPTH + 1].pValue = &val;
++ attrs[P11_RPC_MAX_RECURSION_DEPTH + 1].ulValueLen = sizeof (CK_BBOOL);
++
++ rpc_module = setup_test_rpc_module (&test_normal_vtable, module, &session);
++
++ /* Hit recursion limit */
++ rv = (rpc_module->C_GetAttributeValue) (session, MOCK_PUBLIC_KEY_PREFIX, attrs, 1);
++ assert_num_eq (rv, CKR_DEVICE_ERROR);
++
++ teardown_mock_module (rpc_module);
++}
++
+ #ifdef OS_UNIX
+
+ static void
+@@ -805,6 +831,7 @@ main (int argc,
+ p11_testx (test_get_slot_list_no_device, &mock_module_v3_no_slots, "/rpc3/get-slot-list-no-device");
+ p11_testx (test_simultaneous_functions, &mock_module_v3_no_slots, "/rpc3/simultaneous-functions");
+ p11_testx (test_mechanism_unsupported, &mock_module_v3, "/rpc3/mechanism-unsupported");
++ p11_testx (test_recursion_limit, &mock_module_v3, "/rpc3/recursion-limit");
+
+ #ifdef OS_UNIX
+ p11_testx (test_fork_and_reinitialize, &mock_module_v3_no_slots, "/rpc3/fork-and-reinitialize");
+--
+2.43.0
+
@@ -12,6 +12,7 @@ DEPENDS:append = "${@' glib-2.0' if d.getVar('GTKDOC_ENABLED') == 'True' else ''
SRC_URI = "gitsm://github.com/p11-glue/p11-kit;branch=master;protocol=https \
file://fix-parallel-build-failures.patch \
+ file://CVE-2026-13757.patch \
"
SRCREV = "917e02a3211dabbdea4b079cb598581dce84fda1"
S = "${WORKDIR}/git"
Pick patch according to [2] [1] https://nvd.nist.gov/vuln/detail/cve-2026-13757 [2] https://ubuntu.com/security/CVE-2026-13757 Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> --- .../p11-kit/files/CVE-2026-13757.patch | 265 ++++++++++++++++++ .../recipes-support/p11-kit/p11-kit_0.25.3.bb | 1 + 2 files changed, 266 insertions(+) create mode 100644 meta/recipes-support/p11-kit/files/CVE-2026-13757.patch