summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjulien.pierre.bugs%sun.com <devnull@localhost>2005-11-10 02:18:22 +0000
committerjulien.pierre.bugs%sun.com <devnull@localhost>2005-11-10 02:18:22 +0000
commit4e34366175e87167ed358ab2bac89491a597b86b (patch)
treeaba821c89d514e81b435e09d3d659a1956d2b4b4
parent679df5a910061279e38ffd2c711cfa29082d892d (diff)
downloadnss-hg-4e34366175e87167ed358ab2bac89491a597b86b.tar.gz
Resolve symlinks when loader freebl shared libs, and limit iterations to 20. r=wtchang
-rw-r--r--security/nss/lib/freebl/loader.c64
1 files changed, 63 insertions, 1 deletions
diff --git a/security/nss/lib/freebl/loader.c b/security/nss/lib/freebl/loader.c
index 0716d848c..b98ea9c68 100644
--- a/security/nss/lib/freebl/loader.c
+++ b/security/nss/lib/freebl/loader.c
@@ -123,6 +123,62 @@ getLibName(void)
static const char * getLibName(void) { return default_name; }
#endif
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+
+#define BL_MAXSYMLINKS 20
+
+/*
+ * If 'link' is a symbolic link, this function follows the symbolic links
+ * and returns the pathname of the ultimate source of the symbolic links.
+ * If 'link' is not a symbolic link, this function returns a copy of 'link'.
+ * The caller should call PR_Free to free the string returned by this
+ * function.
+ */
+static char* bl_GetOriginalPathname(const char* link)
+{
+#ifdef XP_UNIX
+ char* resolved = NULL;
+ char* input = NULL;
+ PRUint32 iterations = 0;
+ PRInt32 len = 0, retlen = 0;
+ if (!link) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+ len = PR_MAX(1024, strlen(link) + 1);
+ resolved = PR_Malloc(len);
+ input = PR_Malloc(len);
+ if (!resolved || !input) {
+ if (resolved) {
+ PR_Free(resolved);
+ }
+ if (input) {
+ PR_Free(input);
+ }
+ return NULL;
+ }
+ strcpy(input, link);
+ while ( (iterations++ < BL_MAXSYMLINKS) &&
+ ( (retlen = readlink(input, resolved, len - 1)) > 0) ) {
+ char* tmp = input;
+ resolved[retlen] = '\0'; /* NULL termination */
+ input = resolved;
+ resolved = tmp;
+ }
+ PR_Free(resolved);
+ return input;
+#else
+ if (link) {
+ return PL_strdup(link);
+ } else {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+#endif
+}
+
/*
* We use PR_GetLibraryFilePathname to get the pathname of the loaded
* shared lib that contains this function, and then do a PR_LoadLibrary
@@ -168,7 +224,13 @@ bl_LoadLibrary(const char *name)
/* Remove "libsoftokn" from the pathname and add the freebl libname */
if (softokenPath) {
- char* c = strrchr(softokenPath, PR_GetDirectorySeparator());
+ char* c;
+ char* originalSoftokenPath = bl_GetOriginalPathname(softokenPath);
+ if (originalSoftokenPath) {
+ PR_Free(softokenPath);
+ softokenPath = originalSoftokenPath;
+ }
+ c = strrchr(softokenPath, PR_GetDirectorySeparator());
if (c) {
size_t softoknPathSize = 1 + c - softokenPath;
fullName = (char*) PORT_Alloc(strlen(name) + softoknPathSize + 1);