File openCryptoki-SLE15-SP6-CVE-2026-23893.patch of Package openCryptoki.42499
diff -Naur a/usr/lib/common/loadsave.c b/usr/lib/common/loadsave.c
--- a/usr/lib/common/loadsave.c 2024-02-06 11:02:00.000000000 +0100
+++ b/usr/lib/common/loadsave.c 2026-01-29 10:28:50.167441078 +0100
@@ -43,6 +43,11 @@
#include "ock_syslog.h"
#include "slotmgr.h" // for ock_snprintf
+/*
+ *
+ */
+#include "platform.h"
+
extern void set_perm(int);
CK_RV restore_private_token_object_old(STDLL_TokData_t *tokdata, CK_BYTE *data,
@@ -67,9 +72,15 @@
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);
+ 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 +97,16 @@
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);
+ 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 +118,18 @@
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);
+ 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,13 @@
// 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 +266,8 @@
fclose(fp1);
fclose(fp2);
- fp2 = fopen(objidx, "w");
- fp1 = fopen(idxtmp, "r");
+ fp2 = fopen_nofollow(objidx, "w");
+ fp1 = fopen_nofollow(idxtmp, "r");
if (!fp1 || !fp2) {
if (fp1)
fclose(fp1);
@@ -526,11 +555,14 @@
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,10 +762,14 @@
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));
- rc = CKR_FUNCTION_FAILED;
+ 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,10 +1519,13 @@
rc = CKR_FUNCTION_FAILED;
goto done;
}
- fp = fopen(fname, "r");
if (!fp) {
- TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
- rc = CKR_FUNCTION_FAILED;
+ 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,10 +1611,14 @@
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));
- rc = CKR_FUNCTION_FAILED;
+ 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,12 +2222,16 @@
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));
- rc = CKR_FUNCTION_FAILED;
+ 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;
}
} else {
@@ -2355,14 +2402,17 @@
goto done;
}
- fp = fopen(fname, "r");
+ fp = fopen_nofollow(fname, "r");
if (fp == NULL) {
/* create new token object */
new = 1;
} else {
if (fstat(fileno(fp), &sb) != 0) {
- TRACE_ERROR("fstat(%s): %s\n", fname, strerror(errno));
- rc = CKR_FUNCTION_FAILED;
+ 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;
}
@@ -2453,9 +2503,13 @@
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 +2704,13 @@
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,10 +2821,14 @@
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));
- rc = CKR_FUNCTION_FAILED;
+ 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,7 +2885,7 @@
sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR);
strcat(fname, tmp);
- fp2 = fopen(fname, "r");
+ fp2 = fopen_nofollow(fname, "r");
if (!fp2)
continue;
diff -Naur a/usr/lib/common/platform.h b/usr/lib/common/platform.h
--- a/usr/lib/common/platform.h 2026-01-28 14:25:53.710577830 +0100
+++ b/usr/lib/common/platform.h 2026-01-28 09:57:21.399916646 +0100
@@ -0,0 +1,82 @@
+#ifndef PLATFORM_H
+#define PLATFORM_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 -Naur a/usr/lib/hsm_mk_change/hsm_mk_change.c b/usr/lib/hsm_mk_change/hsm_mk_change.c
--- a/usr/lib/hsm_mk_change/hsm_mk_change.c 2024-02-06 11:02:00.000000000 +0100
+++ b/usr/lib/hsm_mk_change/hsm_mk_change.c 2026-01-29 10:22:06.076511781 +0100
@@ -30,6 +30,11 @@
#include "hsm_mk_change.h"
#include "pkcs32.h"
+/*
+ *
+ */
+#include "platform.h"
+
struct hsm_mk_change_op_hdr {
char id[6];
uint32_t state; /* stored in big endian */
@@ -611,10 +616,15 @@
TRACE_DEVEL("file to open: %s mode: %s\n", hsm_mk_change_file, mode);
- fp = fopen(hsm_mk_change_file, mode);
+ 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));
+ }
}
return fp;
diff -Naur a/usr/lib/icsf_stdll/pbkdf.c b/usr/lib/icsf_stdll/pbkdf.c
--- a/usr/lib/icsf_stdll/pbkdf.c 2024-02-06 11:02:00.000000000 +0100
+++ b/usr/lib/icsf_stdll/pbkdf.c 2026-01-29 10:58:24.764278320 +0100
@@ -27,7 +27,11 @@
#include "h_extern.h"
#include "pbkdf.h"
#include "trace.h"
-
+
+/*
+ *
+ */
+#include "platform.h"
CK_RV get_randombytes(unsigned char *output, int bytes)
{
@@ -189,9 +193,12 @@
}
/* open the file */
- fp = fopen(fname, "r");
+ fp = fopen_nofollow(fname, "r");
if (fp == NULL) {
- TRACE_ERROR("fopen failed\n");
+ if (errno == ELOOP)
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
+ else
+ TRACE_ERROR("fopen failed\n");
return CKR_FUNCTION_FAILED;
}
@@ -288,9 +295,12 @@
}
/* if file exists, open it */
- fp = fopen(RACFFILE, "r");
+ fp = fopen_nofollow(RACFFILE, "r");
if (fp == NULL) {
- TRACE_ERROR("fopen failed\n");
+ if (errno == ELOOP)
+ TRACE_ERROR("Refusing to follow symlink: %s\n", RACFFILE);
+ else
+ TRACE_ERROR("fopen failed\n");
return CKR_FUNCTION_FAILED;
}
@@ -527,9 +537,12 @@
/* get the total length */
totallen = outputlen + AES_INIT_VECTOR_SIZE;
- fp = fopen(RACFFILE, "w");
+ 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 +613,12 @@
/* get the total length */
totallen = outputlen + SALTSIZE;
- fp = fopen(fname, "w");
+ 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 -Naur a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
--- a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c 2024-02-06 11:02:00.000000000 +0100
+++ b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c 2026-01-29 10:22:54.340861654 +0100
@@ -45,7 +45,11 @@
#define OCK_TOOL
#include "pkcs_utils.h"
#include "pin_prompt.h"
-
+
+/*
+ *
+ */
+#include "platform.h"
#define TOKVERSION_00 0x00000000
#define TOKVERSION_312 0x0003000C
@@ -70,9 +74,13 @@
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));
+ 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 +95,13 @@
file, tokenobj);
return NULL;
}
- res = fopen(buf, mode);
- if (!res)
- TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno));
+ 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;
}
@@ -725,9 +737,12 @@
/* Open file */
memset(fname, 0, PATH_MAX);
snprintf(fname, PATH_MAX, "%s/%s", data_store, mkfile);
- fp = fopen(fname, "r");
+ fp = fopen_nofollow(fname, "r");
if (!fp) {
- TRACE_ERROR("fopen(%s) failed, errno=%s\n", fname, strerror(errno));
+ if (errno == ELOOP)
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
+ else
+ TRACE_ERROR("fopen(%s) failed, errno=%s\n", fname, strerror(errno));
ret = CKR_FUNCTION_FAILED;
goto done;
}
@@ -802,9 +817,12 @@
int rc;
FILE *fp = NULL;
- fp = fopen(mkfile, "r");
+ fp = fopen_nofollow(mkfile, "r");
if (!fp) {
- TRACE_ERROR("fopen(%s) failed, errno=%s\n", mkfile, strerror(errno));
+ if (errno == ELOOP)
+ TRACE_ERROR("Refusing to follow symlink: %s\n", mkfile);
+ else
+ TRACE_ERROR("fopen(%s) failed, errno=%s\n", mkfile, strerror(errno));
return CKR_FUNCTION_FAILED;
}
@@ -1175,7 +1193,7 @@
struct ConfigBaseNode *config = NULL;
int ret;
- file = fopen(config_file, "r");
+ file = fopen_nofollow(config_file, "r");
if (file == NULL)
return NULL;
@@ -1840,7 +1858,7 @@
/* Open index file OBJ.IDX */
snprintf(iname, sizeof(iname), "%s/TOK_OBJ/OBJ.IDX", data_store);
- fp = fopen((char *) iname, "r");
+ fp = fopen_nofollow((char *) iname, "r");
if (!fp) {
TRACE_INFO("Cannot open %s, datastore probably empty.\n", iname);
ret = CKR_OK;
@@ -1890,9 +1908,12 @@
/* Read the NVTOK.DAT */
snprintf(fname, PATH_MAX, "%s/NVTOK.DAT", data_store);
- fp = fopen((char *)fname, "r");
+ fp = fopen_nofollow((char *)fname, "r");
if (!fp) {
- TRACE_ERROR("Cannot open %s, errno=%s\n", fname, strerror(errno));
+ if (errno == ELOOP)
+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
+ else
+ TRACE_ERROR("Cannot open %s, errno=%s\n", fname, strerror(errno));
return CKR_FUNCTION_FAILED;
}
@@ -2112,9 +2133,12 @@
/* Open new conf file for write */
snprintf(dst_file, PATH_MAX, "%s/%s", location, "opencryptoki.conf_new");
- fp_w = fopen(dst_file, "w");
+ fp_w = fopen_nofollow(dst_file, "w");
if (!fp_w) {
- TRACE_ERROR("fopen(%s) failed, errno=%s\n", dst_file, strerror(errno));
+ if (errno == ELOOP)
+ TRACE_ERROR("Refusing to follow symlink: %s\n", dst_file);
+ else
+ TRACE_ERROR("fopen(%s) failed, errno=%s\n", dst_file, strerror(errno));
ret = CKR_FUNCTION_FAILED;
goto done;
}
@@ -2194,14 +2218,14 @@
snprintf(dst_file, PATH_MAX, "%s/%s", dst, name);
snprintf(src_file, PATH_MAX, "%s/%s", src, name);
- fp_r = fopen(src_file, "r");
+ fp_r = fopen_nofollow(src_file, "r");
if (!fp_r) {
warnx("fopen(%s) failed, errno=%s", src_file, strerror(errno));
ret = CKR_FUNCTION_FAILED;
goto done;
}
- fp_w = fopen(dst_file, "w");
+ fp_w = fopen_nofollow(dst_file, "w");
if (!fp_w) {
warnx("fopen(%s) failed, errno=%s", dst_file, strerror(errno));
ret = CKR_FUNCTION_FAILED;
@@ -2446,7 +2470,7 @@
TRACE_INFO("Checking if pkcsslotd is running ...\n");
- fp = fopen(PID_FILE_PATH, "r");
+ fp = fopen_nofollow(PID_FILE_PATH, "r");
if (fp == NULL) {
TRACE_INFO("Pid file '%s' not existent, pkcsslotd is not running\n",
PID_FILE_PATH);
@@ -2469,7 +2493,7 @@
}
snprintf(fname, sizeof(fname), "/proc/%ld/cmdline", lpid);
- fp = fopen(fname, "r");
+ fp = fopen_nofollow(fname, "r");
if (fp == NULL) {
TRACE_INFO("Stale pid file, pkcsslotd is not running\n");
return CK_FALSE;