mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-09-27 00:30:20 +00:00
libkcapi: patch CVE-2026-71226
Backport commits[1][2] needed to cherry pick fix for the CVE as per the release notes[3] Details: https://nvd.nist.gov/vuln/detail/cve-2026-71226 [1]https://github.com/smuellerDD/libkcapi/commit/e8396c28c2cd2b81f69fc68500fcb2ec7163b4fd [2]https://github.com/smuellerDD/libkcapi/commit/d9f16d5fbcf8270110a8f6f35523525f345ca311 [3]https://github.com/smuellerDD/libkcapi/releases/tag/v1.5.1 Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com> Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
@@ -0,0 +1,604 @@
|
||||
From 73a34808912e3cfea8d88f0a2c08fc0ed107a9d8 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Theil <markus.theil@secunet.com>
|
||||
Date: Fri, 3 Apr 2026 15:06:53 +0200
|
||||
Subject: [PATCH] fixes found by analysis with LLM
|
||||
|
||||
Signed-off-by: Markus Theil <markus.theil@secunet.com>
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
||||
(cherry picked from commit e8396c28c2cd2b81f69fc68500fcb2ec7163b4fd)
|
||||
|
||||
CVE: CVE-2026-71226
|
||||
Upstream-Status: Backport [https://github.com/smuellerDD/libkcapi/commit/e8396c28c2cd2b81f69fc68500fcb2ec7163b4fd]
|
||||
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
|
||||
---
|
||||
apps/app-internal.c | 15 +++++++++---
|
||||
apps/kcapi-dgst.c | 11 ++++++---
|
||||
apps/kcapi-enc.c | 9 ++++---
|
||||
apps/kcapi-hasher.c | 12 ++++++---
|
||||
apps/kcapi-rng.c | 24 ++++++++++++------
|
||||
configure.ac | 3 ++-
|
||||
lib/kcapi-aead.c | 12 +++++++--
|
||||
lib/kcapi-kdf.c | 6 +++--
|
||||
lib/kcapi-kernel-if.c | 57 +++++++++++++++++++++++++++++--------------
|
||||
lib/kcapi-kpp.c | 4 +--
|
||||
lib/kcapi-md.c | 2 +-
|
||||
lib/kcapi-sym.c | 6 +++++
|
||||
lib/kcapi-utils.c | 7 ++++--
|
||||
13 files changed, 118 insertions(+), 50 deletions(-)
|
||||
|
||||
diff --git a/apps/app-internal.c b/apps/app-internal.c
|
||||
index 7e01dd7..724b0b1 100644
|
||||
--- a/apps/app-internal.c
|
||||
+++ b/apps/app-internal.c
|
||||
@@ -173,18 +173,24 @@ static uint8_t bin_char(char hex)
|
||||
void hex2bin(const char *hex, uint32_t hexlen, uint8_t *bin, uint32_t binlen)
|
||||
{
|
||||
uint32_t i;
|
||||
- uint32_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
|
||||
+ uint32_t chars;
|
||||
|
||||
/*
|
||||
* handle odd-length of strings where the first digit is the least
|
||||
* significant nibble
|
||||
*/
|
||||
if (hexlen & 1) {
|
||||
+ if (!binlen)
|
||||
+ return;
|
||||
bin[0] = bin_char(hex[0]);
|
||||
bin++;
|
||||
hex++;
|
||||
+ hexlen--;
|
||||
+ binlen--;
|
||||
}
|
||||
|
||||
+ chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
|
||||
+
|
||||
for (i = 0; i < chars; i++) {
|
||||
bin[i] = (uint8_t)(bin_char(hex[(i*2)]) << 4);
|
||||
bin[i] |= bin_char(hex[((i*2)+1)]);
|
||||
@@ -238,13 +244,14 @@ ssize_t read_complete(int fd, uint8_t *buf, size_t buflen)
|
||||
if (0 < ret) {
|
||||
buflen -= (size_t)ret;
|
||||
buf += ret;
|
||||
+ rc += ret;
|
||||
}
|
||||
- rc += ret;
|
||||
- if (ret)
|
||||
- break;
|
||||
} while ((0 < ret || EINTR == errno || ERESTART == errno)
|
||||
&& buflen > 0);
|
||||
|
||||
+ if (ret < 0)
|
||||
+ return -errno;
|
||||
+
|
||||
return rc;
|
||||
}
|
||||
|
||||
diff --git a/apps/kcapi-dgst.c b/apps/kcapi-dgst.c
|
||||
index 591a7fb..42d099c 100644
|
||||
--- a/apps/kcapi-dgst.c
|
||||
+++ b/apps/kcapi-dgst.c
|
||||
@@ -128,6 +128,11 @@ static int cipher_op(struct kcapi_handle *handle, struct opt_data *opts)
|
||||
}
|
||||
|
||||
outlen = kcapi_md_digestsize(handle);
|
||||
+ if (!outlen) {
|
||||
+ dolog(KCAPI_LOG_ERR, "Cipher has zero digest size");
|
||||
+ ret = -EINVAL;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
if (opts->hexout)
|
||||
outlen *= 2;
|
||||
@@ -285,8 +290,8 @@ static int set_key(struct kcapi_handle *handle, struct opt_data *opts)
|
||||
}
|
||||
|
||||
while (j < saltbuflen) {
|
||||
- ret = kcapi_rng_generate(rng, saltbuf,
|
||||
- (size_t)saltbuflen);
|
||||
+ ret = kcapi_rng_generate(rng, saltbuf + j,
|
||||
+ (size_t)(saltbuflen - j));
|
||||
if (ret < 0) {
|
||||
kcapi_rng_destroy(rng);
|
||||
free(saltbuf);
|
||||
@@ -320,7 +325,7 @@ static int set_key(struct kcapi_handle *handle, struct opt_data *opts)
|
||||
if (opts->key_fd != -1) {
|
||||
ret = read_complete(opts->key_fd, keybuf, sizeof(keybuf));
|
||||
if (ret < 0)
|
||||
- return (int)ret;
|
||||
+ goto out;
|
||||
|
||||
have_key = 1;
|
||||
keybuflen = (uint32_t)ret;
|
||||
diff --git a/apps/kcapi-enc.c b/apps/kcapi-enc.c
|
||||
index 68cf2f7..e7aa9db 100644
|
||||
--- a/apps/kcapi-enc.c
|
||||
+++ b/apps/kcapi-enc.c
|
||||
@@ -218,7 +218,7 @@ static ssize_t return_data_fd(struct kcapi_handle *handle,
|
||||
}
|
||||
|
||||
out:
|
||||
- munmap(outmem, outsize);
|
||||
+ munmap(outmem, outsize + offset);
|
||||
return (ret < 0) ? ret : generated_bytes;
|
||||
}
|
||||
|
||||
@@ -609,7 +609,7 @@ static int cipher_op(struct kcapi_handle *handle, struct opt_data *opts)
|
||||
}
|
||||
|
||||
/* Get data from file. */
|
||||
- } else {
|
||||
+ } else if (insb.st_size) {
|
||||
uint32_t sent_data = 0;
|
||||
|
||||
inmem = mmap(NULL, (size_t)insb.st_size, PROT_READ, MAP_SHARED,
|
||||
@@ -636,6 +636,7 @@ static int cipher_op(struct kcapi_handle *handle, struct opt_data *opts)
|
||||
* we will not apply padding.
|
||||
*/
|
||||
if (!opts->decrypt &&
|
||||
+ insb.st_size >= 2 &&
|
||||
!(insb.st_size % opts->func_blocksize(handle)) &&
|
||||
(uint32_t)padbyte < opts->func_blocksize(handle)) {
|
||||
uint32_t i;
|
||||
@@ -803,8 +804,8 @@ static int set_key(struct kcapi_handle *handle, struct opt_data *opts)
|
||||
}
|
||||
|
||||
while (j < saltbuflen) {
|
||||
- ret = kcapi_rng_generate(rng, saltbuf,
|
||||
- saltbuflen);
|
||||
+ ret = kcapi_rng_generate(rng, saltbuf + j,
|
||||
+ saltbuflen - j);
|
||||
if (ret < 0) {
|
||||
kcapi_rng_destroy(rng);
|
||||
free(saltbuf);
|
||||
diff --git a/apps/kcapi-hasher.c b/apps/kcapi-hasher.c
|
||||
index 217f59d..90dc34d 100644
|
||||
--- a/apps/kcapi-hasher.c
|
||||
+++ b/apps/kcapi-hasher.c
|
||||
@@ -271,7 +271,7 @@ static int load_file(const char *filename, uint8_t **memory, off_t *size)
|
||||
fprintf(stderr, "Key longer than UINT32_MAX\n");
|
||||
ret = -ERANGE;
|
||||
goto out;
|
||||
- } else if (buffer_size * 2 < buffer_size)
|
||||
+ } else if (buffer_size > UINT32_MAX / 2)
|
||||
buffer_size = UINT32_MAX;
|
||||
else
|
||||
buffer_size *= 2;
|
||||
@@ -340,7 +340,7 @@ static int hasher(struct kcapi_handle *handle, const struct hash_params *params,
|
||||
} while (left);
|
||||
munmap(memblock, mapped);
|
||||
offset = offset + (off_t)mapped;
|
||||
- } while (offset ^ size);
|
||||
+ } while (offset != size);
|
||||
} else {
|
||||
uint8_t tmpbuf[TMPBUFLEN] __aligned(KCAPI_APP_ALIGN);
|
||||
uint32_t bufsize;
|
||||
@@ -647,11 +647,17 @@ static int process_checkfile(const struct hash_params *params,
|
||||
hexhash = buf;
|
||||
|
||||
if (bsd_style) {
|
||||
+ if (bsd_style > linelen) {
|
||||
+ fprintf(stderr, "Invalid checkfile format\n");
|
||||
+ ret = 1;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
/* Hash starts after separator */
|
||||
hexhashlen = linelen - bsd_style + 1;
|
||||
|
||||
/* remove closing parenthesis behind filename */
|
||||
- if (buf[(bsd_style - 4)] == ')')
|
||||
+ if (bsd_style >= 4 && buf[(bsd_style - 4)] == ')')
|
||||
buf[(bsd_style - 4)] = '\0';
|
||||
}
|
||||
|
||||
diff --git a/apps/kcapi-rng.c b/apps/kcapi-rng.c
|
||||
index 9e025cd..46dab02 100644
|
||||
--- a/apps/kcapi-rng.c
|
||||
+++ b/apps/kcapi-rng.c
|
||||
@@ -282,16 +282,18 @@ int main(int argc, char *argv[])
|
||||
seedsize);
|
||||
|
||||
if (!isatty(0) && (errno == EINVAL || errno == ENOTTY)) {
|
||||
- while (fgets((char *)seedbuf, (int)seedsize, stdin)) {
|
||||
- ret = kcapi_rng_seed(rng, seedbuf, seedsize);
|
||||
+ ssize_t rret;
|
||||
+
|
||||
+ while ((rret = read(STDIN_FILENO, seedbuf, seedsize)) > 0) {
|
||||
+ ret = kcapi_rng_seed(rng, seedbuf, (uint32_t)rret);
|
||||
if (ret)
|
||||
dolog(KCAPI_LOG_WARN,
|
||||
- "User-provided seed of %lu bytes not accepted by DRNG (error: %ld)",
|
||||
- (unsigned long)sizeof(buf), ret);
|
||||
+ "User-provided seed of %zd bytes not accepted by DRNG (error: %ld)",
|
||||
+ rret, ret);
|
||||
else
|
||||
dolog(KCAPI_LOG_DEBUG,
|
||||
- "User-provided seed of %u bytes",
|
||||
- seedsize);
|
||||
+ "User-provided seed of %zd bytes",
|
||||
+ rret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,9 +314,15 @@ int main(int argc, char *argv[])
|
||||
char hexbuf[2 * KCAPI_RNG_BUFSIZE];
|
||||
|
||||
bin2hex(buf, (size_t)ret, hexbuf, sizeof(hexbuf), 0);
|
||||
- fwrite(hexbuf, 2 * (size_t)ret, 1, stdout);
|
||||
+ if (fwrite(hexbuf, 2 * (size_t)ret, 1, stdout) != 1) {
|
||||
+ ret = -EIO;
|
||||
+ goto out;
|
||||
+ }
|
||||
} else {
|
||||
- fwrite(buf, (size_t)ret, 1, stdout);
|
||||
+ if (fwrite(buf, (size_t)ret, 1, stdout) != 1) {
|
||||
+ ret = -EIO;
|
||||
+ goto out;
|
||||
+ }
|
||||
}
|
||||
|
||||
outlen -= (size_t)ret;
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index fbae4f9..446b8a8 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -14,16 +14,17 @@ m4_define([__KCAPI_MINVERSION], [5])
|
||||
m4_define([__KCAPI_PATCHLEVEL], [0])
|
||||
m4_define([KCAPI_VERSION], [__KCAPI_MAJVERSION.__KCAPI_MINVERSION.__KCAPI_PATCHLEVEL])
|
||||
|
||||
+AC_PREREQ([2.69])
|
||||
AC_INIT([libkcapi], [KCAPI_VERSION])
|
||||
AC_DEFINE([KCAPI_MAJVERSION], [__KCAPI_MAJVERSION])
|
||||
AC_DEFINE([KCAPI_MINVERSION], [__KCAPI_MINVERSION])
|
||||
AC_DEFINE([KCAPI_PATCHLEVEL], [__KCAPI_PATCHLEVEL])
|
||||
+AC_CONFIG_MACRO_DIRS([m4])
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
LT_INIT([pic-only])
|
||||
AC_SUBST([LIBTOOL_DEPS])
|
||||
AC_PROG_CC
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
-AC_CONFIG_MACRO_DIR([m4])
|
||||
AX_PROG_CC_FOR_BUILD
|
||||
AX_CHECK_PIE
|
||||
|
||||
diff --git a/lib/kcapi-aead.c b/lib/kcapi-aead.c
|
||||
index b52dda0..3a7d711 100644
|
||||
--- a/lib/kcapi-aead.c
|
||||
+++ b/lib/kcapi-aead.c
|
||||
@@ -566,7 +566,11 @@ size_t impl_aead_outbuflen_enc(struct kcapi_handle *handle,
|
||||
{
|
||||
struct kcapi_handle_tfm *tfm = handle->tfm;
|
||||
uint32_t bs = tfm->info.blocksize;
|
||||
- size_t outlen = (inlen + bs - 1) / bs * bs + taglen + assoclen;
|
||||
+ size_t outlen;
|
||||
+
|
||||
+ if (!bs)
|
||||
+ return 0;
|
||||
+ outlen = (inlen + bs - 1) / bs * bs + taglen + assoclen;
|
||||
|
||||
/* the kernel does not like zero length output buffers */
|
||||
if (!outlen)
|
||||
@@ -591,7 +595,11 @@ size_t impl_aead_outbuflen_dec(struct kcapi_handle *handle,
|
||||
{
|
||||
struct kcapi_handle_tfm *tfm = handle->tfm;
|
||||
uint32_t bs = tfm->info.blocksize;
|
||||
- size_t outlen = (inlen + bs - 1) / bs * bs + assoclen;
|
||||
+ size_t outlen;
|
||||
+
|
||||
+ if (!bs)
|
||||
+ return 0;
|
||||
+ outlen = (inlen + bs - 1) / bs * bs + assoclen;
|
||||
|
||||
if (!handle->flags.ge_v4_9 == true)
|
||||
outlen += taglen;
|
||||
diff --git a/lib/kcapi-kdf.c b/lib/kcapi-kdf.c
|
||||
index 54dc1ec..5f389b6 100644
|
||||
--- a/lib/kcapi-kdf.c
|
||||
+++ b/lib/kcapi-kdf.c
|
||||
@@ -54,6 +54,8 @@
|
||||
#include "kcapi.h"
|
||||
#include "internal.h"
|
||||
|
||||
+#define MAX_DIGESTSIZE 64
|
||||
+
|
||||
#ifndef __has_builtin
|
||||
# define __has_builtin(x) 0
|
||||
#endif
|
||||
@@ -101,7 +103,7 @@ ssize_t impl_kdf_dpi(struct kcapi_handle *handle,
|
||||
ssize_t err = 0;
|
||||
uint8_t *dst_orig = dst;
|
||||
size_t dlen_orig = dlen;
|
||||
- uint8_t Ai[h];
|
||||
+ uint8_t Ai[MAX_DIGESTSIZE];
|
||||
uint32_t i = 1;
|
||||
|
||||
if (dlen > INT_MAX)
|
||||
@@ -448,7 +450,7 @@ static inline uint64_t kcapi_get_time(void)
|
||||
{
|
||||
struct timespec time;
|
||||
|
||||
- if (clock_gettime(CLOCK_REALTIME, &time) == 0)
|
||||
+ if (clock_gettime(CLOCK_MONOTONIC, &time) == 0)
|
||||
return (uint64_t)time.tv_nsec;
|
||||
|
||||
return 0;
|
||||
diff --git a/lib/kcapi-kernel-if.c b/lib/kcapi-kernel-if.c
|
||||
index 835e45a..b37f0dc 100644
|
||||
--- a/lib/kcapi-kernel-if.c
|
||||
+++ b/lib/kcapi-kernel-if.c
|
||||
@@ -216,7 +216,7 @@ ssize_t _kcapi_common_send_meta(struct kcapi_handle *handle,
|
||||
}
|
||||
header->cmsg_level = SOL_ALG;
|
||||
header->cmsg_type = ALG_SET_IV;
|
||||
- header->cmsg_len = kcapi_downcast_socklen_t(iv_msg_size);
|
||||
+ header->cmsg_len = CMSG_LEN(iv_msg_size);
|
||||
alg_iv = (void*)CMSG_DATA(header);
|
||||
alg_iv->ivlen = tfm->info.ivsize;
|
||||
memcpy(alg_iv->iv, handle->cipher.iv, tfm->info.ivsize);
|
||||
@@ -409,8 +409,10 @@ ssize_t _kcapi_common_vmsplice_chunk(struct kcapi_handle *handle,
|
||||
"AF_ALG: splice syscall returned %zd", ret);
|
||||
}
|
||||
|
||||
+ if (ret == 0)
|
||||
+ return -EPIPE;
|
||||
processed += ret;
|
||||
- inlen -= (uint32_t)ret;
|
||||
+ inlen -= (size_t)ret;
|
||||
}
|
||||
|
||||
return processed;
|
||||
@@ -434,14 +436,17 @@ int _kcapi_aio_read_all(struct kcapi_handle *handle, size_t toread,
|
||||
|
||||
for (i = 0; i < rc; i++) {
|
||||
struct iocb *cb;
|
||||
+ unsigned int idx = (unsigned int)events[i].data;
|
||||
+
|
||||
+ if (idx >= KCAPI_AIO_CONCURRENT)
|
||||
+ return -EOVERFLOW;
|
||||
|
||||
/*
|
||||
* If one cipher operation fails, so will the entire
|
||||
* AIO operation
|
||||
*/
|
||||
if (events[i].res < 0) {
|
||||
- handle->aio.iocb_ret[events[i].data] =
|
||||
- events[i].res;
|
||||
+ handle->aio.iocb_ret[idx] = events[i].res;
|
||||
return (int)events[i].res;
|
||||
}
|
||||
|
||||
@@ -452,16 +457,15 @@ int _kcapi_aio_read_all(struct kcapi_handle *handle, size_t toread,
|
||||
* return code.
|
||||
*/
|
||||
if (events[i].res > 0) {
|
||||
- handle->aio.iocb_ret[events[i].data] =
|
||||
- events[i].res;
|
||||
+ handle->aio.iocb_ret[idx] = events[i].res;
|
||||
} else {
|
||||
- handle->aio.iocb_ret[events[i].data] =
|
||||
+ handle->aio.iocb_ret[idx] =
|
||||
(__s64)cb->aio_nbytes;
|
||||
}
|
||||
|
||||
cb->aio_fildes = 0;
|
||||
}
|
||||
- toread -= (uint32_t)rc;
|
||||
+ toread -= (size_t)rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -613,7 +617,7 @@ ssize_t _kcapi_common_read_data(struct kcapi_handle *handle,
|
||||
ret = read(*_kcapi_get_opfd(handle), out, outlen);
|
||||
if (ret > 0) {
|
||||
out += ret;
|
||||
- outlen -= (uint32_t)ret;
|
||||
+ outlen -= (size_t)ret;
|
||||
totallen += ret;
|
||||
}
|
||||
kcapi_dolog(KCAPI_LOG_DEBUG,
|
||||
@@ -722,13 +726,13 @@ static int __kcapi_common_getinfo(struct kcapi_handle *handle,
|
||||
goto out;
|
||||
}
|
||||
if (addr_len != sizeof(nl)) {
|
||||
- ret = -errno;
|
||||
+ ret = -EPROTO;
|
||||
kcapi_dolog(KCAPI_LOG_ERR,
|
||||
"Netlink error: wrong address length %d", addr_len);
|
||||
goto out;
|
||||
}
|
||||
if (nl.nl_family != AF_NETLINK) {
|
||||
- ret = -errno;
|
||||
+ ret = -EPROTO;
|
||||
kcapi_dolog(KCAPI_LOG_ERR,
|
||||
"Netlink error: wrong address family %d",
|
||||
nl.nl_family);
|
||||
@@ -764,12 +768,12 @@ static int __kcapi_common_getinfo(struct kcapi_handle *handle,
|
||||
goto out;
|
||||
}
|
||||
if (rc == 0) {
|
||||
- ret = -errno;
|
||||
+ ret = -ENODATA;
|
||||
kcapi_dolog(KCAPI_LOG_ERR, "Netlink error: no data");
|
||||
goto out;
|
||||
}
|
||||
if (rc > (ssize_t)sizeof(buf)) {
|
||||
- ret = -errno;
|
||||
+ ret = -EOVERFLOW;
|
||||
kcapi_dolog(KCAPI_LOG_ERR,
|
||||
"Netlink error: received too much data");
|
||||
goto out;
|
||||
@@ -779,6 +783,12 @@ static int __kcapi_common_getinfo(struct kcapi_handle *handle,
|
||||
|
||||
ret = -EFAULT;
|
||||
res_len = res_n->nlmsg_len;
|
||||
+ if (res_len > sizeof(buf)) {
|
||||
+ kcapi_dolog(KCAPI_LOG_ERR,
|
||||
+ "Netlink error: nlmsg_len %lu exceeds buffer",
|
||||
+ res_len);
|
||||
+ goto out;
|
||||
+ }
|
||||
if (res_n->nlmsg_type == NLMSG_ERROR) {
|
||||
/*
|
||||
* return -EAGAIN -- this error will occur if we received a
|
||||
@@ -819,6 +829,9 @@ static int __kcapi_common_getinfo(struct kcapi_handle *handle,
|
||||
|
||||
if (tb[CRYPTOCFGA_REPORT_HASH]) {
|
||||
struct rtattr *rta = tb[CRYPTOCFGA_REPORT_HASH];
|
||||
+
|
||||
+ if (RTA_PAYLOAD(rta) < sizeof(struct crypto_report_hash))
|
||||
+ goto out;
|
||||
struct crypto_report_hash *rsh =
|
||||
(struct crypto_report_hash *) RTA_DATA(rta);
|
||||
tfm->info.hash_digestsize = rsh->digestsize;
|
||||
@@ -831,6 +844,9 @@ static int __kcapi_common_getinfo(struct kcapi_handle *handle,
|
||||
}
|
||||
if (tb[CRYPTOCFGA_REPORT_BLKCIPHER]) {
|
||||
struct rtattr *rta = tb[CRYPTOCFGA_REPORT_BLKCIPHER];
|
||||
+
|
||||
+ if (RTA_PAYLOAD(rta) < sizeof(struct crypto_report_blkcipher))
|
||||
+ goto out;
|
||||
struct crypto_report_blkcipher *rblk =
|
||||
(struct crypto_report_blkcipher *) RTA_DATA(rta);
|
||||
tfm->info.blocksize = rblk->blocksize;
|
||||
@@ -845,6 +861,9 @@ static int __kcapi_common_getinfo(struct kcapi_handle *handle,
|
||||
}
|
||||
if (tb[CRYPTOCFGA_REPORT_AEAD]) {
|
||||
struct rtattr *rta = tb[CRYPTOCFGA_REPORT_AEAD];
|
||||
+
|
||||
+ if (RTA_PAYLOAD(rta) < sizeof(struct crypto_report_aead))
|
||||
+ goto out;
|
||||
struct crypto_report_aead *raead =
|
||||
(struct crypto_report_aead *) RTA_DATA(rta);
|
||||
tfm->info.blocksize = raead->blocksize;
|
||||
@@ -858,6 +877,9 @@ static int __kcapi_common_getinfo(struct kcapi_handle *handle,
|
||||
}
|
||||
if (tb[CRYPTOCFGA_REPORT_RNG]) {
|
||||
struct rtattr *rta = tb[CRYPTOCFGA_REPORT_RNG];
|
||||
+
|
||||
+ if (RTA_PAYLOAD(rta) < sizeof(struct crypto_report_rng))
|
||||
+ goto out;
|
||||
struct crypto_report_rng *rrng =
|
||||
(struct crypto_report_rng *) RTA_DATA(rta);
|
||||
tfm->info.rng_seedsize = rrng->seedsize;
|
||||
@@ -981,19 +1003,19 @@ static int _kcapi_get_kernver(struct kcapi_handle *handle)
|
||||
/* 3.15.0 */
|
||||
res = strtok_r(kernel.release, ".", &saveptr);
|
||||
if (!res) {
|
||||
- printf("Could not parse kernel version");
|
||||
+ kcapi_dolog(KCAPI_LOG_ERR, "Could not parse kernel version");
|
||||
return -EFAULT;
|
||||
}
|
||||
tfm->sysinfo.kernel_maj = strtoul(res, NULL, 10);
|
||||
res = strtok_r(NULL, ".", &saveptr);
|
||||
if (!res) {
|
||||
- printf("Could not parse kernel version");
|
||||
+ kcapi_dolog(KCAPI_LOG_ERR, "Could not parse kernel version");
|
||||
return -EFAULT;
|
||||
}
|
||||
tfm->sysinfo.kernel_minor = strtoul(res, NULL, 10);
|
||||
res = strtok_r(NULL, ".", &saveptr);
|
||||
if (!res) {
|
||||
- printf("Could not parse kernel version");
|
||||
+ kcapi_dolog(KCAPI_LOG_ERR, "Could not parse kernel version");
|
||||
return -EFAULT;
|
||||
}
|
||||
tfm->sysinfo.kernel_patchlevel = strtoul(res, NULL, 10);
|
||||
@@ -1217,7 +1239,6 @@ static int _kcapi_handle_init_tfm(struct kcapi_handle *handle, const char *type,
|
||||
|
||||
ret = _kcapi_common_getinfo(handle, ciphername);
|
||||
if (ret) {
|
||||
- ret = -errno;
|
||||
kcapi_dolog(KCAPI_LOG_ERR, "NETLINK_CRYPTO: cannot obtain cipher information for %s (is required crypto_user.c patch missing? see documentation)",
|
||||
ciphername);
|
||||
return ret;
|
||||
@@ -1368,7 +1389,7 @@ ssize_t _kcapi_cipher_crypt_chunk(struct kcapi_handle *handle,
|
||||
in += inprocess;
|
||||
inlen -= inprocess;
|
||||
out += ret;
|
||||
- outlen -= (uint32_t)ret;
|
||||
+ outlen -= (size_t)ret;
|
||||
}
|
||||
|
||||
return totallen;
|
||||
diff --git a/lib/kcapi-kpp.c b/lib/kcapi-kpp.c
|
||||
index 814485a..d0383d6 100644
|
||||
--- a/lib/kcapi-kpp.c
|
||||
+++ b/lib/kcapi-kpp.c
|
||||
@@ -52,12 +52,12 @@ int kcapi_kpp_ecdh_setcurve(struct kcapi_handle *handle,
|
||||
unsigned long curve_id)
|
||||
{
|
||||
struct kcapi_handle_tfm *tfm = handle->tfm;
|
||||
- char curve_id_str[sizeof(unsigned long)];
|
||||
+ char curve_id_str[24];
|
||||
int ret = 0;
|
||||
|
||||
snprintf(curve_id_str, sizeof(curve_id_str), "%lu", curve_id);
|
||||
ret = setsockopt(tfm->tfmfd, SOL_ALG, ALG_SET_ECDH_CURVE,
|
||||
- curve_id_str, sizeof(curve_id_str));
|
||||
+ curve_id_str, (socklen_t)strlen(curve_id_str));
|
||||
return (ret >= 0) ? ret : -errno;
|
||||
}
|
||||
|
||||
diff --git a/lib/kcapi-md.c b/lib/kcapi-md.c
|
||||
index bddd76b..5f493eb 100644
|
||||
--- a/lib/kcapi-md.c
|
||||
+++ b/lib/kcapi-md.c
|
||||
@@ -196,7 +196,7 @@ ssize_t impl_md_sha256(const uint8_t *in, size_t inlen,
|
||||
}
|
||||
|
||||
ORIG_SYMVER(md_sha256, "1.0.0")
|
||||
-ssize_t orig_md_sha256(const uint8_t *in, uint32_t inlen,
|
||||
+int32_t orig_md_sha256(const uint8_t *in, uint32_t inlen,
|
||||
uint8_t *out, uint32_t outlen)
|
||||
{
|
||||
return (int32_t)kcapi_md_conv_common("sha256", in, inlen, out, outlen);
|
||||
diff --git a/lib/kcapi-sym.c b/lib/kcapi-sym.c
|
||||
index 911ec1e..d500061 100644
|
||||
--- a/lib/kcapi-sym.c
|
||||
+++ b/lib/kcapi-sym.c
|
||||
@@ -47,6 +47,9 @@ ssize_t impl_cipher_encrypt(struct kcapi_handle *handle,
|
||||
struct kcapi_handle_tfm *tfm = handle->tfm;
|
||||
uint32_t bs = tfm->info.blocksize;
|
||||
|
||||
+ if (!bs)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
/* require properly sized output data size */
|
||||
if (outlen < ((inlen + bs - 1) / bs * bs))
|
||||
kcapi_dolog(KCAPI_LOG_WARN,
|
||||
@@ -120,6 +123,9 @@ ssize_t impl_cipher_decrypt(struct kcapi_handle *handle,
|
||||
{
|
||||
struct kcapi_handle_tfm *tfm = handle->tfm;
|
||||
|
||||
+ if (!tfm->info.blocksize)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
/* require properly sized output data size */
|
||||
if (inlen % tfm->info.blocksize)
|
||||
kcapi_dolog(KCAPI_LOG_WARN,
|
||||
diff --git a/lib/kcapi-utils.c b/lib/kcapi-utils.c
|
||||
index 46fd330..e801d29 100644
|
||||
--- a/lib/kcapi-utils.c
|
||||
+++ b/lib/kcapi-utils.c
|
||||
@@ -96,7 +96,7 @@ err:
|
||||
} else {
|
||||
kcapi_dolog(KCAPI_LOG_WARN,
|
||||
"AF_ALG: setting maximum splice pipe size to %u failed: %s",
|
||||
- size, strerror(ret));
|
||||
+ size, strerror(-ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -109,7 +109,10 @@ int kcapi_get_maxsplicesize(struct kcapi_handle *handle)
|
||||
return -EINVAL;
|
||||
|
||||
/* Both pipe endpoints should have the same pipe size */
|
||||
- handle->pipesize = (unsigned int)fcntl(handle->pipes[0], F_GETPIPE_SZ);
|
||||
+ int ret = fcntl(handle->pipes[0], F_GETPIPE_SZ);
|
||||
+ if (ret < 0)
|
||||
+ return -errno;
|
||||
+ handle->pipesize = (unsigned int)ret;
|
||||
|
||||
/*
|
||||
* For vmsplice to allow the maximum number of 16 pages, we need to
|
||||
@@ -0,0 +1,55 @@
|
||||
From 79198067bdf027f5d4d5e2804b086a0a37b277ec Mon Sep 17 00:00:00 2001
|
||||
From: Stephan Mueller <smueller@chronox.de>
|
||||
Date: Fri, 3 Apr 2026 17:43:05 +0200
|
||||
Subject: [PATCH] fix kernel invocation
|
||||
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
||||
(cherry picked from commit d9f16d5fbcf8270110a8f6f35523525f345ca311)
|
||||
|
||||
CVE: CVE-2026-71226
|
||||
Upstream-Status: Backport [https://github.com/smuellerDD/libkcapi/commit/d9f16d5fbcf8270110a8f6f35523525f345ca311]
|
||||
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
|
||||
---
|
||||
lib/kcapi-kernel-if.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/lib/kcapi-kernel-if.c b/lib/kcapi-kernel-if.c
|
||||
index b37f0dc..5d3b352 100644
|
||||
--- a/lib/kcapi-kernel-if.c
|
||||
+++ b/lib/kcapi-kernel-if.c
|
||||
@@ -216,7 +216,7 @@ ssize_t _kcapi_common_send_meta(struct kcapi_handle *handle,
|
||||
}
|
||||
header->cmsg_level = SOL_ALG;
|
||||
header->cmsg_type = ALG_SET_IV;
|
||||
- header->cmsg_len = CMSG_LEN(iv_msg_size);
|
||||
+ header->cmsg_len = kcapi_downcast_socklen_t(iv_msg_size);
|
||||
alg_iv = (void*)CMSG_DATA(header);
|
||||
alg_iv->ivlen = tfm->info.ivsize;
|
||||
memcpy(alg_iv->iv, handle->cipher.iv, tfm->info.ivsize);
|
||||
@@ -411,6 +411,7 @@ ssize_t _kcapi_common_vmsplice_chunk(struct kcapi_handle *handle,
|
||||
|
||||
if (ret == 0)
|
||||
return -EPIPE;
|
||||
+
|
||||
processed += ret;
|
||||
inlen -= (size_t)ret;
|
||||
}
|
||||
@@ -436,7 +437,7 @@ int _kcapi_aio_read_all(struct kcapi_handle *handle, size_t toread,
|
||||
|
||||
for (i = 0; i < rc; i++) {
|
||||
struct iocb *cb;
|
||||
- unsigned int idx = (unsigned int)events[i].data;
|
||||
+ uint64_t idx = events[i].data;
|
||||
|
||||
if (idx >= KCAPI_AIO_CONCURRENT)
|
||||
return -EOVERFLOW;
|
||||
@@ -459,8 +460,7 @@ int _kcapi_aio_read_all(struct kcapi_handle *handle, size_t toread,
|
||||
if (events[i].res > 0) {
|
||||
handle->aio.iocb_ret[idx] = events[i].res;
|
||||
} else {
|
||||
- handle->aio.iocb_ret[idx] =
|
||||
- (__s64)cb->aio_nbytes;
|
||||
+ handle->aio.iocb_ret[idx] = (__s64)cb->aio_nbytes;
|
||||
}
|
||||
|
||||
cb->aio_fildes = 0;
|
||||
@@ -0,0 +1,93 @@
|
||||
From 8ab3c8939276848ec8f43156a7658f7c5dae4026 Mon Sep 17 00:00:00 2001
|
||||
From: Stephan Mueller <smueller@chronox.de>
|
||||
Date: Thu, 30 Jul 2026 08:36:32 +0200
|
||||
Subject: [PATCH] fix memory corruption
|
||||
|
||||
Signed-off-by: Zoltan Fridrich <zfridric@redhat.com>
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
||||
|
||||
CVE: CVE-2026-71226
|
||||
Upstream-Status: Backport [https://github.com/smuellerDD/libkcapi/commit/cd966ffa08cf605ae5853d2f9a42fdd2b6df8bb4]
|
||||
|
||||
Dropped changes to the CHANGES.md file.
|
||||
|
||||
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
|
||||
---
|
||||
lib/kcapi-kernel-if.c | 33 ++++++++++++++-------------------
|
||||
1 file changed, 14 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/lib/kcapi-kernel-if.c b/lib/kcapi-kernel-if.c
|
||||
index 5d3b352..8a12c09 100644
|
||||
--- a/lib/kcapi-kernel-if.c
|
||||
+++ b/lib/kcapi-kernel-if.c
|
||||
@@ -423,6 +423,8 @@ ssize_t _kcapi_common_vmsplice_chunk(struct kcapi_handle *handle,
|
||||
int _kcapi_aio_read_all(struct kcapi_handle *handle, size_t toread,
|
||||
struct timespec *timeout)
|
||||
{
|
||||
+ int err = 0;
|
||||
+
|
||||
if (toread > KCAPI_AIO_CONCURRENT)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -433,34 +435,26 @@ int _kcapi_aio_read_all(struct kcapi_handle *handle, size_t toread,
|
||||
events, timeout);
|
||||
|
||||
if (rc < 0)
|
||||
- return rc;
|
||||
+ return err == 0 ? rc : err;
|
||||
|
||||
for (i = 0; i < rc; i++) {
|
||||
struct iocb *cb;
|
||||
uint64_t idx = events[i].data;
|
||||
|
||||
- if (idx >= KCAPI_AIO_CONCURRENT)
|
||||
- return -EOVERFLOW;
|
||||
-
|
||||
- /*
|
||||
- * If one cipher operation fails, so will the entire
|
||||
- * AIO operation
|
||||
- */
|
||||
- if (events[i].res < 0) {
|
||||
- handle->aio.iocb_ret[idx] = events[i].res;
|
||||
- return (int)events[i].res;
|
||||
+ if (idx >= KCAPI_AIO_CONCURRENT) {
|
||||
+ if (err == 0)
|
||||
+ err = -EOVERFLOW;
|
||||
+ continue;
|
||||
}
|
||||
|
||||
cb = (struct iocb *)(uintptr_t)events[i].obj;
|
||||
|
||||
- /*
|
||||
- * Older symmetric AIO implementations used a wrong
|
||||
- * return code.
|
||||
- */
|
||||
- if (events[i].res > 0) {
|
||||
- handle->aio.iocb_ret[idx] = events[i].res;
|
||||
- } else {
|
||||
+ if (events[i].res == 0) {
|
||||
handle->aio.iocb_ret[idx] = (__s64)cb->aio_nbytes;
|
||||
+ } else {
|
||||
+ handle->aio.iocb_ret[idx] = events[i].res;
|
||||
+ if (events[i].res < 0 && err == 0)
|
||||
+ err = (int)events[i].res;
|
||||
}
|
||||
|
||||
cb->aio_fildes = 0;
|
||||
@@ -468,7 +462,7 @@ int _kcapi_aio_read_all(struct kcapi_handle *handle, size_t toread,
|
||||
toread -= (size_t)rc;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return err;
|
||||
}
|
||||
|
||||
int _kcapi_aio_send_iov(struct kcapi_handle *handle, struct iovec *iov,
|
||||
@@ -544,6 +538,7 @@ int _kcapi_aio_read_iov(struct kcapi_handle *handle,
|
||||
} else {
|
||||
kcapi_dolog(KCAPI_LOG_ERR,
|
||||
"Could not sumbit AIO read\n");
|
||||
+ _kcapi_aio_read_all(handle, (size_t)ret, NULL);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,9 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=3d8a091d797491204567185a6efce70f"
|
||||
|
||||
SRCREV = "fc937358e71253a6efaa3ba74885364976b040ea"
|
||||
SRC_URI = "git://github.com/smuellerDD/libkcapi.git;branch=master;protocol=https \
|
||||
file://CVE-2026-71226-1.patch \
|
||||
file://CVE-2026-71226-2.patch \
|
||||
file://CVE-2026-71226-3.patch \
|
||||
"
|
||||
|
||||
inherit autotools
|
||||
|
||||
Reference in New Issue
Block a user