From c4bd40a483c7962beb4a8b1c7f84d647de66bf0c Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Tue, 29 Aug 2017 13:08:11 +0200
Subject: [PATCH 1/5] util: fix the return value type of ReadDERFromFile()
SECStatus is an inappropriate type for returning the count of objects.
Upstream-commit: 01c13264e59050ea34aefc3d2a38e9ead247276c
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/ckpem.h | 6 ++----
src/pinst.c | 15 +++++----------
src/pobject.c | 10 ++++------
src/util.c | 7 +++----
4 files changed, 14 insertions(+), 24 deletions(-)
diff --git a/src/ckpem.h b/src/ckpem.h
index e6ecc5f..be9977a 100644
--- a/src/ckpem.h
+++ b/src/ckpem.h
@@ -259,10 +259,8 @@ pem_CreateMDObject
#define NSS_PEM_ARRAY_SIZE(x) ((sizeof (x))/(sizeof ((x)[0])))
/* Read DER encoded data from a PEM file or a binary (der-encoded) file. */
-/* NOTE: Discrepancy with the the way callers use of the return value as a count
- * Fix this when we sync. up with the cleanup work being done at nss-pem project.
- */
-SECStatus ReadDERFromFile(SECItem ***derlist, char *filename, PRBool ascii, int *cipher, char **ivstring, PRBool certsonly);
+int ReadDERFromFile(SECItem ***derlist, char *filename, PRBool ascii,
+ int *cipher, char **ivstring, PRBool certsonly);
/* Fetch an attribute of the specified type. */
const NSSItem * pem_FetchAttribute ( pemInternalObject *io, CK_ATTRIBUTE_TYPE type, CK_RV *pError);
diff --git a/src/pinst.c b/src/pinst.c
index 25485b1..a5901f0 100644
--- a/src/pinst.c
+++ b/src/pinst.c
@@ -475,14 +475,12 @@ AddCertificate(char *certfile, char *keyfile, PRBool cacert,
pemInternalObject *o = NULL;
CK_RV error = 0;
int objid, i = 0;
- int nobjs = 0;
SECItem **objs = NULL;
char *ivstring = NULL;
int cipher;
- /* TODO: Fix discrepancy between our usage of the return value as
- * as an int (a count) and the declaration as a SECStatus. */
- nobjs = (int) ReadDERFromFile(&objs, certfile, PR_TRUE, &cipher, &ivstring, PR_TRUE /* certs only */);
+ int nobjs = ReadDERFromFile(&objs, certfile, /* ascii */ PR_TRUE, &cipher,
+ &ivstring, /* certs only */ PR_TRUE);
if (nobjs <= 0) {
NSS_ZFreeIf(objs);
return CKR_GENERAL_ERROR;
@@ -517,12 +515,9 @@ AddCertificate(char *certfile, char *keyfile, PRBool cacert,
if (o != NULL && keyfile != NULL) { /* add the private key */
SECItem **keyobjs = NULL;
- int kobjs = 0;
- /* TODO: Fix discrepancy between our usage of the return value as
- * as an int and the declaration as a SECStatus. */
- kobjs =
- (int) ReadDERFromFile(&keyobjs, keyfile, PR_TRUE, &cipher,
- &ivstring, PR_FALSE);
+ int kobjs = ReadDERFromFile(&keyobjs, keyfile, /* ascii */ PR_TRUE,
+ &cipher, &ivstring,
+ /*certs only */ PR_FALSE);
if (kobjs < 1) {
found_error = PR_TRUE;
} else {
diff --git a/src/pobject.c b/src/pobject.c
index 918b327..d80092a 100644
--- a/src/pobject.c
+++ b/src/pobject.c
@@ -1165,11 +1165,8 @@ pem_CreateObject
}
if (objClass == CKO_CERTIFICATE) {
- /* TODO: Fix discrepancy between our usage of the return value as
- * as an int and the declaration as a SECStatus. Typecasting as a
- * temporary workaround.
- */
- nobjs = (int) ReadDERFromFile(&derlist, filename, PR_TRUE, &cipher, &ivstring, PR_TRUE /* certs only */);
+ nobjs = ReadDERFromFile(&derlist, filename, /* ascii */ PR_TRUE,
+ &cipher, &ivstring, /* certs only */ PR_TRUE);
if (nobjs < 1)
goto loser;
@@ -1213,7 +1210,8 @@ pem_CreateObject
SECItem certDER;
PRBool added;
- nobjs = ReadDERFromFile(&derlist, filename, PR_TRUE, &cipher, &ivstring, PR_FALSE /* keys only */);
+ nobjs = ReadDERFromFile(&derlist, filename, /* ascii */ PR_TRUE,
+ &cipher, &ivstring, /* keys only */ PR_FALSE);
if (nobjs < 1)
goto loser;
diff --git a/src/util.c b/src/util.c
index ee9e0a4..9bad613 100644
--- a/src/util.c
+++ b/src/util.c
@@ -144,10 +144,9 @@ static SECStatus ConvertAsciiToZAllocItem(SECItem *der, const char *ascii)
return rv;
}
-/* FIX: Returns a SECStatus yet callers take result as a count */
-SECStatus
-ReadDERFromFile(SECItem *** derlist, char *filename, PRBool ascii,
- int *cipher, char **ivstring, PRBool certsonly)
+/* returns count of objects read, or -1 on error */
+int ReadDERFromFile(SECItem *** derlist, char *filename, PRBool ascii,
+ int *cipher, char **ivstring, PRBool certsonly)
{
SECStatus rv;
PRFileDesc *inFile;
--
2.17.2
From 729f16122f0bae216583323389aa6ef1418e4c37 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Thu, 20 Dec 2018 18:42:33 +0100
Subject: [PATCH 2/5] ckpem: make pem_objs a list instead of array
Since libcurl started to use PK11_CreateManagedGenericObject(),
the calls to PK11_DestroyGenericObject() started to take affect
at the level of nss-pem. Internal objects were removed on each
call of curl_easy_cleanup() and allocated again on each call of
curl_easy_perform(). This would be fine if the corresponding items
of the global pem_objects array were reused, which was, however,
not the case. Consequently, the array grew unboundedly while most
of its items were NULL pointers. This caused severe performance
regression in libcurl-based applications.
This commit replaces the global array by a global linked list,
which allows to delete arbitrary items instead of keeping NULL
pointers. For compatibility reasons, the original array indexes
are stored in the list nodes.
Bug: https://bugzilla.redhat.com/1659108
Fixes #2
Upstream-commit: 8fc25a6b062a34d09473d4f80058fffda37f41a2
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/ckpem.h | 11 ++-
src/list.h | 200 +++++++++++++++++++++++++++++++++++++++++++++++++
src/pfind.c | 19 ++---
src/pinst.c | 56 +++++++-------
src/pobject.c | 27 +++----
src/psession.c | 11 +--
6 files changed, 258 insertions(+), 66 deletions(-)
create mode 100644 src/list.h
diff --git a/src/ckpem.h b/src/ckpem.h
index be9977a..caad74b 100644
--- a/src/ckpem.h
+++ b/src/ckpem.h
@@ -39,6 +39,8 @@
#ifndef CKPEM_H
#define CKPEM_H
+#include "list.h"
+
#define USE_UTIL_DIRECTLY
#include <utilrename.h>
@@ -197,9 +199,14 @@ struct pemInternalObjectStr {
char *nickname;
NSSCKMDObject mdObject;
CK_SLOT_ID slotID;
- CK_ULONG gobjIndex;
int refCount;
+ /* all internal objects are linked in a global list */
+ struct list_head gl_list;
+
+ /* we represent sparse array as list but keep its elements indexed */
+ long arrayIdx;
+
/* used by pem_mdFindObjects_Next */
CK_BBOOL extRef;
@@ -208,7 +215,7 @@ struct pemInternalObjectStr {
pemObjectListItem *list;
};
-NSS_EXTERN_DATA pemInternalObject **pem_objs;
+NSS_EXTERN_DATA struct list_head pem_objs;
NSS_EXTERN_DATA int pem_nobjs;
NSS_EXTERN_DATA int token_needsLogin[];
NSS_EXTERN_DATA NSSCKMDSlot *lastEventSlot;
diff --git a/src/list.h b/src/list.h
new file mode 100644
index 0000000..7b4aec4
--- /dev/null
+++ b/src/list.h
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+/* simplified for our use case */
+#define READ_ONCE(x) (x)
+#define WRITE_ONCE(dst, src) (dst = (src))
+#define typeof(x) __typeof__(x)
+#define POISON_POINTER_DELTA 0
+
+/* following code is taken from <linux/list.h> of v4.20-rc7-202-g1d51b4b1d3f2 */
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({ \
+ void *__mptr = (void *)(ptr); \
+ ((type *)(__mptr - offsetof(type, member))); })
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA)
+#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA)
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+ WRITE_ONCE(list->next, list);
+ list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ WRITE_ONCE(prev->next, new);
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+ next->prev = prev;
+ WRITE_ONCE(prev->next, next);
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void __list_del_entry(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+static inline void list_del(struct list_head *entry)
+{
+ __list_del_entry(entry);
+ entry->next = LIST_POISON1;
+ entry->prev = LIST_POISON2;
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_head within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+/**
+ * list_last_entry - get the last element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_head within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_last_entry(ptr, type, member) \
+ list_entry((ptr)->prev, type, member)
+
+/**
+ * list_next_entry - get the next element in list
+ * @pos: the type * to cursor
+ * @member: the name of the list_head within the struct.
+ */
+#define list_next_entry(pos, member) \
+ list_entry((pos)->member.next, typeof(*(pos)), member)
+
+/**
+ * list_prev_entry - get the prev element in list
+ * @pos: the type * to cursor
+ * @member: the name of the list_head within the struct.
+ */
+#define list_prev_entry(pos, member) \
+ list_entry((pos)->member.prev, typeof(*(pos)), member)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_first_entry(head, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_next_entry(pos, member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_last_entry(head, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_prev_entry(pos, member))
+
+#endif
diff --git a/src/pfind.c b/src/pfind.c
index 2aff8ff..3f0fdcb 100644
--- a/src/pfind.c
+++ b/src/pfind.c
@@ -253,12 +253,13 @@ collect_objects(CK_ATTRIBUTE_PTR pTemplate,
size_t result_array_capacity = 0;
pemObjectType type = pemRaw;
CK_OBJECT_CLASS objClass = pem_GetObjectClass(pTemplate, ulAttributeCount);
+ pemInternalObject *obj = NULL;
*pError = CKR_OK;
plog("collect_objects slot #%ld, ", slotID);
plog("%d attributes, ", ulAttributeCount);
- plog("%d objects to look through.\n", pem_nobjs);
+ plog("%d objects created in total.\n", pem_nobjs);
plog("Looking for: ");
/*
* now determine type of the object
@@ -299,22 +300,18 @@ collect_objects(CK_ATTRIBUTE_PTR pTemplate,
}
/* find objects */
- for (i = 0; i < pem_nobjs; i++) {
+ list_for_each_entry(obj, &pem_objs, gl_list) {
int match = 1; /* matches type if type not specified */
- if (NULL == pem_objs[i])
- continue;
-
- plog(" %d type = %d\n", i, pem_objs[i]->type);
+ plog(" %d type = %d\n", i, obj->type);
if (type != pemAll) {
/* type specified - must match given type */
- match = (type == pem_objs[i]->type);
+ match = (type == obj->type);
}
if (match) {
- match = (slotID == pem_objs[i]->slotID) &&
- (CK_TRUE == pem_match(pTemplate, ulAttributeCount, pem_objs[i]));
+ match = (slotID == obj->slotID) &&
+ (CK_TRUE == pem_match(pTemplate, ulAttributeCount, obj));
}
if (match) {
- pemInternalObject *o = pem_objs[i];
pemInternalObject **new_result_array = (pemInternalObject **)
ensure_array_capacity(*result_array,
&result_array_capacity,
@@ -328,7 +325,7 @@ collect_objects(CK_ATTRIBUTE_PTR pTemplate,
if (*result_array != new_result_array) {
*result_array = new_result_array;
}
- (*result_array)[ result_array_entries ] = o;
+ (*result_array)[ result_array_entries ] = obj;
result_array_entries++;
}
}
diff --git a/src/pinst.c b/src/pinst.c
index a5901f0..810db5a 100644
--- a/src/pinst.c
+++ b/src/pinst.c
@@ -50,7 +50,7 @@
static PRBool pemInitialized = PR_FALSE;
-pemInternalObject **pem_objs;
+LIST_HEAD(pem_objs);
int pem_nobjs = 0;
int token_needsLogin[NUM_SLOTS];
NSSCKMDSlot *lastEventSlot;
@@ -362,13 +362,9 @@ derEncodingsMatch(CK_OBJECT_CLASS objClass, pemInternalObject * obj,
static CK_RV
LinkSharedKeyObject(int oldKeyIdx, int newKeyIdx)
{
- int i;
- for (i = 0; i < pem_nobjs; i++) {
+ pemInternalObject *obj;
+ list_for_each_entry(obj, &pem_objs, gl_list) {
CK_RV rv;
- pemInternalObject *obj = pem_objs[i];
- if (NULL == obj)
- continue;
-
if (atoi(obj->id.data) != oldKeyIdx)
continue;
@@ -381,13 +377,26 @@ LinkSharedKeyObject(int oldKeyIdx, int newKeyIdx)
return CKR_OK;
}
+/* return pointer to the internal object with given arrayIdx */
+static pemInternalObject *
+FindObjectByArrayIdx(const long arrayIdx)
+{
+ pemInternalObject *obj;
+
+ list_for_each_entry(obj, &pem_objs, gl_list)
+ if (arrayIdx == obj->arrayIdx)
+ return obj;
+
+ return NULL;
+}
+
pemInternalObject *
AddObjectIfNeeded(CK_OBJECT_CLASS objClass,
pemObjectType type, SECItem * certDER,
SECItem * keyDER, const char *filename,
int objid, CK_SLOT_ID slotID, PRBool *pAdded)
{
- int i;
+ pemInternalObject *curObj;
const char *nickname = strrchr(filename, '/');
if (nickname
@@ -401,11 +410,7 @@ AddObjectIfNeeded(CK_OBJECT_CLASS objClass,
*pAdded = PR_FALSE;
/* first look for the object in pem_objs, it might be already there */
- for (i = 0; i < pem_nobjs; i++) {
- pemInternalObject *const curObj = pem_objs[i];
- if (NULL == curObj)
- continue;
-
+ list_for_each_entry(curObj, &pem_objs, gl_list) {
/* Comparing DER encodings is dependable and frees the PEM module
* from having to require clients to provide unique nicknames.
*/
@@ -419,11 +424,11 @@ AddObjectIfNeeded(CK_OBJECT_CLASS objClass,
* the key object is shared by multiple client certificates, such
* an assumption does not hold. We have to update the references.
*/
- LinkSharedKeyObject(pem_nobjs, i);
+ LinkSharedKeyObject(pem_nobjs, curObj->arrayIdx);
if (CKO_CERTIFICATE == objClass) {
const int ref = atoi(curObj->id.data);
- if (0 < ref && ref < pem_nobjs && !pem_objs[ref]) {
+ if (0 < ref && ref < pem_nobjs && !FindObjectByArrayIdx(ref)) {
/* The certificate we are going to reuse refers to an
* object that has already been removed. Make it refer
* to the object that will be added next (private key).
@@ -433,7 +438,8 @@ AddObjectIfNeeded(CK_OBJECT_CLASS objClass,
}
}
- plog("AddObjectIfNeeded: re-using internal object #%i\n", i);
+ plog("AddObjectIfNeeded: re-using internal object #%li\n",
+ curObj->arrayIdx);
curObj->refCount ++;
return curObj;
}
@@ -448,18 +454,9 @@ AddObjectIfNeeded(CK_OBJECT_CLASS objClass,
/* initialize pointers to functions */
pem_CreateMDObject(NULL, io, NULL);
- io->gobjIndex = pem_nobjs;
-
- /* add object to global array */
- if (pem_objs)
- pem_objs = NSS_ZRealloc(pem_objs,
- (pem_nobjs + 1) * sizeof(pemInternalObject *));
- else
- pem_objs = NSS_ZNEWARRAY(NULL, pemInternalObject *, 1);
- if (!pem_objs)
- return NULL;
- pem_objs[pem_nobjs] = io;
- pem_nobjs++;
+ /* add object to global list */
+ io->arrayIdx = pem_nobjs++;
+ list_add_tail(&io->gl_list, &pem_objs);
if (pAdded)
*pAdded = PR_TRUE;
@@ -748,8 +745,7 @@ pem_Finalize
if (!pemInitialized)
return;
- NSS_ZFreeIf(pem_objs);
- pem_objs = NULL;
+ INIT_LIST_HEAD(&pem_objs);
pem_nobjs = 0;
PR_AtomicSet(&pemInitialized, PR_FALSE);
diff --git a/src/pobject.c b/src/pobject.c
index d80092a..f118f5d 100644
--- a/src/pobject.c
+++ b/src/pobject.c
@@ -672,10 +672,8 @@ pem_DestroyInternalObject
return;
}
- if (NULL != pem_objs)
- /* remove reference to self from the global array */
- pem_objs[io->gobjIndex] = NULL;
-
+ /* remove self from the global list */
+ list_del(&io->gl_list);
NSS_ZFreeIf(io);
return;
}
@@ -1206,7 +1204,7 @@ pem_CreateObject
goto loser;
}
} else if (objClass == CKO_PRIVATE_KEY) {
- int i;
+ pemInternalObject *curObj;
SECItem certDER;
PRBool added;
@@ -1220,30 +1218,27 @@ pem_CreateObject
/* Brute force: find the id of the certificate, if any, in this slot */
objid = -1;
- for (i = pem_nobjs - 1; 0 <= i; i--) {
- if (NULL == pem_objs[i])
- continue;
-
- if (slotID != pem_objs[i]->slotID)
+ list_for_each_entry_reverse(curObj, &pem_objs, gl_list) {
+ if (slotID != curObj->slotID)
continue;
- if (pem_objs[i]->type != pemCert)
+ if (curObj->type != pemCert)
continue;
- if (atoi(pem_objs[i]->id.data) != pem_nobjs)
+ if (atoi(curObj->id.data) != pem_nobjs)
/* not a certificate that refers to the key being added */
continue;
objid = pem_nobjs;
- certDER.data = NSS_ZAlloc(NULL, pem_objs[i]->derCert->len);
+ certDER.data = NSS_ZAlloc(NULL, curObj->derCert->len);
if (certDER.data == NULL)
goto loser;
- certDER.len = pem_objs[i]->derCert->len;
+ certDER.len = curObj->derCert->len;
memcpy(certDER.data,
- pem_objs[i]->derCert->data,
- pem_objs[i]->derCert->len);
+ curObj->derCert->data,
+ curObj->derCert->len);
break;
}
diff --git a/src/psession.c b/src/psession.c
index 4e94a7f..13a5e5d 100644
--- a/src/psession.c
+++ b/src/psession.c
@@ -241,7 +241,7 @@ pem_mdSession_Login
NSSLOWKEYPrivateKey *lpk = NULL;
PLArenaPool *arena;
SECItem plain;
- int i;
+ pemInternalObject *curObj;
fwSlot = NSSCKFWToken_GetFWSlot(fwToken);
slotID = NSSCKFWSlot_GetSlotID(fwSlot);
@@ -256,12 +256,9 @@ pem_mdSession_Login
token_needsLogin[slotID - 1] = PR_FALSE;
/* Find the right key object */
- for (i = 0; i < pem_nobjs; i++) {
- if (NULL == pem_objs[i])
- continue;
-
- if ((slotID == pem_objs[i]->slotID) && (pem_objs[i]->type == pemBareKey)) {
- io = pem_objs[i];
+ list_for_each_entry(curObj, &pem_objs, gl_list) {
+ if ((slotID == curObj->slotID) && (curObj->type == pemBareKey)) {
+ io = curObj;
break;
}
}
--
2.17.2
From 6d968e0f54bfd48029086ae41067e6024bde76a2 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Fri, 21 Dec 2018 13:43:47 +0100
Subject: [PATCH 3/5] ckpem: define pem_nobjs and objid as long to avoid
wraparound
Fixes #2
Upstream-commit: 5a14b625f529b35f997f60f4ff302f0bfc6ddc16
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/ckpem.h | 4 ++--
src/pfind.c | 2 +-
src/pinst.c | 29 +++++++++++++++--------------
src/pobject.c | 4 ++--
4 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/src/ckpem.h b/src/ckpem.h
index caad74b..5d05087 100644
--- a/src/ckpem.h
+++ b/src/ckpem.h
@@ -216,7 +216,7 @@ struct pemInternalObjectStr {
};
NSS_EXTERN_DATA struct list_head pem_objs;
-NSS_EXTERN_DATA int pem_nobjs;
+NSS_EXTERN_DATA long pem_nobjs;
NSS_EXTERN_DATA int token_needsLogin[];
NSS_EXTERN_DATA NSSCKMDSlot *lastEventSlot;
@@ -304,7 +304,7 @@ PRBool pem_ParseString(const char *inputstring, const char delimiter,
pemInternalObject *
AddObjectIfNeeded(CK_OBJECT_CLASS objClass, pemObjectType type,
- SECItem *certDER, SECItem *keyDER, const char *filename, int objid,
+ SECItem *certDER, SECItem *keyDER, const char *filename, long objid,
CK_SLOT_ID slotID, PRBool *pAdded);
void pem_DestroyInternalObject (pemInternalObject *io);
diff --git a/src/pfind.c b/src/pfind.c
index 3f0fdcb..958c0d5 100644
--- a/src/pfind.c
+++ b/src/pfind.c
@@ -259,7 +259,7 @@ collect_objects(CK_ATTRIBUTE_PTR pTemplate,
plog("collect_objects slot #%ld, ", slotID);
plog("%d attributes, ", ulAttributeCount);
- plog("%d objects created in total.\n", pem_nobjs);
+ plog("%ld objects created in total.\n", pem_nobjs);
plog("Looking for: ");
/*
* now determine type of the object
diff --git a/src/pinst.c b/src/pinst.c
index 810db5a..87bf7c2 100644
--- a/src/pinst.c
+++ b/src/pinst.c
@@ -51,7 +51,7 @@
static PRBool pemInitialized = PR_FALSE;
LIST_HEAD(pem_objs);
-int pem_nobjs = 0;
+long pem_nobjs = 0L;
int token_needsLogin[NUM_SLOTS];
NSSCKMDSlot *lastEventSlot;
@@ -182,12 +182,12 @@ GetCertFields(unsigned char *cert, int cert_length,
}
static CK_RV
-assignObjectID(pemInternalObject *o, int objid)
+assignObjectID(pemInternalObject *o, const long objid)
{
- char id[16];
+ char id[24];
int len;
- sprintf(id, "%d", objid);
+ sprintf(id, "%ld", objid);
len = strlen(id) + 1; /* zero terminate */
o->id.size = len;
o->id.data = NSS_ZAlloc(NULL, len);
@@ -202,7 +202,7 @@ static pemInternalObject *
CreateObject(CK_OBJECT_CLASS objClass,
pemObjectType type, SECItem * certDER,
SECItem * keyDER, const char *filename,
- int objid, CK_SLOT_ID slotID)
+ long objid, CK_SLOT_ID slotID)
{
pemInternalObject *o;
SECItem subject;
@@ -226,17 +226,17 @@ CreateObject(CK_OBJECT_CLASS objClass,
switch (objClass) {
case CKO_CERTIFICATE:
- plog("Creating cert nick %s id %d in slot %ld\n", nickname, objid, slotID);
+ plog("Creating cert nick %s id %ld in slot %ld\n", nickname, objid, slotID);
memset(&o->u.cert, 0, sizeof(o->u.cert));
break;
case CKO_PRIVATE_KEY:
- plog("Creating key id %d in slot %ld\n", objid, slotID);
+ plog("Creating key id %ld in slot %ld\n", objid, slotID);
memset(&o->u.key, 0, sizeof(o->u.key));
/* more unique nicknames - https://bugzilla.redhat.com/689031#c66 */
nickname = filename;
break;
case CKO_NETSCAPE_TRUST:
- plog("Creating trust nick %s id %d in slot %ld\n", nickname, objid, slotID);
+ plog("Creating trust nick %s id %ld in slot %ld\n", nickname, objid, slotID);
memset(&o->u.trust, 0, sizeof(o->u.trust));
break;
}
@@ -360,12 +360,12 @@ derEncodingsMatch(CK_OBJECT_CLASS objClass, pemInternalObject * obj,
}
static CK_RV
-LinkSharedKeyObject(int oldKeyIdx, int newKeyIdx)
+LinkSharedKeyObject(const long oldKeyIdx, const long newKeyIdx)
{
pemInternalObject *obj;
list_for_each_entry(obj, &pem_objs, gl_list) {
CK_RV rv;
- if (atoi(obj->id.data) != oldKeyIdx)
+ if (atol(obj->id.data) != oldKeyIdx)
continue;
NSS_ZFreeIf(obj->id.data);
@@ -394,7 +394,7 @@ pemInternalObject *
AddObjectIfNeeded(CK_OBJECT_CLASS objClass,
pemObjectType type, SECItem * certDER,
SECItem * keyDER, const char *filename,
- int objid, CK_SLOT_ID slotID, PRBool *pAdded)
+ long objid, CK_SLOT_ID slotID, PRBool *pAdded)
{
pemInternalObject *curObj;
@@ -427,7 +427,7 @@ AddObjectIfNeeded(CK_OBJECT_CLASS objClass,
LinkSharedKeyObject(pem_nobjs, curObj->arrayIdx);
if (CKO_CERTIFICATE == objClass) {
- const int ref = atoi(curObj->id.data);
+ const long ref = atol(curObj->id.data);
if (0 < ref && ref < pem_nobjs && !FindObjectByArrayIdx(ref)) {
/* The certificate we are going to reuse refers to an
* object that has already been removed. Make it refer
@@ -471,7 +471,8 @@ AddCertificate(char *certfile, char *keyfile, PRBool cacert,
{
pemInternalObject *o = NULL;
CK_RV error = 0;
- int objid, i = 0;
+ long objid;
+ int i = 0;
SECItem **objs = NULL;
char *ivstring = NULL;
int cipher;
@@ -746,7 +747,7 @@ pem_Finalize
return;
INIT_LIST_HEAD(&pem_objs);
- pem_nobjs = 0;
+ pem_nobjs = 0L;
PR_AtomicSet(&pemInitialized, PR_FALSE);
}
diff --git a/src/pobject.c b/src/pobject.c
index f118f5d..9a8321c 100644
--- a/src/pobject.c
+++ b/src/pobject.c
@@ -1089,7 +1089,7 @@ pem_CreateObject
SECItem **derlist = NULL;
int nobjs = 0;
int i;
- int objid;
+ long objid;
#if 0
pemToken *token;
#endif
@@ -1225,7 +1225,7 @@ pem_CreateObject
if (curObj->type != pemCert)
continue;
- if (atoi(curObj->id.data) != pem_nobjs)
+ if (atol(curObj->id.data) != pem_nobjs)
/* not a certificate that refers to the key being added */
continue;
--
2.17.2
From 513ac624ec4c640f53f2bcdee11dc332358b77d7 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Fri, 21 Dec 2018 14:26:01 +0100
Subject: [PATCH 4/5] ckpem: keep objid as number to avoid use of atol()
Fixes #2
Upstream-commit: 188c63f7b824e256d20b70ee080ea88d96d8e9c6
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/ckpem.h | 1 +
src/pinst.c | 5 +++--
src/pobject.c | 2 +-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/ckpem.h b/src/ckpem.h
index 5d05087..e2f18cf 100644
--- a/src/ckpem.h
+++ b/src/ckpem.h
@@ -194,6 +194,7 @@ struct pemInternalObjectStr {
CK_OBJECT_CLASS objClass;
NSSItem hashKey;
NSSItem id;
+ long objid;
unsigned char hashKeyData[128];
SECItem *derCert;
char *nickname;
diff --git a/src/pinst.c b/src/pinst.c
index 87bf7c2..26f3ac2 100644
--- a/src/pinst.c
+++ b/src/pinst.c
@@ -195,6 +195,7 @@ assignObjectID(pemInternalObject *o, const long objid)
return CKR_HOST_MEMORY;
memcpy(o->id.data, id, len);
+ o->objid = objid;
return CKR_OK;
}
@@ -365,7 +366,7 @@ LinkSharedKeyObject(const long oldKeyIdx, const long newKeyIdx)
pemInternalObject *obj;
list_for_each_entry(obj, &pem_objs, gl_list) {
CK_RV rv;
- if (atol(obj->id.data) != oldKeyIdx)
+ if (obj->objid != oldKeyIdx)
continue;
NSS_ZFreeIf(obj->id.data);
@@ -427,7 +428,7 @@ AddObjectIfNeeded(CK_OBJECT_CLASS objClass,
LinkSharedKeyObject(pem_nobjs, curObj->arrayIdx);
if (CKO_CERTIFICATE == objClass) {
- const long ref = atol(curObj->id.data);
+ const long ref = curObj->objid;
if (0 < ref && ref < pem_nobjs && !FindObjectByArrayIdx(ref)) {
/* The certificate we are going to reuse refers to an
* object that has already been removed. Make it refer
diff --git a/src/pobject.c b/src/pobject.c
index 9a8321c..2ffffed 100644
--- a/src/pobject.c
+++ b/src/pobject.c
@@ -1225,7 +1225,7 @@ pem_CreateObject
if (curObj->type != pemCert)
continue;
- if (atol(curObj->id.data) != pem_nobjs)
+ if (curObj->objid != pem_nobjs)
/* not a certificate that refers to the key being added */
continue;
--
2.17.2
From db140f2d9259ac73d59c50a658d444e418b81c3c Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Wed, 16 Jan 2019 16:19:50 +0100
Subject: [PATCH 5/5] pfind: fix use of uninitialized var in plog() call
Detected by static analysis:
Error: UNINIT (CWE-457):
nss-pem-1.0.3/src/pfind.c:251: var_decl: Declaring variable "i" without initializer.
nss-pem-1.0.3/src/pfind.c:305: uninit_use_in_call: Using uninitialized value "i" when calling "plog".
303| list_for_each_entry(obj, &pem_objs, gl_list) {
304| int match = 1; /* matches type if type not specified */
305|-> plog(" %d type = %d\n", i, obj->type);
306| if (type != pemAll) {
307| /* type specified - must match given type */
Error: CLANG_WARNING:
nss-pem-1.0.3/src/pfind.c:305:9: warning: Function call argument is an uninitialized value
nss-pem-1.0.3/src/pfind.c:364:9: note: Assuming 'fwSlot' is not equal to null
nss-pem-1.0.3/src/pfind.c:364:5: note: Taking false branch
nss-pem-1.0.3/src/pfind.c:370:9: note: Assuming 'arena' is not equal to null
nss-pem-1.0.3/src/pfind.c:370:5: note: Taking false branch
nss-pem-1.0.3/src/pfind.c:375:9: note: Assuming 'rv' is not equal to null
nss-pem-1.0.3/src/pfind.c:375:5: note: Taking false branch
nss-pem-1.0.3/src/pfind.c:381:9: note: Assuming 'fo' is not equal to null
nss-pem-1.0.3/src/pfind.c:381:5: note: Taking false branch
nss-pem-1.0.3/src/pfind.c:395:9: note: Calling 'collect_objects'
nss-pem-1.0.3/src/pfind.c:251:5: note: 'i' declared without an initial value
nss-pem-1.0.3/src/pfind.c:267:5: note: Control jumps to 'case 0:' at line 293
nss-pem-1.0.3/src/pfind.c:296:9: note: Execution continues on line 303
nss-pem-1.0.3/src/pfind.c:305:9: note: Function call argument is an uninitialized value
Error: COMPILER_WARNING:
nss-pem-1.0.3/src/pfind.c: scope_hint: In function 'pem_FindObjectsInit'
nss-pem-1.0.3/src/pfind.c:305:13: warning: 'i' may be used uninitialized in this function [-Wmaybe-uninitialized]
nss-pem-1.0.3/src/pfind.c:251:14: note: 'i' was declared here
Upstream-commit: 5c05ed268675c7544b1a51198e1e9e566be17608
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/pfind.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/pfind.c b/src/pfind.c
index 958c0d5..83d5b89 100644
--- a/src/pfind.c
+++ b/src/pfind.c
@@ -248,7 +248,6 @@ collect_objects(CK_ATTRIBUTE_PTR pTemplate,
pemInternalObject *** result_array,
CK_RV * pError, CK_SLOT_ID slotID)
{
- PRUint32 i;
size_t result_array_entries = 0;
size_t result_array_capacity = 0;
pemObjectType type = pemRaw;
@@ -302,7 +301,7 @@ collect_objects(CK_ATTRIBUTE_PTR pTemplate,
/* find objects */
list_for_each_entry(obj, &pem_objs, gl_list) {
int match = 1; /* matches type if type not specified */
- plog(" %d type = %d\n", i, obj->type);
+ plog(" %ld type = %d\n", obj->arrayIdx, obj->type);
if (type != pemAll) {
/* type specified - must match given type */
match = (type == obj->type);
--
2.17.2