p11-kit: Fix CVE-2026-13757

Pick patch according to [2]

[1] https://nvd.nist.gov/vuln/detail/cve-2026-13757
[2] https://ubuntu.com/security/CVE-2026-13757

(From OE-Core rev: 1233224dcb13924b1366775a71fdf0ce72e3a589)

Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Vijay Anusuri
2026-08-28 12:45:52 +05:30
committed by Richard Purdie
parent abef4d0701
commit c71dd3cb0d
2 changed files with 266 additions and 0 deletions

View File

@@ -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

View File

@@ -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 \ SRC_URI = "gitsm://github.com/p11-glue/p11-kit;branch=master;protocol=https \
file://fix-parallel-build-failures.patch \ file://fix-parallel-build-failures.patch \
file://CVE-2026-13757.patch \
" "
SRCREV = "917e02a3211dabbdea4b079cb598581dce84fda1" SRCREV = "917e02a3211dabbdea4b079cb598581dce84fda1"
S = "${WORKDIR}/git" S = "${WORKDIR}/git"