diff -c -r src.old/Security.pbproj/project.pbxproj src/Security.pbproj/project.pbxproj *** src.old/Security.pbproj/project.pbxproj Wed Dec 18 22:26:19 2002 --- src/Security.pbproj/project.pbxproj Wed Dec 18 22:26:12 2002 *************** *** 126,132 **** HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/BSafe.framework/Headers\" \"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks/BSafe.framework/Headers\" \"$(SRCROOT)/AppleCSP\" \"$(SRCROOT)/AppleCSP/open_ssl\""; LIBRARY_STYLE = STATIC; OPTIMIZATION_CFLAGS = "-O3 -DNDEBUG"; ! OTHER_CFLAGS = "-DCRYPTKIT_CSP_ENABLE -DASC_CSP_ENABLE -DVDADER_RULES -DALLOW_ZERO_PASSWORD -DCRYPTKIT_DER_ENABLE"; OTHER_LDFLAGS = ""; OTHER_LIBTOOL_FLAGS = ""; OTHER_REZFLAGS = ""; --- 126,132 ---- HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/BSafe.framework/Headers\" \"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks/BSafe.framework/Headers\" \"$(SRCROOT)/AppleCSP\" \"$(SRCROOT)/AppleCSP/open_ssl\""; LIBRARY_STYLE = STATIC; OPTIMIZATION_CFLAGS = "-O3 -DNDEBUG"; ! OTHER_CFLAGS = "-DVDADER_RULES -DALLOW_ZERO_PASSWORD -DCRYPTKIT_DER_ENABLE"; OTHER_LDFLAGS = ""; OTHER_LIBTOOL_FLAGS = ""; OTHER_REZFLAGS = ""; *************** *** 9263,9273 **** INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; LIBRARY_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)\""; OPTIMIZATION_CFLAGS = "-Os -DNDEBUG"; ! OTHER_CFLAGS = "-DLIMITED_SIGNING -DBUILTIN_PLUGINS -DVDADER_RULES -DCRYPTKIT_CSP_ENABLE -DASC_CSP_ENABLE"; ! OTHER_LDFLAGS = "-lComCryption -lCryptKit -twolevel_namespace"; PREBINDING = YES; PRODUCT_NAME = Security; ! SECTORDER_FLAGS = "-sectorder __TEXT __text \"$(APPLE_INTERNAL_DIR)/OrderFiles/Security.order\" -seg_addr_table \"$(APPLE_INTERNAL_DEVELOPER_DIR)/seg_addr_table\""; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = Sec; WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; --- 9263,9273 ---- INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; LIBRARY_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)\""; OPTIMIZATION_CFLAGS = "-Os -DNDEBUG"; ! OTHER_CFLAGS = "-DLIMITED_SIGNING -DBUILTIN_PLUGINS -DVDADER_RULES"; ! OTHER_LDFLAGS = "-twolevel_namespace"; PREBINDING = YES; PRODUCT_NAME = Security; ! SECTORDER_FLAGS = ""; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = Sec; WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; diff -c -r src.old/SecurityServer/Authorization/Authorization.cpp src/SecurityServer/Authorization/Authorization.cpp *** src.old/SecurityServer/Authorization/Authorization.cpp Wed Dec 18 22:26:20 2002 --- src/SecurityServer/Authorization/Authorization.cpp Wed Dec 18 22:26:13 2002 *************** *** 151,156 **** --- 151,157 ---- END_API(CSSM) } + #include // // Get session information *************** *** 161,173 **** { BEGIN_API SecuritySessionId sid = session; server().getSessionInfo(sid, *attributes); if (sessionId) *sessionId = sid; ! END_API(CSSM) } - // // Create a new session // --- 162,191 ---- { BEGIN_API SecuritySessionId sid = session; + syslog(7,"SessionGetInfo(), entering"); server().getSessionInfo(sid, *attributes); + syslog(7,"SessionGetInfo(), session id is 0x%.8X, " + "attributes are 0x%.8X",sid,*attributes); if (sessionId) *sessionId = sid; ! //END_API(CSSM) ! } ! catch (const CssmCommonError &err) { ! syslog(7,"SessionGetInfo(), CssmCommonError error is 0x%.8X", ! err.cssmError(CSSM_CSSM_BASE_ERROR)); ! return err.cssmError(CSSM_CSSM_BASE_ERROR); ! } ! catch (const std::bad_alloc &) { ! syslog(7,"SessionGetInfo(), memory error"); ! return CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_CSSM_BASE_ERROR); ! } ! catch (...) { ! syslog(7,"SessionGetInfo(), unknown error"); ! return CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_CSSM_BASE_ERROR); ! } ! return CSSM_OK; } // // Create a new session // *************** *** 175,180 **** --- 193,200 ---- SessionAttributeBits attributes) { BEGIN_API + syslog(7,"SessionCreate(), called with flags = 0x%.8X, attrs = 0x%.8X", + flags,attributes); // unless the (expert) caller has already done so, create a sub-bootstrap and set it // note that this is inherently thread-unfriendly; we can't do anything about that *************** *** 182,193 **** Bootstrap bootstrap; if (!(flags & sessionKeepCurrentBootstrap)) { TaskPort self; bootstrap = bootstrap.subset(TaskPort()); self.bootstrap(bootstrap); } // now call the SecurityServer and tell it to initialize the (new) session server().setupSession(flags, attributes); ! ! END_API(CSSM) } --- 202,231 ---- Bootstrap bootstrap; if (!(flags & sessionKeepCurrentBootstrap)) { TaskPort self; + syslog(7,"SessionCreate(), before bootstrap.subset(TaskPort())"); bootstrap = bootstrap.subset(TaskPort()); self.bootstrap(bootstrap); + syslog(7,"SessionCreate(), after self.bootstrap(bootstrap)"); } // now call the SecurityServer and tell it to initialize the (new) session server().setupSession(flags, attributes); ! syslog(7,"SessionCreate(), succeeded"); ! ! //END_API(CSSM) ! } ! catch (const CssmCommonError &err) { ! syslog(7,"SessionCreate(), CssmCommonError error is 0x%.8X", ! err.cssmError(CSSM_CSSM_BASE_ERROR)); ! return err.cssmError(CSSM_CSSM_BASE_ERROR); ! } ! catch (const std::bad_alloc &) { ! syslog(7,"SessionCreate(), memory error"); ! return CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_CSSM_BASE_ERROR); ! } ! catch (...) { ! syslog(7,"SessionCreate(), unknown error"); ! return CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_CSSM_BASE_ERROR); ! } ! return CSSM_OK; } diff -c -r src.old/SecurityServer/connection.h src/SecurityServer/connection.h *** src.old/SecurityServer/connection.h Wed Dec 18 22:26:21 2002 --- src/SecurityServer/connection.h Wed Dec 18 22:26:13 2002 *************** *** 48,53 **** --- 48,54 ---- virtual ~Connection(); void terminate(); // normal termination bool abort(bool keepReplyPort = false); // abnormal termination + bool safeToDelete() { return ((state==idle) && !agentWait); } Port clientPort() const { return mClientPort; } diff -c -r src.old/SecurityServer/main.cpp src/SecurityServer/main.cpp *** src.old/SecurityServer/main.cpp Wed Dec 18 22:26:21 2002 --- src/SecurityServer/main.cpp Wed Dec 18 22:26:14 2002 *************** *** 130,136 **** Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_PERROR); Syslog::notice("SecurityServer started in debug mode"); } else { ! Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_CONS); } // if we're not running as root in production mode, fail --- 130,137 ---- Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_PERROR); Syslog::notice("SecurityServer started in debug mode"); } else { ! //Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_CONS); ! Syslog::open(bootstrapName, LOG_AUTH, LOG_CONS); // For debugging only } // if we're not running as root in production mode, fail diff -c -r src.old/SecurityServer/process.h src/SecurityServer/process.h *** src.old/SecurityServer/process.h Wed Dec 18 22:26:22 2002 --- src/SecurityServer/process.h Wed Dec 18 22:26:14 2002 *************** *** 63,68 **** --- 63,69 ---- void beginConnection(Connection &); bool endConnection(Connection &); bool kill(); + bool safeToDelete() { return (mBusyCount == 0); } void addDatabase(Database *database); void removeDatabase(Database *database); diff -c -r src.old/SecurityServer/server.cpp src/SecurityServer/server.cpp *** src.old/SecurityServer/server.cpp Wed Dec 18 22:26:22 2002 --- src/SecurityServer/server.cpp Wed Dec 18 22:26:14 2002 *************** *** 177,191 **** // // Synchronously end a Connection. // This is due to a request from the client, so no thread races are possible. // void Server::endConnection(Port replyPort) { StLock _(lock); Connection *connection = connections[replyPort]; ! assert(connection); connections.erase(replyPort); connection->terminate(); delete connection; } --- 177,207 ---- // // Synchronously end a Connection. // This is due to a request from the client, so no thread races are possible. + // (Still, only end the connection (and delete its object) if it's safe to do + // so. And if it's safe to delete its associated process (and the process's + // associated session), do that, too. This makes it possible for the client + // to later make another connection and call SessionCreate() without getting + // an error because the previous session still exists.) // void Server::endConnection(Port replyPort) { StLock _(lock); + syslog(7,"Server::endConnection(), entering"); Connection *connection = connections[replyPort]; ! if (!connection || !connection->safeToDelete()) ! return; connections.erase(replyPort); + syslog(7,"Server::endConnection(), before connection->terminate()"); connection->terminate(); + Process *process = &connection->process; + syslog(7,"Server::endConnection(), before delete connection"); delete connection; + if (!process || !process->safeToDelete()) + return; + processes.erase(replyPort); + syslog(7,"Server::endConnection(), before delete process"); + delete process; + syslog(7,"Server::endConnection(), done"); } diff -c -r src.old/SecurityServer/ssclient.cpp src/SecurityServer/ssclient.cpp *** src.old/SecurityServer/ssclient.cpp Wed Dec 18 22:26:22 2002 --- src/SecurityServer/ssclient.cpp Wed Dec 18 22:26:14 2002 *************** *** 38,50 **** ModuleNexus ClientSession::mGlobal; bool ClientSession::mSetupSession; const char *ClientSession::mContactName; // // Construct a client session // ClientSession::ClientSession(CssmAllocator &std, CssmAllocator &rtn) ! : internalAllocator(std), returnAllocator(rtn) { } --- 38,51 ---- ModuleNexus ClientSession::mGlobal; bool ClientSession::mSetupSession; const char *ClientSession::mContactName; + bool ClientSession::mTeardownBeforeSessionSetup; // // Construct a client session // ClientSession::ClientSession(CssmAllocator &std, CssmAllocator &rtn) ! : internalAllocator(std), returnAllocator(rtn), mProcessId(NULL) { } *************** *** 61,72 **** --- 62,89 ---- // void ClientSession::activate() { + pid_t currentProcessId = getpid(); + // If the process id has changed (for example because we are a child + // process spawned by fork() or exec()) and we inherited a connection from + // our parent, the server and reply ports in mGlobal will be invalid and + // the connection we inherited will no longer work. So clean out mGlobal + // to make its constructor (mGlobal(), whose code is in ClientSession:: + // Global::Global() below) reinitialize it and give us a new connection + // and new ports. But don't do this if mGlobal.reset() has already been + // called in ClientSession::setupSession(). + if (!mSetupSession && mProcessId && (mProcessId!=currentProcessId)) { + syslog(7,"SSclnt, pid was 0x%.8X, is now 0x%.8X, so calling mGlobal.reset()", + mProcessId, currentProcessId); + mGlobal.reset(); + } + mProcessId = currentProcessId; Global &global = mGlobal(); Thread &thread = global.thread(); if (!thread) { // first time for this thread - use abbreviated registration IPCN(ucsp_client_setup(UCSP_ARGS, mach_task_self(), "")); thread.registered = true; + mTeardownBeforeSessionSetup = true; global.serverPort.requestNotify(thread.replyPort, MACH_NOTIFY_DEAD_NAME, true); debug("SSclnt", "Thread registered with %s", mContactName); } *************** *** 106,111 **** --- 123,129 ---- mContactName = SECURITYSERVER_BOOTSTRAP_NAME; serverPort = Bootstrap().lookup(mContactName); debug("SSclnt", "contacting %s at port %d", mContactName, serverPort.port()); + syslog(7,"SSclnt, contacting %s at port %d", mContactName, serverPort.port()); // send identification/setup message string extForm; *************** *** 119,138 **** } // cannot use UCSP_ARGS here because it uses mGlobal() -> deadlock Thread &thread = this->thread(); ! if (mSetupSession) { debug("SSclnt", "sending session setup request"); mSetupSession = false; IPCN(ucsp_client_setupNew(serverPort, thread.replyPort, &rcode, mach_task_self(), extForm.c_str(), &serverPort.port())); debug("SSclnt", "new session server port is %d", serverPort.port()); } else { IPCN(ucsp_client_setup(serverPort, thread.replyPort, &rcode, mach_task_self(), extForm.c_str())); } thread.registered = true; // as a side-effect of setup call above serverPort.requestNotify(thread.replyPort, MACH_NOTIFY_DEAD_NAME, true); debug("SSclnt", "contact with %s established", mContactName); } --- 137,159 ---- } // cannot use UCSP_ARGS here because it uses mGlobal() -> deadlock Thread &thread = this->thread(); ! if (mSetupSession) { debug("SSclnt", "sending session setup request"); mSetupSession = false; IPCN(ucsp_client_setupNew(serverPort, thread.replyPort, &rcode, mach_task_self(), extForm.c_str(), &serverPort.port())); debug("SSclnt", "new session server port is %d", serverPort.port()); + syslog(7,"SSclnt, new session server port is %d", serverPort.port()); } else { IPCN(ucsp_client_setup(serverPort, thread.replyPort, &rcode, mach_task_self(), extForm.c_str())); } thread.registered = true; // as a side-effect of setup call above + mTeardownBeforeSessionSetup = true; serverPort.requestNotify(thread.replyPort, MACH_NOTIFY_DEAD_NAME, true); debug("SSclnt", "contact with %s established", mContactName); + syslog(7,"SSclnt, contact with %s established", mContactName); } diff -c -r src.old/SecurityServer/ssclient.h src/SecurityServer/ssclient.h *** src.old/SecurityServer/ssclient.h Wed Dec 18 22:26:22 2002 --- src/SecurityServer/ssclient.h Wed Dec 18 22:26:14 2002 *************** *** 316,321 **** --- 316,323 ---- static ModuleNexus mGlobal; static bool mSetupSession; static const char *mContactName; + static bool mTeardownBeforeSessionSetup; + pid_t mProcessId; }; diff -c -r src.old/SecurityServer/sstransit.cpp src/SecurityServer/sstransit.cpp *** src.old/SecurityServer/sstransit.cpp Wed Dec 18 22:26:22 2002 --- src/SecurityServer/sstransit.cpp Wed Dec 18 22:26:15 2002 *************** *** 586,591 **** --- 586,599 ---- void ClientSession::setupSession(SessionCreationFlags flags, SessionAttributeBits attrs) { + // If a connection already exists, so does a session (it may be the root + // session). In this case we need to tear down the existing connection + // (and session) before we can create a new one. + if (mTeardownBeforeSessionSetup) { + syslog(7,"ClientSession::setupSession(), before ucsp_client_teardown()"); + IPC(ucsp_client_teardown(UCSP_ARGS)); + syslog(7,"ClientSession::setupSession(), after ucsp_client_teardown()"); + } mSetupSession = true; // global flag to Global constructor mGlobal.reset(); // kill existing cache, all threads IPC(ucsp_client_setupSession(UCSP_ARGS, flags, attrs)); diff -c -r src.old/cdsa/cdsa_utilities/mach++.cpp src/cdsa/cdsa_utilities/mach++.cpp *** src.old/cdsa/cdsa_utilities/mach++.cpp Wed Dec 18 22:26:17 2002 --- src/cdsa/cdsa_utilities/mach++.cpp Wed Dec 18 22:26:09 2002 *************** *** 48,55 **** case MIG_SERVER_DIED: return CSSM_ERRCODE_SERVICE_NOT_AVAILABLE; default: ! return CSSM_ERRCODE_INTERNAL_ERROR; ! } } OSStatus --- 48,55 ---- case MIG_SERVER_DIED: return CSSM_ERRCODE_SERVICE_NOT_AVAILABLE; default: ! return error; // Don't return CSSM_ERRCODE_INTERNAL_ERROR here -- ! } // that breaks all IPC error reporting! } OSStatus diff -c -r src.old/cdsa/cdsa_utilities/threading.cpp src/cdsa/cdsa_utilities/threading.cpp *** src.old/cdsa/cdsa_utilities/threading.cpp Wed Dec 18 22:26:17 2002 --- src/cdsa/cdsa_utilities/threading.cpp Wed Dec 18 22:26:09 2002 *************** *** 38,43 **** --- 38,50 ---- { if (int err = pthread_key_create(&mKey, destructor)) UnixError::throwMe(err); + // If we are a child process spawned by fork() or exec(), the thread-local + // storage pointed to by the key we just created may already contain a + // non-NULL value -- one set by a thread in our parent process before it + // called fork() or exec()! So we need to initialize our thread-local + // storage. + if (int err = pthread_setspecific(mKey, NULL)) + UnixError::throwMe(err); } ThreadStoreSlot::~ThreadStoreSlot()