diff -up ./mozilla/security/nss/lib/freebl/Makefile.prelink ./mozilla/security/nss/lib/freebl/Makefile --- ./mozilla/security/nss/lib/freebl/Makefile.prelink 2010-09-04 14:13:58.846327263 -0700 +++ ./mozilla/security/nss/lib/freebl/Makefile 2010-09-04 14:15:11.544326993 -0700 @@ -82,6 +82,12 @@ ifeq ($(FREEBL_NO_DEPEND),1) else MAPFILE_SOURCE = freebl.def endif +ifdef FREEBL_USE_PRELINK + DEFINES += -DFREEBL_USE_PRELINK +endif +ifdef FREEBL_PRELINK_COMMAND + DEFINES +=-DFREEBL_PRELINK_COMMAND=\"$(FREEBL_PRELINK_COMMAND)\" +endif # NSS_X86 means the target is a 32-bits x86 CPU architecture # NSS_X64 means the target is a 64-bits x64 CPU architecture # NSS_X86_OR_X64 means the target is either x86 or x64 diff -up ./mozilla/security/nss/lib/freebl/shvfy.c.prelink ./mozilla/security/nss/lib/freebl/shvfy.c --- ./mozilla/security/nss/lib/freebl/shvfy.c.prelink 2010-09-04 14:16:01.518326988 -0700 +++ ./mozilla/security/nss/lib/freebl/shvfy.c 2010-09-04 14:25:44.770326384 -0700 @@ -48,6 +48,168 @@ #include "stdio.h" #include "prmem.h" +#ifdef FREEBL_USE_PRELINK +#ifndef FREEBL_PRELINK_COMMAND +#define FREEBL_PRELINK_COMMAND "/usr/sbin/prelink -u -o -" +#endif +#include "private/pprio.h" + +#include +#include +#include +#include +#include + +PRFileDesc * +bl_OpenUnPrelink(const char *shName, int *pid) +{ + char *command= strdup(FREEBL_PRELINK_COMMAND); + char *argString = NULL; + char **argv = NULL; + char *shNameArg = NULL; + char *cp; + pid_t child; + int argc = 0, argNext = 0; + struct stat statBuf; + int pipefd[2] = {-1,-1}; + int ret; + + *pid = 0; + + /* make sure the prelink command exists first. If not, fall back to + * just reading the file */ + for (cp = command; *cp ; cp++) { + if (*cp == ' ') { + *cp++ = 0; + argString = cp; + break; + } + } + memset (&statBuf, 0, sizeof(statBuf)); + /* stat the file, follow the link */ + ret = stat(command, &statBuf); + if (ret < 0) { + free(command); + return PR_Open(shName, PR_RDONLY, 0); + } + /* file exits, make sure it's an executable */ + if (!S_ISREG(statBuf.st_mode) || + ((statBuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0)) { + free(command); + return PR_Open(shName, PR_RDONLY, 0); + } + + /* OK, the prelink command exists and looks correct, use it */ + /* build the arglist while we can still malloc */ + /* count the args if any */ + if (argString && *argString) { + /* argString may have leading spaces, strip them off*/ + for (cp = argString; *cp && *cp == ' '; cp++); + argString = cp; + if (*cp) { + /* there is at least one arg.. */ + argc = 1; + } + + /* count the rest: Note there is no provision for escaped + * spaces here */ + for (cp = argString; *cp ; cp++) { + if (*cp == ' ') { + while (*cp && *cp == ' ') cp++; + if (*cp) argc++; + } + } + } + + /* add the additional args: argv[0] (command), shName, NULL*/ + argc += 3; + argv = PORT_NewArray(char *, argc); + if (argv == NULL) { + goto loser; + } + + /* fill in the arglist */ + argv[argNext++] = command; + if (argString && *argString) { + argv[argNext++] = argString; + for (cp = argString; *cp; cp++) { + if (*cp == ' ') { + *cp++ = 0; + while (*cp && *cp == ' ') cp++; + if (*cp) argv[argNext++] = cp; + } + } + } + /* exec doesn't advertise taking const char **argv, do the paranoid + * copy */ + shNameArg = strdup(shName); + if (shNameArg == NULL) { + goto loser; + } + argv[argNext++] = shNameArg; + argv[argNext++] = 0; + + ret = pipe(pipefd); + if (ret < 0) { + goto loser; + } + + /* use vfork() so we don't trigger the pthread_at_fork() handlers */ + child = vfork(); + if (child < 0) goto loser; + if (child == 0) { + /* set up the file descriptors */ + close(0); + /* associate pipefd[1] with stdout */ + if (pipefd[1] != 1) dup2(pipefd[1], 1); + close(2); + close(pipefd[0]); + /* should probably close the other file descriptors? */ + + + execv(command, argv); + /* avoid at_exit() handlers */ + _exit(1); /* shouldn't reach here except on an error */ + } + close(pipefd[1]); + pipefd[1] = -1; + + /* this is safe because either vfork() as full fork() semantics, and thus + * already has it's own address space, or because vfork() has paused + * the parent util the exec or exit */ + free(command); + free(shNameArg); + PORT_Free(argv); + + *pid = child; + + return PR_ImportPipe(pipefd[0]); + +loser: + if (pipefd[0] != -1) { + close(pipefd[0]); + } + if (pipefd[1] != -1) { + close(pipefd[1]); + } + free(command); + free(shNameArg); + PORT_Free(argv); + + return NULL; +} + +void +bl_CloseUnPrelink( PRFileDesc *file, int pid) +{ + /* close the file descriptor */ + PR_Close(file); + /* reap the child */ + if (pid) { + waitpid(pid, NULL, 0); + } +} +#endif /* #define DEBUG_SHVERIFY 1 */ @@ -117,6 +279,9 @@ BLAPI_SHVerify(const char *name, PRFuncP SECStatus rv; DSAPublicKey key; int count; +#ifdef FREEBL_USE_PRELINK + int pid = 0; +#endif PRBool result = PR_FALSE; /* if anything goes wrong, * the signature does not verify */ @@ -197,7 +362,11 @@ BLAPI_SHVerify(const char *name, PRFuncP checkFD = NULL; /* open our library file */ +#ifdef FREEBL_USE_PRELINK + shFD = bl_OpenUnPrelink(shName,&pid); +#else shFD = PR_Open(shName, PR_RDONLY, 0); +#endif if (shFD == NULL) { #ifdef DEBUG_SHVERIFY fprintf(stderr, "Failed to open the library file %s: (%d, %d)\n", @@ -218,7 +387,11 @@ BLAPI_SHVerify(const char *name, PRFuncP SHA1_Update(hashcx, buf, bytesRead); count += bytesRead; } +#ifdef FREEBL_USE_PRELINK + bl_CloseUnPrelink(shFD, pid); +#else PR_Close(shFD); +#endif shFD = NULL; SHA1_End(hashcx, hash.data, &hash.len, hash.len); diff -up ./mozilla/security/nss/lib/freebl/stubs.c.prelink ./mozilla/security/nss/lib/freebl/stubs.c --- ./mozilla/security/nss/lib/freebl/stubs.c.prelink 2010-09-04 14:26:27.454327120 -0700 +++ ./mozilla/security/nss/lib/freebl/stubs.c 2010-09-04 14:31:56.778327428 -0700 @@ -69,6 +69,7 @@ #include #include #include +#include #define FREEBL_NO_WEAK 1 @@ -157,6 +158,8 @@ STUB_DECLARE(void,PR_Lock,(PRLock *lock) STUB_DECLARE(PRLock *,PR_NewLock,(void)); STUB_DECLARE(PRFileDesc *,PR_Open,(const char *name, PRIntn flags, PRIntn mode)); +STUB_DECLARE(PRFileDesc *,PR_ImportFile,(PROsfd osfd)); +STUB_DECLARE(PRFileDesc *,PR_ImportPipe,(PROsfd osfd)); STUB_DECLARE(PRInt32,PR_Read,(PRFileDesc *fd, void *buf, PRInt32 amount)); STUB_DECLARE(PROffset32,PR_Seek,(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence)); @@ -295,6 +298,34 @@ PR_Open_stub(const char *name, PRIntn fl return (PRFileDesc *)lfd; } +extern PRFileDesc * +PR_ImportFile_stub(PROsfd fd) +{ + int *lfd = NULL; + + STUB_SAFE_CALL1(PR_ImportFile, fd); + + lfd = PORT_New_stub(int); + if (lfd != NULL) { + *lfd = fd; + } + return (PRFileDesc *)lfd; +} + +extern PRFileDesc * +PR_ImportPipe_stub(PROsfd fd) +{ + int *lfd = NULL; + + STUB_SAFE_CALL1(PR_ImportPipe, fd); + + lfd = PORT_New_stub(int); + if (lfd != NULL) { + *lfd = fd; + } + return (PRFileDesc *)lfd; +} + extern PRStatus PR_Close_stub(PRFileDesc *fd) { @@ -492,6 +523,8 @@ freebl_InitNSPR(void *lib) { STUB_FETCH_FUNCTION(PR_Free); STUB_FETCH_FUNCTION(PR_Open); + STUB_FETCH_FUNCTION(PR_ImportFile); + STUB_FETCH_FUNCTION(PR_ImportPipe); STUB_FETCH_FUNCTION(PR_Close); STUB_FETCH_FUNCTION(PR_Read); STUB_FETCH_FUNCTION(PR_Seek); diff -up ./mozilla/security/nss/lib/freebl/stubs.h.prelink ./mozilla/security/nss/lib/freebl/stubs.h --- ./mozilla/security/nss/lib/freebl/stubs.h.prelink 2010-09-04 14:26:41.822327256 -0700 +++ ./mozilla/security/nss/lib/freebl/stubs.h 2010-09-04 14:32:53.498540767 -0700 @@ -78,6 +78,8 @@ #define PR_Lock PR_Lock_stub #define PR_NewLock PR_NewLock_stub #define PR_Open PR_Open_stub +#define PR_ImportFile PR_ImportFile_stub +#define PR_ImportPipe PR_ImportPipe_stub #define PR_Read PR_Read_stub #define PR_Seek PR_Seek_stub #define PR_Sleep PR_Sleep_stub