Compare commits
No commits in common. "c8" and "c8-beta" have entirely different histories.
@ -1,55 +0,0 @@
|
|||||||
From 742463a3c5a25313ab7ceb578d81b9998db65f67 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ingo Franzki <ifranzki@linux.ibm.com>
|
|
||||||
Date: Wed, 2 Apr 2025 16:36:45 +0200
|
|
||||||
Subject: [PATCH] CCA: Adjust CCA host library version detection for newer CCA
|
|
||||||
versions
|
|
||||||
|
|
||||||
Newer CCA versions might report the version string with CSUACFV or CSUACFQ
|
|
||||||
with keyword STATCCA using a different indicator character after the version
|
|
||||||
information. Ignore the indication character and the remaining data entirely.
|
|
||||||
Only the version information as such is of interest.
|
|
||||||
|
|
||||||
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
|
|
||||||
---
|
|
||||||
usr/lib/cca_stdll/cca_specific.c | 9 ++++-----
|
|
||||||
1 file changed, 4 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/usr/lib/cca_stdll/cca_specific.c b/usr/lib/cca_stdll/cca_specific.c
|
|
||||||
index 80369248..08e794d0 100644
|
|
||||||
--- a/usr/lib/cca_stdll/cca_specific.c
|
|
||||||
+++ b/usr/lib/cca_stdll/cca_specific.c
|
|
||||||
@@ -751,7 +751,6 @@ static CK_RV cca_get_version(STDLL_TokData_t *tokdata)
|
|
||||||
long return_code, reason_code;
|
|
||||||
long version_data_length;
|
|
||||||
long exit_data_len = 0;
|
|
||||||
- char date[20];
|
|
||||||
|
|
||||||
/* Get CCA host library version */
|
|
||||||
version_data_length = sizeof(version_data);
|
|
||||||
@@ -767,10 +766,10 @@ static CK_RV cca_get_version(STDLL_TokData_t *tokdata)
|
|
||||||
version_data[sizeof(version_data) - 1] = '\0';
|
|
||||||
TRACE_DEVEL("CCA Version string: %s\n", version_data);
|
|
||||||
|
|
||||||
- if (sscanf((char *)version_data, "%u.%u.%uz%s",
|
|
||||||
+ if (sscanf((char *)version_data, "%u.%u.%u",
|
|
||||||
&cca_private->cca_lib_version.ver,
|
|
||||||
&cca_private->cca_lib_version.rel,
|
|
||||||
- &cca_private->cca_lib_version.mod, date) != 4) {
|
|
||||||
+ &cca_private->cca_lib_version.mod) != 3) {
|
|
||||||
TRACE_ERROR("CCA library version is invalid: %s\n", version_data);
|
|
||||||
return CKR_FUNCTION_FAILED;
|
|
||||||
}
|
|
||||||
@@ -3431,8 +3430,8 @@ static CK_RV cca_get_adapter_version(cca_min_card_version_t *data)
|
|
||||||
memcpy(ccaversion, &rule_array[CCA_STATCCA_CCA_VERSION_OFFSET],
|
|
||||||
CCA_STATCCA_CCA_VERSION_LENGTH);
|
|
||||||
|
|
||||||
- if (sscanf(ccaversion, "%d.%d.%02d*", (int *)&adapter_version.ver,
|
|
||||||
- (int *)&adapter_version.rel, (int *)&adapter_version.mod) != 3) {
|
|
||||||
+ if (sscanf(ccaversion, "%u.%u.%u", &adapter_version.ver,
|
|
||||||
+ &adapter_version.rel, &adapter_version.mod) != 3) {
|
|
||||||
TRACE_ERROR("sscanf of string %s failed, cannot determine CCA card version\n",
|
|
||||||
ccaversion);
|
|
||||||
return CKR_FUNCTION_FAILED;
|
|
||||||
--
|
|
||||||
2.16.2.windows.1
|
|
||||||
|
|
||||||
@ -1,499 +0,0 @@
|
|||||||
commit b3392430af1fe260386d609c967f514679d218a4
|
|
||||||
Author: Pavel Kohout <pavel@aisle.com>
|
|
||||||
Date: Tue Jan 13 00:00:00 2026 +0000
|
|
||||||
|
|
||||||
Fix symlink-following vulnerabilities (CWE-59)
|
|
||||||
|
|
||||||
Multiple symlink-following vulnerabilities exist in OpenCryptoki that run
|
|
||||||
in privileged contexts. These allow a token-group user to redirect file
|
|
||||||
operations to arbitrary filesystem targets by planting symlinks in
|
|
||||||
group-writable token directories, resulting in privilege escalation or
|
|
||||||
data exposure.
|
|
||||||
|
|
||||||
Affected components:
|
|
||||||
1. pkcstok_migrate: fopen() follows symlinks, then set_perm() modifies the
|
|
||||||
target permissions.
|
|
||||||
2. loadsave.c: Multiple wrapper functions use fopen() followed by set_perm().
|
|
||||||
3. hsm_mk_change.c: hsm_mk_change_op_open() uses fopen() followed by
|
|
||||||
hsm_mk_change_op_set_perm().
|
|
||||||
4. pbkdf.c: fopen() followed by set_perms() in two locations.
|
|
||||||
|
|
||||||
This fix:
|
|
||||||
- Introduces fopen_nofollow() helper in platform.h
|
|
||||||
- Checks for O_NOFOLLOW at compile time (not hardcoded per-platform)
|
|
||||||
- On platforms with O_NOFOLLOW: uses open(O_NOFOLLOW) + fdopen() for atomic
|
|
||||||
symlink rejection (race-condition free)
|
|
||||||
- On platforms without O_NOFOLLOW: falls back to lstat() + fopen() and emits
|
|
||||||
a compiler warning so the unsafe fallback doesn't go unnoticed
|
|
||||||
- Updates all affected wrapper functions to use fopen_nofollow()
|
|
||||||
|
|
||||||
Reported-by: Pavel Kohout, Aisle Research, www.aisle.com
|
|
||||||
Signed-off-by: Pavel Kohout <pavel@aisle.com>
|
|
||||||
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
|
|
||||||
|
|
||||||
diff --git a/usr/lib/common/loadsave.c b/usr/lib/common/loadsave.c
|
|
||||||
index 09553b51..352a71dc 100644
|
|
||||||
--- a/usr/lib/common/loadsave.c
|
|
||||||
+++ b/usr/lib/common/loadsave.c
|
|
||||||
@@ -42,6 +42,7 @@
|
|
||||||
#include "trace.h"
|
|
||||||
#include "ock_syslog.h"
|
|
||||||
#include "slotmgr.h" // for ock_snprintf
|
|
||||||
+#include "platform.h"
|
|
||||||
|
|
||||||
extern void set_perm(int);
|
|
||||||
|
|
||||||
@@ -67,9 +68,17 @@ static FILE *open_token_object_path(char *buf, size_t buflen,
|
|
||||||
STDLL_TokData_t *tokdata, char *path,
|
|
||||||
char *mode)
|
|
||||||
{
|
|
||||||
+ FILE *fp;
|
|
||||||
+
|
|
||||||
if (get_token_object_path(buf, buflen, tokdata, path) < 0)
|
|
||||||
return NULL;
|
|
||||||
- return fopen(buf, mode);
|
|
||||||
+
|
|
||||||
+ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
|
|
||||||
+ fp = fopen_nofollow(buf, mode);
|
|
||||||
+ if (fp == NULL && errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", buf);
|
|
||||||
+
|
|
||||||
+ return fp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_token_data_store_path(char *buf, size_t buflen,
|
|
||||||
@@ -86,9 +95,17 @@ static FILE *open_token_data_store_path(char *buf, size_t buflen,
|
|
||||||
STDLL_TokData_t *tokdata, char *path,
|
|
||||||
char *mode)
|
|
||||||
{
|
|
||||||
+ FILE *fp;
|
|
||||||
+
|
|
||||||
if (get_token_data_store_path(buf, buflen, tokdata, path) < 0)
|
|
||||||
return NULL;
|
|
||||||
- return fopen(buf, mode);
|
|
||||||
+
|
|
||||||
+ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
|
|
||||||
+ fp = fopen_nofollow(buf, mode);
|
|
||||||
+ if (fp == NULL && errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", buf);
|
|
||||||
+
|
|
||||||
+ return fp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FILE *open_token_object_index(char *buf, size_t buflen,
|
|
||||||
@@ -100,11 +117,19 @@ static FILE *open_token_object_index(char *buf, size_t buflen,
|
|
||||||
static FILE *open_token_nvdat(char *buf, size_t buflen,
|
|
||||||
STDLL_TokData_t *tokdata, char *mode)
|
|
||||||
{
|
|
||||||
+ FILE *fp;
|
|
||||||
+
|
|
||||||
if (ock_snprintf(buf, buflen, "%s/" PK_LITE_NV, tokdata->data_store)) {
|
|
||||||
TRACE_ERROR("NVDAT.TOK file name buffer overflow\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
- return fopen(buf, mode);
|
|
||||||
+
|
|
||||||
+ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
|
|
||||||
+ fp = fopen_nofollow(buf, mode);
|
|
||||||
+ if (fp == NULL && errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", buf);
|
|
||||||
+
|
|
||||||
+ return fp;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *get_pk_dir(STDLL_TokData_t *tokdata, char *fname, size_t len)
|
|
||||||
@@ -185,9 +210,12 @@ CK_RV save_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
|
|
||||||
// we didn't find it...either the index file doesn't exist or this
|
|
||||||
// is a new object...
|
|
||||||
//
|
|
||||||
- fp = fopen(fname, "a");
|
|
||||||
+ fp = fopen_nofollow(fname, "a");
|
|
||||||
if (!fp) {
|
|
||||||
- TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
return CKR_FUNCTION_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -237,8 +265,12 @@ CK_RV delete_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
|
|
||||||
|
|
||||||
fclose(fp1);
|
|
||||||
fclose(fp2);
|
|
||||||
- fp2 = fopen(objidx, "w");
|
|
||||||
- fp1 = fopen(idxtmp, "r");
|
|
||||||
+ fp2 = fopen_nofollow(objidx, "w");
|
|
||||||
+ if (fp1 == NULL && errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", objidx);
|
|
||||||
+ fp1 = fopen_nofollow(idxtmp, "r");
|
|
||||||
+ if (fp2 == NULL && errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", idxtmp);
|
|
||||||
if (!fp1 || !fp2) {
|
|
||||||
if (fp1)
|
|
||||||
fclose(fp1);
|
|
||||||
@@ -526,11 +558,14 @@ CK_RV load_token_data_old(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id)
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
init_token_data(tokdata, slot_id);
|
|
||||||
|
|
||||||
- fp = fopen(fname, "r");
|
|
||||||
+ fp = fopen_nofollow(fname, "r");
|
|
||||||
if (!fp) {
|
|
||||||
// were really hosed here since the created
|
|
||||||
// did not occur
|
|
||||||
- TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
rc = CKR_FUNCTION_FAILED;
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
@@ -730,9 +765,12 @@ static CK_RV save_private_token_object_old(STDLL_TokData_t *tokdata, OBJECT *obj
|
|
||||||
rc = CKR_FUNCTION_FAILED;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
- fp = fopen(fname, "w");
|
|
||||||
+ fp = fopen_nofollow(fname, "w");
|
|
||||||
if (!fp) {
|
|
||||||
- TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
rc = CKR_FUNCTION_FAILED;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
@@ -1483,9 +1521,12 @@ CK_RV reload_token_object_old(STDLL_TokData_t *tokdata, OBJECT *obj)
|
|
||||||
rc = CKR_FUNCTION_FAILED;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
- fp = fopen(fname, "r");
|
|
||||||
+ fp = fopen_nofollow(fname, "r");
|
|
||||||
if (!fp) {
|
|
||||||
- TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
rc = CKR_FUNCTION_FAILED;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
@@ -1572,9 +1613,12 @@ CK_RV save_public_token_object_old(STDLL_TokData_t *tokdata, OBJECT * obj)
|
|
||||||
rc = CKR_FUNCTION_FAILED;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
- fp = fopen(fname, "w");
|
|
||||||
+ fp = fopen_nofollow(fname, "w");
|
|
||||||
if (!fp) {
|
|
||||||
- TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
rc = CKR_FUNCTION_FAILED;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
@@ -2179,11 +2223,14 @@ CK_RV load_token_data(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id)
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
init_token_data(tokdata, slot_id);
|
|
||||||
|
|
||||||
- fp = fopen(fname, "r");
|
|
||||||
+ fp = fopen_nofollow(fname, "r");
|
|
||||||
if (!fp) {
|
|
||||||
// were really hosed here since the created
|
|
||||||
// did not occur
|
|
||||||
- TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
rc = CKR_FUNCTION_FAILED;
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
@@ -2355,7 +2402,7 @@ CK_RV save_private_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
- fp = fopen(fname, "r");
|
|
||||||
+ fp = fopen_nofollow(fname, "r");
|
|
||||||
if (fp == NULL) {
|
|
||||||
/* create new token object */
|
|
||||||
new = 1;
|
|
||||||
@@ -2453,9 +2500,12 @@ do_work:
|
|
||||||
if (rc != CKR_OK)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
- fp = fopen(fname, "w");
|
|
||||||
+ fp = fopen_nofollow(fname, "w");
|
|
||||||
if (!fp) {
|
|
||||||
- TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
rc = CKR_FUNCTION_FAILED;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
@@ -2650,9 +2700,12 @@ CK_RV reload_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
|
|
||||||
sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR);
|
|
||||||
strncat(fname, (char *) obj->name, 8);
|
|
||||||
|
|
||||||
- fp = fopen(fname, "r");
|
|
||||||
+ fp = fopen_nofollow(fname, "r");
|
|
||||||
if (!fp) {
|
|
||||||
- TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
rc = CKR_FUNCTION_FAILED;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
@@ -2763,9 +2816,12 @@ CK_RV save_public_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
|
|
||||||
sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR);
|
|
||||||
strncat(fname, (char *) obj->name, 8);
|
|
||||||
|
|
||||||
- fp = fopen(fname, "w");
|
|
||||||
+ fp = fopen_nofollow(fname, "w");
|
|
||||||
if (!fp) {
|
|
||||||
- TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
||||||
rc = CKR_FUNCTION_FAILED;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
@@ -2823,9 +2879,12 @@ CK_RV load_public_token_objects(STDLL_TokData_t *tokdata)
|
|
||||||
sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR);
|
|
||||||
strcat(fname, tmp);
|
|
||||||
|
|
||||||
- fp2 = fopen(fname, "r");
|
|
||||||
- if (!fp2)
|
|
||||||
+ fp2 = fopen_nofollow(fname, "r");
|
|
||||||
+ if (!fp2) {
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
|
|
||||||
continue;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (fread(header, PUB_HEADER_LEN, 1, fp2) != 1) {
|
|
||||||
fclose(fp2);
|
|
||||||
diff --git a/usr/lib/common/platform.h b/usr/lib/common/platform.h
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..b3e5473b
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/usr/lib/common/platform.h
|
|
||||||
@@ -0,0 +1,91 @@
|
|
||||||
+/*
|
|
||||||
+ * COPYRIGHT (c) International Business Machines Corp. 2024
|
|
||||||
+ *
|
|
||||||
+ * This program is provided under the terms of the Common Public License,
|
|
||||||
+ * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
|
|
||||||
+ * software constitutes recipient's acceptance of CPL-1.0 terms which can be
|
|
||||||
+ * found in the file LICENSE file or at
|
|
||||||
+ * https://opensource.org/licenses/cpl1.0.php
|
|
||||||
+ */
|
|
||||||
+#ifndef PLATFORM_H
|
|
||||||
+#define PLATFORM_H
|
|
||||||
+
|
|
||||||
+#include <dlfcn.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <fcntl.h>
|
|
||||||
+#include <unistd.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <sys/stat.h>
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Check for O_NOFOLLOW support at compile time.
|
|
||||||
+ * If not available, fall back to lstat() + fopen() (has TOCTOU race).
|
|
||||||
+ */
|
|
||||||
+#ifndef O_NOFOLLOW
|
|
||||||
+#define OCK_NO_O_NOFOLLOW 1
|
|
||||||
+#warning "O_NOFOLLOW not supported, symlink protection uses racy lstat() fallback!"
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * CWE-59 fix: Open file without following symlinks.
|
|
||||||
+ *
|
|
||||||
+ * On platforms with O_NOFOLLOW support:
|
|
||||||
+ * Uses open(O_NOFOLLOW) + fdopen() for atomic symlink rejection.
|
|
||||||
+ *
|
|
||||||
+ * On platforms without O_NOFOLLOW (e.g., older AIX):
|
|
||||||
+ * Falls back to lstat() + fopen(). This has a TOCTOU race condition,
|
|
||||||
+ * but still catches pre-planted symlinks which is the common attack
|
|
||||||
+ * scenario. Better than no protection at all.
|
|
||||||
+ *
|
|
||||||
+ * Returns NULL with errno=ELOOP if path is a symlink.
|
|
||||||
+ */
|
|
||||||
+static inline FILE *fopen_nofollow(const char *path, const char *mode)
|
|
||||||
+{
|
|
||||||
+#ifdef OCK_NO_O_NOFOLLOW
|
|
||||||
+ /*
|
|
||||||
+ * Fallback for platforms without O_NOFOLLOW: use lstat() check.
|
|
||||||
+ * This has a TOCTOU race but catches pre-planted symlinks.
|
|
||||||
+ */
|
|
||||||
+ struct stat sb;
|
|
||||||
+
|
|
||||||
+ if (lstat(path, &sb) == 0) {
|
|
||||||
+ if (S_ISLNK(sb.st_mode)) {
|
|
||||||
+ errno = ELOOP;
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ /* Note: if lstat fails (e.g., file doesn't exist for "w" mode),
|
|
||||||
+ * we proceed with fopen() which will handle the error appropriately */
|
|
||||||
+ return fopen(path, mode);
|
|
||||||
+#else
|
|
||||||
+ /* Preferred: atomic symlink rejection via O_NOFOLLOW */
|
|
||||||
+ int flags = O_NOFOLLOW;
|
|
||||||
+ int fd;
|
|
||||||
+ FILE *fp;
|
|
||||||
+
|
|
||||||
+ /* Determine flags based on mode */
|
|
||||||
+ if (mode[0] == 'r') {
|
|
||||||
+ flags |= (mode[1] == '+') ? O_RDWR : O_RDONLY;
|
|
||||||
+ } else if (mode[0] == 'w') {
|
|
||||||
+ flags |= O_CREAT | O_TRUNC | ((mode[1] == '+') ? O_RDWR : O_WRONLY);
|
|
||||||
+ } else if (mode[0] == 'a') {
|
|
||||||
+ flags |= O_CREAT | O_APPEND | ((mode[1] == '+') ? O_RDWR : O_WRONLY);
|
|
||||||
+ } else {
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ fd = open(path, flags, 0600);
|
|
||||||
+ if (fd < 0)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ fp = fdopen(fd, mode);
|
|
||||||
+ if (fp == NULL) {
|
|
||||||
+ close(fd);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ return fp;
|
|
||||||
+#endif
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#endif /* PLATFORM_H */
|
|
||||||
diff --git a/usr/lib/hsm_mk_change/hsm_mk_change.c b/usr/lib/hsm_mk_change/hsm_mk_change.c
|
|
||||||
index 6c032965..bbdd94c2 100644
|
|
||||||
--- a/usr/lib/hsm_mk_change/hsm_mk_change.c
|
|
||||||
+++ b/usr/lib/hsm_mk_change/hsm_mk_change.c
|
|
||||||
@@ -29,6 +29,7 @@
|
|
||||||
#endif
|
|
||||||
#include "hsm_mk_change.h"
|
|
||||||
#include "pkcs32.h"
|
|
||||||
+#include "platform.h"
|
|
||||||
|
|
||||||
struct hsm_mk_change_op_hdr {
|
|
||||||
char id[6];
|
|
||||||
@@ -611,9 +612,13 @@ static FILE* hsm_mk_change_op_open(const char *id, CK_SLOT_ID slot_id,
|
|
||||||
|
|
||||||
TRACE_DEVEL("file to open: %s mode: %s\n", hsm_mk_change_file, mode);
|
|
||||||
|
|
||||||
- fp = fopen(hsm_mk_change_file, mode);
|
|
||||||
+ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
|
|
||||||
+ fp = fopen_nofollow(hsm_mk_change_file, mode);
|
|
||||||
if (fp == NULL) {
|
|
||||||
- TRACE_ERROR("%s fopen(%s, %s): %s\n", __func__,
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", hsm_mk_change_file);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("%s fopen(%s, %s): %s\n", __func__,
|
|
||||||
hsm_mk_change_file, mode, strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/usr/lib/icsf_stdll/pbkdf.c b/usr/lib/icsf_stdll/pbkdf.c
|
|
||||||
index abf9ff13..e50fe4e2 100644
|
|
||||||
--- a/usr/lib/icsf_stdll/pbkdf.c
|
|
||||||
+++ b/usr/lib/icsf_stdll/pbkdf.c
|
|
||||||
@@ -27,6 +27,7 @@
|
|
||||||
#include "h_extern.h"
|
|
||||||
#include "pbkdf.h"
|
|
||||||
#include "trace.h"
|
|
||||||
+#include "platform.h"
|
|
||||||
|
|
||||||
|
|
||||||
CK_RV get_randombytes(unsigned char *output, int bytes)
|
|
||||||
@@ -527,9 +528,13 @@ CK_RV secure_racf(STDLL_TokData_t *tokdata,
|
|
||||||
/* get the total length */
|
|
||||||
totallen = outputlen + AES_INIT_VECTOR_SIZE;
|
|
||||||
|
|
||||||
- fp = fopen(RACFFILE, "w");
|
|
||||||
+ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
|
|
||||||
+ fp = fopen_nofollow(RACFFILE, "w");
|
|
||||||
if (!fp) {
|
|
||||||
- TRACE_ERROR("fopen failed: %s\n", strerror(errno));
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", RACFFILE);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("fopen failed: %s\n", strerror(errno));
|
|
||||||
return CKR_FUNCTION_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -600,9 +605,13 @@ CK_RV secure_masterkey(STDLL_TokData_t *tokdata,
|
|
||||||
/* get the total length */
|
|
||||||
totallen = outputlen + SALTSIZE;
|
|
||||||
|
|
||||||
- fp = fopen(fname, "w");
|
|
||||||
+ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
|
|
||||||
+ fp = fopen_nofollow(fname, "w");
|
|
||||||
if (!fp) {
|
|
||||||
- TRACE_ERROR("fopen failed: %s\n", strerror(errno));
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("fopen failed: %s\n", strerror(errno));
|
|
||||||
return CKR_FUNCTION_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
|
|
||||||
index a9777a3c..84988b2c 100644
|
|
||||||
--- a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
|
|
||||||
+++ b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
|
|
||||||
@@ -41,6 +41,7 @@
|
|
||||||
#include "local_types.h"
|
|
||||||
#include "h_extern.h"
|
|
||||||
#include "slotmgr.h" // for ock_snprintf
|
|
||||||
+#include "platform.h"
|
|
||||||
|
|
||||||
#define OCK_TOOL
|
|
||||||
#include "pkcs_utils.h"
|
|
||||||
@@ -70,9 +71,14 @@ static FILE *open_datastore_file(char *buf, size_t buflen,
|
|
||||||
TRACE_ERROR("Path overflow for datastore file %s\n", file);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
- res = fopen(buf, mode);
|
|
||||||
- if (!res)
|
|
||||||
- TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno));
|
|
||||||
+ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
|
|
||||||
+ res = fopen_nofollow(buf, mode);
|
|
||||||
+ if (!res) {
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", buf);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno));
|
|
||||||
+ }
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -87,9 +93,14 @@ static FILE *open_tokenobject(char *buf, size_t buflen,
|
|
||||||
file, tokenobj);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
- res = fopen(buf, mode);
|
|
||||||
- if (!res)
|
|
||||||
- TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno));
|
|
||||||
+ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
|
|
||||||
+ res = fopen_nofollow(buf, mode);
|
|
||||||
+ if (!res) {
|
|
||||||
+ if (errno == ELOOP)
|
|
||||||
+ TRACE_ERROR("Refusing to follow symlink: %s\n", buf);
|
|
||||||
+ else
|
|
||||||
+ TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno));
|
|
||||||
+ }
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
Name: opencryptoki
|
Name: opencryptoki
|
||||||
Summary: Implementation of the PKCS#11 (Cryptoki) specification v3.0
|
Summary: Implementation of the PKCS#11 (Cryptoki) specification v3.0
|
||||||
Version: 3.22.0
|
Version: 3.22.0
|
||||||
Release: 3%{?dist}.2
|
Release: 3%{?dist}
|
||||||
License: CPL
|
License: CPL
|
||||||
Group: System Environment/Base
|
Group: System Environment/Base
|
||||||
URL: https://github.com/opencryptoki/opencryptoki
|
URL: https://github.com/opencryptoki/opencryptoki
|
||||||
@ -21,10 +21,6 @@ Patch21: opencryptoki-CVE-2024-0914-part2.patch
|
|||||||
Patch22: opencryptoki-CVE-2024-0914-part3.patch
|
Patch22: opencryptoki-CVE-2024-0914-part3.patch
|
||||||
Patch23: opencryptoki-CVE-2024-0914-part4.patch
|
Patch23: opencryptoki-CVE-2024-0914-part4.patch
|
||||||
Patch24: opencryptoki-CVE-2024-0914-part5.patch
|
Patch24: opencryptoki-CVE-2024-0914-part5.patch
|
||||||
# supporting CCA 8.4
|
|
||||||
Patch25: 3.22-CCA-Adjust-CCA-host-library-version-detection-for-ne.patch
|
|
||||||
# CVE-3-2026-23893, symlink-following vulnerabilities
|
|
||||||
Patch26: opencryptoki-3.20.0-CVE-3-2026-23893.patch
|
|
||||||
|
|
||||||
Requires(pre): coreutils diffutils
|
Requires(pre): coreutils diffutils
|
||||||
Requires: (selinux-policy >= 3.14.3-121 if selinux-policy-targeted)
|
Requires: (selinux-policy >= 3.14.3-121 if selinux-policy-targeted)
|
||||||
@ -385,12 +381,6 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Mon Mar 02 2026 Than Ngo <than@redhat.com> - 3.22.0-3.2
|
|
||||||
- Resolves: RHEL-144817, CVE-2026-23893 Privilege Escalation or Data Exposure via Symlink Following
|
|
||||||
|
|
||||||
* Mon Aug 11 2025 Than Ngo <than@redhat.com> - 3.22.0-3.1
|
|
||||||
- Resolves: RHEL-105918, fix for supporting CCA 8.4
|
|
||||||
|
|
||||||
* Fri Feb 16 2024 Than Ngo <than@redhat.com> - 3.22.0-3
|
* Fri Feb 16 2024 Than Ngo <than@redhat.com> - 3.22.0-3
|
||||||
- Fix implicit rejection with RSA keys with empty CKA_PRIVATE_EXPONENT
|
- Fix implicit rejection with RSA keys with empty CKA_PRIVATE_EXPONENT
|
||||||
Related: RHEL-22791
|
Related: RHEL-22791
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user